Warning This is a beta release of the Viam C++ SDK. Stability is not guaranteed. Breaking changes are likely to occur, and occur often.
The viam-cpp-sdk
has a newly introduced CMake build system to
replace the existing Makefile infrastructure. This document explains
how to use the new infrastructure.
If you experience problems while following this guide, please see the
Limitations, Known Issues, and Troubleshooting
section at the bottom
to see if your issue (and hopefully a workaround) is covered there.
PLEASE NOTE: It is very likely that you will need to rebuild the
generated sources as part of building the SDK. Please see the
documentation on VIAMCPPSDK_USE_DYNAMIC_PROTOS
below, and the
additional comments about mismatched protobufs in the troubleshooting
guide, before continuing further.
The project depends on CMake >= 3.25, Boost >= 1.74, gRPC >= 1.30.2, protobuf >= 3.12.4, xtensor >= 0.24.3, abseil and on the transitive dependencies of those projects.
You will need to install these required dependencies before building the Viam C++ SDK, preferably by way of your system package manager:
- Debian:
apt-get install cmake build-essential libabsl-dev libboost-all-dev libgrpc++-dev libprotobuf-dev libxtensor-dev
- MacOS with Homebrew:
brew install abseil cmake boost grpc protobuf xtensor
There are also several optional or conditionally required dependencies:
- Debian:
apt-get install pkg-config ninja-build protobuf-compiler-grpc
- MacOS with Homebrew:
brew install pkg-config ninja buf
The pkg-config
dependency is needed if your local system does not
provide CMake find_package
support for one or more required
dependencies like gRPC
.
The ninja[-build]
dependency is only required if you want to use
Ninja as the target build system, so is entirely optional.
You will need protobuf-compiler-grpc
if you intend to do local
dynamic protobuf generation (see the relevant SDK options below) or if
your local gRPC version is too old to be used with buf.build
(effectively, older than gRPC 1.41).
Installing the buf
homebrew package will save you from needing to
download it as part of the build, which costs a little time on every
build invocation.
Note that Debian Bullseye does not ship a recent enough version of CMake by default, but it can be obtained from the Bullseye Backports repository:
apt-get install software-properties-common
apt-add-repository 'deb http://deb.debian.org/debian bullseye-backports main'
apt-get update
apt-get install -t bullseye-backports cmake
You can of course build and install any or all of these requirements manually rather than via your package manager, though this is likely to make it more difficult to correctly configure the build of the Viam C++ SDK.
Just clone https://github.com/viamrobotics/viam-cpp-sdk into a directory of your choice and checkout the branch or tag of interest.
This document doesn't intend to provide a complete guide for how CMake
is used, as that is a complex topic. Please consult the CMake
documentation for
specific details on how CMake works and how to invoke the tool. The
guidance here is intended to cover the common case builds of the
viam-cpp-sdk
.
CMake organizes out-of-tree builds. The first step is to create a
scratch directory where you want to keep the working state of your
build. A convention is to name this directory build
and to create it
under the root of the project. The viam-cpp-sdk
top-level
.gitignore
file already ignores such a directory, so we recommend
starting there:
git clone https://github.com/viamrobotics/viam-cpp-sdk
cd viam-cpp-sdk
mkdir build
cd build
CMake isn't itself a build system, it is a build system generator. Our next step is to generate the build system. In these examples we use Ninja, but you can also use Makefiles or many other build systems.
When invoking CMake, you pass the path to the root CMakeLists.txt
file for the project you wish to build. If you have opted to use an
in-tree build
directory per the above instructions, this is as
simple as:
cmake .. -G Ninja
If all went well, you should now have a file named build.ninja
in
the build
directory created above. Note that git status
will not
show this, since the build
directory is ignored.
If you wish to use a different generator than Ninja, change the
argument to -G
above to the build system you wish to generate for.
To compile all targets in the SDK:
ninja all
To install the SDK:
ninja install
By default, the build is configured to install the SDK to the
install
subdirectory of the working directory, so if you have been
following the instructions above and the build worked, you should see
an installation tree under build/install
.
If the build did not succeed, please see the next section.
A frequent cause of difficulty or failure is an inability for the
build to find a third-party dependency like gRPC
. If the build
fails, first check if you have installed the right dependencies per
the lists above. In some cases, you may find that a necessary direct
or transitive dependency has been installed, but to a location that
CMake does not search by default.
On Homebrew, OpenSSL does not get installed in the default search
paths because it is "keg-only". We can inform CMake of the actual
install location by customizing PKG_CONFIG_PATH
in the shell
environment before invoking CMake:
PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@3/lib/pkgconfig" cmake ...
CMake also has its own intrinsic package search mechanism. If you have
dependencies installed to locations that are not part of CMake's
default search set, you can add them by configuring
CMAKE_PREFIX_PATH
as an argument to CMake. For instance, if you have
a personal tree of installed software in $HOME/opt
, you can inform
CMake that this path should be searched for packages by passing it as
a command line "define" to CMake:
cmake -DCMAKE_PREFIX_PATH=$HOME/opt ...
Please see
CMAKE_PREFIX_PATH
for more details on CMAKE_PREFIX_PATH
.
By default, the SDK will install into a subdirectory of the working
build directory. This is not appropriate for making the SDK available
for other projects. To install the SDK to a location of your choice
you should customize CMAKE_INSTALL_PREFIX
while invoking CMake
and
then re-run the install
task. For instance, to install the SDK to
/usr/local
:
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ...
ninja install
By default, the SDK build will enforce compiler minima. If you must bypass this check for some reason, you may do so by disabling this default-on option:
cmake -DVIAMCPPSDK_ENFORCE_COMPILER_MINIMA=OFF ...
Because the checked-in copies of generated sources only work with a narrow range of gRPC versions, the SDK by default will dynamically regenerate proto code. If you wish to test against the checked-in copies or cannot regenerate for any reason, you can do so by disabling this flag:
cmake -DVIAMCPPSDK_USE_DYNAMIC_PROTOS=OFF ...
By default, the SDK will use local buf services and definitions to generate code. It is possible to instead rely on buf.build services to do code generation (note that this requies online access):
cmake -DVIAMCPPSDK_OFFLINE_PROTO_GENERATION=OFF ...
Note that this option only has an effect when
VIAMCPPSDK_USE_DYNAMIC_PROTOS=ON
.
The Viam C++ SDK installs support files for CMake's find_package
subsystem.
find_package(viam-cpp-sdk CONFIG REQUIRED COMPONENTS Lib)
target_link_libraries(mytarget viam-cpp-sdk::viamcpp)
Note that you will need to ensure that CMAKE_PREFIX_PATH
is set
appropriately in your project to include the path to the installed
Viam C++ SDK.
An example project using this technique is available under
examples/project/cmake
and it can be built with CMake in the regular
way. If you have allowed the SDK to install to the default
build/install
prefix, the example should build against your SDK
installation automatically. If you have customized the SDK
installation prefix by building it with a specific
CMAKE_INSTALL_PREFIX
that is not among CMake's default package
search list (e.g. $HOME/opt
), you will need to pass that information
along when building the example:
cd examples/project/cmake
mkdir build
cd build
cmake .. -DCMAKE_PREFIX_PATH=<path/to/which/the/sdk/was/installed> ...
Consuming the SDK via CMake is the preferred mechanism and likely to give the best results.
The Viam C++ SDK also installs .pc
files to introspect the SDK with
pkg-config
. An example project using make
and pkg-config
is
available under examples/project/pkg-config
. Much like with the need
to customize the CMake prefix path, you may need to customize
PKG_CONFIG_PATH
in order to find a Viam C++ SDK installation that is
not part of pkg-config
's default search list:
cd examples/project/pkg-config
PKG_CONFIG_PATH=<path/to/which/the/sdk/was/installed>/lib/pkgconfig make ...
It is of course possible to build against the Viam C++ SDK without
using either CMake support or pkg-config
by explicitly setting
toolchain include paths, library paths, and passing -lviamcpp
or
similar on the link line.
Sometimes when running ninja all
or ninja install
in a project
using -DVIAMCPPSDK_USE_DYNAMIC_PROTOS=ON
the build will fail because
generated sources have not yet been produced. If that happens you can
explicitly run the ninja generate-dynamic-protos
command to ensure
that they are pre-populated.
cmake -DVIAMCPPSDK_USE_DYNAMIC_PROTOS=ON ...
ninja all # FAILS!
ninja generate-dynamic-protos
nina all # OK!
If compilation fails with a wall of compiler-generated errors that includes text like:
error: incompatible with your Protocol Buffer headers
then there is likely a mismatch between your local protobuf/gRPC version and the version used to generate the checked-in files. Switch to using dynamic proto generation:
cmake ...
ninja all # FAILS, wall of compiler text with above message
cmake -DVIAMCPPSDK_USE_DYNAMIC_PROTOS=ON ...
ninja all # OK!
For some platforms (mostly macOS) the runtime and install name
properties are not correctly configured for the viam_rust_utils
library. This can lead to a runtime error where the viam_rust_utils
shared library is not found at program startup. If this happens, set
[DY]LD_LIBRARY_PATH
to point into the library directory of the
installation when running commands that require it:
cmake ...
ninja install
./build/install/bin/example_echo # FAILS: libviam_rust_utils not found
export DYLD_LIBRRAY_PATH=./build/install/lib
./build/install/bin/example_echo # OK!
If you are having trouble getting the SDK installed or your project built against it and running, please take advantage of our community resources.
Copyright 2023 Viam Inc.
Apache 2.0 - See LICENSE file