如何解决Yocto配方中std::atomic相关的链接器错误
问题:Yocto构建含std::atomic的源码包时链接器错误
初始错误现象
构建时出现链接器未定义引用错误,具体日志:
/opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/bar/git-r0/recipe-sysroot-native/usr/bin/x86_64-poky-linux/../../libexec/x86_64-poky-linux/gcc/x86_64-poky-linux/11.2.0/ld: src/CMakeFiles/FooImpl.dir/xxx.cpp.o: in function `std::atomic<xxx_handle>::load(std::memory_order) const': /usr/include/c++/11.2.0/atomic:285: undefined reference to `__atomic_load_16' /opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/bar/git-r0/recipe-sysroot-native/usr/bin/x86_64-poky-linux/../../libexec/x86_64-poky-linux/gcc/x86_64-poky-linux/11.2.0/ld: src/CMakeFiles/FooImpl.dir/xxx.cpp.o: in function `std::atomic<xxx_handle>::store(xxx_handle, std::memory_order)': /usr/include/c++/11.2.0/atomic:271: undefined reference to `__atomic_store_16' /opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/bar/git-r0/recipe-sysroot-native/usr/bin/x86_64-poky-linux/../../libexec/x86_64-poky-linux/gcc/x86_64-poky-linux/11.2.0/ld: /usr/include/c++/11.2.0/atomic:271: undefined reference to `__atomic_store_16' /opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/bar/git-r0/recipe-sysroot-native/usr/bin/x86_64-poky-linux/../../libexec/x86_64-poky-linux/gcc/x86_64-poky-linux/11.2.0/ld: /usr/include/c++/11.2.0/atomic:271: undefined reference to `__atomic_store_16' /opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/bar/git-r0/recipe-sysroot-native/usr/bin/x86_64-poky-linux/../../libexec/x86_64-poky-linux/gcc/x86_64-poky-linux/11.2.0/ld: src/CMakeFiles/FooImpl.dir/xxx.cpp.o: in function `std::atomic<xxx_handle>::load(std::memory_order) const': /usr/include/c++/11.2.0/atomic:285: undefined reference to `__atomic_load_16'
尝试的配方修改
查阅资料得知需添加-latomic链接参数,于是修改Yocto配方:
SUMMARY = "FooImpl" DESCRIPTION = "FooImpl Recipe" LICENSE = "CLOSED" DEPENDS = "fooInterface googletest framework" SRC_URI = "git://FooImpl;protocol=ssh;branch=mainline;" SRCREV = "yyyy" S = "${WORKDIR}/git" inherit cmake TARGET_LDFLAGS += " -latomic " LDFLAGS += " -latomic " TARGET_CFLAGS += " -march=native " CFLAGS += " -march=native "
后续更新信息
- 构建日志显示
-latomic和-march=native参数已被传递,但链接错误仍存在:
[buildfarm-ssh] l/git-r0=/usr/src/debug/fooimpl/git-r0 -fdebug-prefix-map=/opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/fooimpl/git-r0/recipe-sysroot= -fdebug-prefix-map=/opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/fooimpl/git-r0/recipe-sysroot-native= -latomic -Wl,-z,relro,-z,now -latomic -Wl,-zdefs -Wl,-zrelro -Wl,-znow -Wl,--whole-archive,/opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/fooimpl/git-r0/fooimpl-git/src/libFooInterface.a,--no-whole-archive -T/opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/fooimpl/git-r0/recipe-sysroot/usr/share/ff/ff.ld -shared -Wl,-soname,libFooImpl.so -o src/libFooImpl.so src/CMakeFiles/FooImpl.dir/xxx.cpp.o src/CMakeFiles/FooImpl.dir/discovery_ipc.cpp.o -Wl,-rpath,"\$APMF-/opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/fooimpl/git-r0/fooimpl-git/_ff_components:" src/libFooInterface.a /opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/fooimpl/git-r0/recipe-sysroot/usr/lib/libip.so.0.1.0 /opt/workspace/foo/build-sim-debug/tmp/work/core2-64-poky-linux/fooimpl/git-r0/recipe-sysroot/usr/lib/libff.so && : FAILED: src/libFooImpl.so
- 直接在源码的
CMakeLists.txt中给target_link_libraries添加atomic即可正常构建,但希望通过Yocto配方实现该修改,避免改动源码。 - 源码中
FooImpl/src/CMakeLists.txt的关键内容:
set(lib FooImpl) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_CXX_STANDARD 17) find_package(xxx CONFIG REQUIRED) add_library(${lib} SHARED yyy.cpp zzz.cpp ) target_include_directories(${lib} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(${lib} PUBLIC FooInterface xxx) # 添加atomic此处可正常构建
解决方案
方法1:通过EXTRA_OECMAKE传递CMake链接器参数
在Yocto配方中,删除原来的TARGET_LDFLAGS和LDFLAGS设置,改用EXTRA_OECMAKE向CMake传递链接参数:
inherit cmake EXTRA_OECMAKE += " -DCMAKE_SHARED_LINKER_FLAGS='${CMAKE_SHARED_LINKER_FLAGS} -latomic' " TARGET_CFLAGS += " -march=native " CFLAGS += " -march=native "
原理:CMake在生成共享库的链接命令时,会优先使用CMAKE_SHARED_LINKER_FLAGS中的参数,并且会将其放在正确的链接顺序位置,确保-latomic能正确解析依赖的符号。
方法2:通过配方修改CMakeLists.txt(备选方案)
如果无法通过CMake变量解决,可以在配方中添加预配置步骤,自动修改源码的CMakeLists.txt:
do_configure_prepend() { sed -i 's/target_link_libraries(${lib} PUBLIC FooInterface xxx)/target_link_libraries(${lib} PUBLIC FooInterface xxx atomic)/' ${S}/src/CMakeLists.txt }
原理:在配置阶段开始前,通过sed命令修改源码中的target_link_libraries行,添加atomic库依赖,效果和手动修改一致。
为什么直接设置LDFLAGS无效?
链接库的顺序对链接器至关重要,依赖库需要放在引用它的目标文件之后。直接在配方中设置LDFLAGS会让-latomic被放在链接命令的前面,而CMake生成的链接命令中,目标文件和依赖库在后面,导致链接器无法找到__atomic_load_16等符号。而通过CMake的target_link_libraries或CMAKE_SHARED_LINKER_FLAGS设置,能保证-latomic出现在正确的位置,从而解决未定义引用问题。
内容的提问来源于stack exchange,提问作者bourne
相关产品推荐
相关产品推荐

