You cross-compile a 3D camera SDK for an ARM controller and the build stops at the generate step: Boost::system and Boost::program_options are not defined, even though the configure log says Boost was found. This failure pairs an older host CMake with a newer Boost — the classic case is a Buildroot toolchain carrying CMake 3.8.2 against Boost 1.64. The SDK links imported targets that this FindBoost never creates for a Boost release past the end of its version table. Below: the diagnosis in order of probability, the variable-based fix as a patch you can carry in Buildroot or Yocto, and when to patch versus move the toolchain forward. The whole fix is one link line per module.
The symptom: configure passes, generation fails
The configure stage finds Boost and prints the version, so the failure looks contradictory. It comes one stage later: when CMake generates the build files it resolves every item in target_link_libraries, and Boost::system with its double colon must be a target. No such target exists on this toolchain, so generation stops on every module that links it. In the SDK that fails this way, three module CMakeLists carry one such line each — the frame grabber module, the protocol client module, and the command-line tools — so the fix touches three lines in three files.
The ARM architecture is not the cause. ARM changes the compiler and the sysroot, not CMake's Boost module, and the same source builds on a desktop with a current CMake. ARM builds that fail for binary or architecture reasons look different, as ARM64 machine vision acquisition: fix the binary layer shows.
Why Boost 1.64 breaks CMake 3.8.2
FindBoost is version-driven. It maps Boost releases to library file names from a table inside the module, and it creates the Boost::<component> imported targets only for releases that table recognizes. The overhauled module in CMake 3.9 extended the table and made the targets dependable; CMake 3.8.2 predates that overhaul, and Boost 1.64 sits past the end of its list. Headers and libraries still resolve — the result variables are set — but the targets are skipped, and every Boost:: name then fails at generation.
Boost's own header encodes the release number that FindBoost compares against the table:
The sysroot reports 106400, FindBoost 3.8.2 has no entry covering it, and the imported-target path is never built. The per-component variables — Boost_SYSTEM_LIBRARY, Boost_PROGRAM_OPTIONS_LIBRARY — are set whatever the table says, and that is the hook the fix uses.
Three checks that confirm the cause
- Run
cmake --versionfrom the toolchain's host tools — the binary that runs configure, which in Buildroot is the host CMake the build system built. This toolchain reports 3.8.2. Anything below 3.9 takes the imported-target route off the table for a Boost this new. - Add one diagnostic line just after the SDK's
find_package(Boost ...)call:message(STATUS "boost system: ${Boost_SYSTEM_LIBRARY}"). A non-empty path proves headers and libraries resolved and only the targets are missing. - Grep the sources for the target names:
grep -R 'Boost::' modules/. Every hit is a link line to convert; in this SDK the grep returns three files with one hit each.
If check 2 prints empty, the cause is one of two others. Either the find_package(Boost ...) call names no components — then neither targets nor variables exist, and the call must read find_package(Boost REQUIRED COMPONENTS system program_options) — or only the Boost headers landed in the sysroot, in which case select Boost with its built libraries in the build system's package configuration. For tracing deeper dependency failures, CMake missing dependency diagnostics for vision builds covers the same toolchain from the CMake side.
The fix: link the variables FindBoost always sets
Replace each imported target with the per-component result variable, which every FindBoost version sets after the components resolve. Here vision_sdk_module stands for the SDK's own library target:
# before — requires imported targets from a newer FindBoost
target_link_libraries(vision_sdk_module PRIVATE
Boost::system
Threads::Threads
)
# after — the per-component variable, set on old and new CMake alike
target_link_libraries(vision_sdk_module PRIVATE
${Boost_SYSTEM_LIBRARY}
Threads::Threads
)
Make the same substitution in each module. In the tools module the line names Boost::program_options; replace it with ${Boost_PROGRAM_OPTIONS_LIBRARY}. The pattern is Boost_<COMPONENT>_LIBRARY for every component the SDK links.
Include directories travel with an imported target and not with a bare variable, so the SDK must add Boost_INCLUDE_DIRS itself; the one failing here already does. If your fork trimmed that, add it back with target_include_directories.
Prove the fix: re-run the cross-configure and build. The generate step that stopped before now completes, and each module's link.txt under CMakeFiles in the build tree carries the sysroot's libboost_system instead of an unresolved Boost:: name.
Carry it as a patch, not a hand edit
In Buildroot, place the patch file in the package's patch directory or under the global patch directory you configured; the build system then applies it every time it extracts the sources. In Yocto, write a .bbappend for the SDK recipe that adds the patch file to SRC_URI. Pin the SDK release in the same layer: a version bump then fails loudly at patch application instead of building unpatched sources in silence. The same pinning discipline across build stages is what Docker build SDK version mismatch: pin one library version everywhere walks through for container builds.
One CMakeLists for old and new toolchains
When the SDK must also build on desktop CI with a current CMake, keep both spellings behind a version guard:
if(CMAKE_VERSION VERSION_LESS 3.9)
set(SDK_LINK_BOOST_SYSTEM ${Boost_SYSTEM_LIBRARY})
else()
set(SDK_LINK_BOOST_SYSTEM Boost::system)
endif()
target_link_libraries(vision_sdk_module PRIVATE
${SDK_LINK_BOOST_SYSTEM}
Threads::Threads
)
CMAKE_VERSION reports the running CMake — 3.8.2 on the Buildroot host, 3.9 or newer on the desktop — and SDK_LINK_BOOST_SYSTEM is this example's variable name; take it into the SDK's own namespace. Set it once in the top-level CMakeLists after find_package and reference it from every module.
Or move the toolchain forward instead
The patch treats the symptom; a newer host CMake removes the cause. CMake 3.9 overhauled FindBoost for modern Boost releases, Boost 1.70 began shipping its own CMake package configuration file, and CMake 3.15 prefers that file when present. A toolchain refresh that lands on Boost 1.70 or newer with CMake 3.15 or newer stops seeing this failure class entirely.
Bumping the compiler or core libraries in a validated toolchain carries its own bill: rebuilt dependencies and ABI boundaries to re-check, as computer vision library ABI integration across toolchains sets out. ARM container builds hit the neighbouring failure mode — find_package resolution — covered in Docker builds for arm64: fix find_package dependencies.
Decision: patch or upgrade
| Situation | Do this |
|---|---|
| Toolchain pinned by a vendor or a validated release (CMake 3.8.2, Boost 1.64) | Apply the variable patch and carry it in your patch directory |
| You own the Yocto layer and can rebase packages | Move host CMake to 3.9 or newer, keeping Boost and CMake in step |
| One source tree must build on old ARM toolchains and desktop CI | Use the CMAKE_VERSION guard in every module |
| A toolchain refresh is planned anyway | Target Boost 1.70 or newer with CMake 3.15 or newer |
Once it links: the sensor and the host port
The SDK exists to drive a sensor, and for profile scanning that is a laser profiler from the 3D sensors range; the camera finder filters by type and series. One safety note first: laser profilers are class-labelled lasers, so follow the class marking on the sensor and never stare into the projected line.
The camera link is GigE, so the ARM controller needs a PoE port for the sensor. A card such as the MV-GE2002P gives the camera that port and leaves a spare for service traffic. When a sensor needs more bandwidth, the frame grabbers range steps up through 10GigE and CoaXPress via the accessories finder.
- Interface
- GigE
- Ports
- 2 ports
After the build, keep camera firmware and SDK versions aligned; the runtime failure when they drift is the subject of 3D camera header version mismatch: fix firmware and SDK alignment. More sensor-side set-up lives on the 3D topic page.
Checklist before the next rebuild
- Host CMake version logged —
cmake --versionfrom the toolchain's host tools; 3.8.2 in this build. - Boost release logged from the sysroot — 1.64, encoded as 106400 in the header.
- Patch filed against the pinned SDK tag and applied by the build system.
- Each module's link.txt resolves libboost_system out of the sysroot.
- Desktop CI and the ARM build agree through the CMAKE_VERSION guard.
- The Boost and CMake pair recorded in the layer so the toolchain is reproducible.
If the toolchain is vendor-pinned and you want a second opinion on the patch, send the version triple — host CMake, Boost release, SDK tag — through the contact page.
Questions
Why does the same SDK build fine on the desktop but fail on ARM?
The failing component is not the ARM target but the host CMake running configure. A desktop CMake is typically 3.9 or newer, whose overhauled FindBoost creates Boost::system and Boost::program_options; the Buildroot toolchain's host CMake 3.8.2 stops before Boost 1.64 in its version table, so the targets are never defined and generation fails. Same sources, different CMake behavior.
Is ${Boost_SYSTEM_LIBRARY} worse than the Boost::system target?
No. Both name the same library file in the sysroot; the target simply wraps it with include-directory usage requirements. With the variable, include paths must come from Boost_INCLUDE_DIRS where the SDK consumes Boost headers, and the failing SDK already does that. The link result is identical, and it works on toolchains where the targets never exist.
Should I patch the SDK or upgrade CMake?
Patch when the toolchain is pinned by a platform vendor or a validated release you cannot touch: the change is one link line per module and rides in your patch directory or .bbappend. Upgrade host CMake to 3.9 or newer when you own the layer, because that deletes this failure class instead of carrying a patch against every SDK release.
How do I keep one CMakeLists working on old and new CMake?
Wrap the choice in a version guard: when CMAKE_VERSION reports less than 3.9, set the link item to ${Boost_SYSTEM_LIBRARY}, otherwise to Boost::system, then reference the variable in target_link_libraries. Repeat the guard in each module, or set the variable once in the top-level CMakeLists after find_package, so desktop CI and the ARM toolchain build from one tree.
Will my patch survive an SDK update?
Only if the build system applies it: a patch file applied at extract time, placed in the package's patch directory or your global patch directory in Buildroot, or added to SRC_URI through a .bbappend in Yocto. Pin the SDK release tag in the same layer, so a version bump fails loudly at patch application instead of silently building unpatched sources.
