CMake命令target_link_libraries链接库的顺序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMake命令target_link_libraries链接库的顺序相关的知识,希望对你有一定的参考价值。

参考技术A target_link_libraries( hello
android_ABI/liba.a
ANDROID_ABI/libb.a
ANDROID_ABI/libc.a
ANDROID_ABI/libd.a
$log-lib )

需要把被依赖的库放在依赖的库后面

CMake交叉编译目标rpath

【中文标题】CMake交叉编译目标rpath【英文标题】:CMake cross compile target rpath 【发布时间】:2015-08-04 16:37:34 【问题描述】:

我正在使用 CMake 进行交叉编译。

在我的 CMakeLists.txt 中(用于编译和交叉编译):

set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
find_package(foo REQUIRED)
add_library(mylib SHARED $SRCS)
target_link_libraries(mylib $FOO_LIBRARIES)

在我的 toolchain.cmake 中:

set(CMAKE_CXX_FLAGS "... --sysroot=/path/to/sysroot/ ... ")
set(CMAKE_CXX_LINK_FLAGS "... --sysroot=/path/to/sysroot/ ... )
...
set(CMAKE_FIND_ROOT_PATH /path/to/sysroot)

考虑 foo 位于 /path/to/sysroot/usr/local/lib/foo.so,当我为 mylib/path/to/sysroot/usr/local/lib

我希望运行时路径是 /usr/local/lib 以反映我的目标文件系统。

如果不在我的 CMakelists.txt 中定义硬编码的 CMAKE_INSTALL_RPATH 变量,我怎么能做到这一点?

编辑:我使用 /usr/local/lib 作为示例,但 foo lib 位于不属于系统目录的特定文件夹中:/path/to/sysroot/usr /local/share/mypackage/lib/foo.so

【问题讨论】:

【参考方案1】:

您只需要:

set(CMAKE_BUILD_RPATH "/my/libs/location")

指定运行时路径 (RPATH) 条目以添加到构建树中链接的二进制文件(对于支持它的平台)。这些条目不会用于安装树中的二进制文件。另请参阅 CMAKE_INSTALL_RPATH 变量。

【讨论】:

【参考方案2】:

查看CMake RPATH handling 上的 wiki。

默认情况下,CMake 使用指向主机系统库位置 (/crosssdk/sysroot/usr/lib/) 的 RPATH 编译您的可执行文件,然后(我相信)在安装时(即 make install)它会编辑可执行文件中的 RPATH 以替换它与适当的目标 RPATH (/usr/lib 或任何你有它)。我认为这个想法是,您可以更改共享库并在主机系统上执行输出,而无需每次都安装共享库和可执行文件。 就我而言,我的主机是 x86,目标是 ARM,所以我告诉 CMake 将构建 RPATH 设置为与安装 RPATH 相同:

set_target_properties(mytarget PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)

【讨论】:

这个想法不能在我的情况下使用,因为我的库与位于非标准位置的其他库链接。所以,除了 /usr/local/lib 之外,我还需要将 rpath 设置为额外的位置。 由于它是一个非标准位置,您必须将路径设置为库somewhere。在目标系统上设置 LD_LIBRARY_PATH 可能是一种解决方案。【参考方案3】:

我不确定您使用的是哪个交叉编译工具链。

您需要指定 C/CXX 编译器、链接器等。 除此之外,一些重要的变量是 CMAKE_FIND_ROOT_PATH_MODE_LIBRARY 和 CMAKE_FIND_ROOT_PATH_MODE_INCLUDE。如果您将它们设置为“ONLY”,当您调用 FindXXX() 时,搜索只会在目标根文件系统目录中进行,而不是在构建机器中进行。

在我的例子中,我不必指定 sysroot,因为交叉编译器已经知道它是交叉编译,并且它还知道目标根文件系统的位置。

使用这个工具链文件,我只需编译源代码而不需要任何额外的标志,在目标上加载可执行文件,它运行良好,直接从正确的路径获取 *.so 文件。

试一试,告诉我进展如何。

这是我的工具链文件:

set(ELDK_DIR /opt/eldk/ppc-v42-1)


set (CMAKE_C_COMPILER $ELDK_DIR/usr/bin/ppc_6xx-gcc)
set (CMAKE_CXX_COMPILER $ELDK_DIR/usr/bin/ppc_6xx-g++)
set (CMAKE_LINKER $ELDK_DIR/usr/bin/ppc_6xx-ld CACHE STRING "Set the cross-compiler tool LD" FORCE)
set (CMAKE_AR $ELDK_DIR/usr/bin/ppc_6xx-ar CACHE STRING "Set the cross-compiler tool AR" FORCE)
set (CMAKE_NM $ELDK_DIR/usr/bin/ppc_6xx-nm CACHE STRING "Set the cross-compiler tool NM" FORCE)
set (CMAKE_OBJCOPY $ELDK_DIR/usr/bin/ppc_6xx-objcopy CACHE STRING "Set the cross-compiler tool OBJCOPY" FORCE)
set (CMAKE_OBJDUMP $ELDK_DIR/usr/bin/ppc_6xx-objdump CACHE STRING "Set the cross-compiler tool OBJDUMP" FORCE)
set (CMAKE_RANLIB $ELDK_DIR/usr/bin/ppc_6xx-ranlib CACHE STRING "Set the cross-compiler tool RANLIB" FORCE)
set (CMAKE_STRIP $ELDK_DIR/usr/bin/ppc_6xx-strip CACHE STRING "Set the cross-compiler tool RANLIB" FORCE)

# Target environment
set (CMAKE_FIND_ROOT_PATH $ELDK_DIR/ppc_6xx)

# Don't search for programs in the host environment
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# Search for the libraries and headers in the target environment
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

【讨论】:

我的工具链文件定义了编译器等...我的代码比我的工具链文件短。控制 findXXX 命令的 Cmake 变量已正确设置为您的。我除了你没有链接到不在你的 sysroot 的默认系统文件夹中的共享库,这就是你的 rpath 设置正确的原因,因为 CMake 没有改变(你的 rpath 是系统目录)

以上是关于CMake命令target_link_libraries链接库的顺序的主要内容,如果未能解决你的问题,请参考以下文章

cmake set命令

Cmake知识整理

如何捕获 CMake 命令行参数?

使用CMake组织C++工程2:CMake 常用命令和变量

向 CMake 添加命令行选项

cmake 在Windows 命令行怎么指定编译器