【问题标题】:Set linker search path for build in CMake为 CMake 中的构建设置链接器搜索路径
【发布时间】:2016-06-21 07:10:18
【问题描述】:

似乎这个问题以前经常被问到,但似乎没有一个解决方案适用于我的情况。

我在 CMake/Linux 环境中,必须在 build 步骤中运行可执行二进制文件(尤其是protoc)。

此二进制文件需要一个库,但它未安装(也不能)在标准目录(如/usr)中,因此无法找到该库。

很遗憾,我无法操纵 protoc 调用,因为它嵌入在第 3 方脚本中。

我现在可以在每个 make 之前设置 LD_LIBRARY_PATH 或在系统范围内设置它,但这非常不方便,尤其是在涉及进行构建的 IDE 或具有连续构建环境的分布式构建场景时。

我尝试通过

设置LD_LIBRARY_PATH
set(ENV{LD_LIBRARY_PATH} "/path/to/library/dir")

但这似乎在构建步骤中没有效果。

所以我的问题是:我可以在 CMake 中设置在构建期间使用的库搜索路径吗?

【问题讨论】:

  • 这个stackoverflow.com/a/30455909可以帮助你吗?
  • 不幸的是,库和可执行文件都在其他地方构建。
  • 也许,找到了一种方法:尝试添加到您的 Cmake 脚本中:execute_process(COMMAND export LD_LIBRARY_PATH="/path/to/library/dir:$LD_LIBRARY_PATH") 希望,Cmake 将在子 shell/当前 shell 中启动您的第 3 方脚本 - 然后 export 会影响它.
  • can I set a library search path in CMake which is used during the build? - 如果链接器调用不受 CMake 控制,那么获得正确的库搜索路径的唯一方法是设置相应的环境变量。通过set() 在 CMake 中设置环境变量不会影响 build 步骤。可以通过调用 3d-party 脚本来设置环境,但这取决于你如何调用它。

标签: linux linker cmake executable


【解决方案1】:

试试这个

SET(ENV{LD_LIBRARY_PATH} "/path/to/library/dir:$ENV{LD_LIBRARY_PATH}")

我也使用了这个肮脏的技巧来临时更改一些环境变量:

LD_LIBRARY_PATH="/path/to/library/dir:$LD_LIBRARY_PATH" cmake ...

执行此行后LD_LIBRARY_PATH在当前shell中没有改变。

另外,在调用cmake 之前更改LD_LIBRARY_PATH 也不错: export LD_LIBRARY_PATH=...

它不会改变系统范围内的任何东西,但它会用于您当前的 shell,当前的构建过程。 CI 构建也是如此。您可以保存变量并在cmake 调用后恢复它:

MY_LD=$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=...
cmake...
export LD_LIBRARY_PATH=$MY_LD

【讨论】:

  • 我在我的问题中写了这个 - 我误解你了吗? :)
  • 注意,我在右侧添加了$ENV{LD_LIBRARY_PATH}。 :)
  • 哦,试试大符号SET。您拥有的最大符号 ;)
  • 好吧,CMake 命令不区分大小写,而且 - 我想我也说过 - 在运行 make 之前我无法设置环境变量,因为 make 步骤发生在我没有的环境中轻松访问。所以我必须改变我的环境inside CMake,它不仅要适用于配置,还要适用于构建步骤。
  • 对不起,如果SET 只影响configure 阶段,我不知道怎么做inside Cmake。但我建议改用 2 种修改 LD_LIBRARY_PATH 的方法(与 cmake 在同一行,在 cmake 之前)。这对我来说很方便,但对你却不方便。抱歉,害怕,我只能建议了。
【解决方案2】:

我最近遇到了一个类似的问题。 我的解决方案是在每个命令中合并一个设置适当环境的文件。 例如,这个自定义命令:

add_custom_command(
    OUTPUT some_output
    COMMAND some_command
    ARGS some_args
    DEPENDS some_dependencies
    COMMENT "Running some_command some_args to produce some_output"
    )

会变成:

set(my_some_command_with_environment "source my_environment_script.sh && some_command")
add_custom_command(
    OUTPUT some_output
    COMMAND bash
    ARGS -c "${my_some_command_with_environment} some_args"
    DEPENDS some_dependencies
    COMMENT "Running some_command some_args to produce some_output"
    VERBATIM
    )

显然,这有一些缺点:

  • 它依赖于可用的 bash shell。

  • 它为每个命令调用(性能问题)提供环境脚本,您必须更改依赖该环境变量的所有命令调用。

  • 它改变了让命令跟随 COMMAND 而参数跟随 ARGS 的正常语法,因为现在“真实”命令是 ARGS 的一部分。

事实证明,我的 CMake-Fu 不足以找到语法上更好的方法,但也许有人可以评论更好的方法。

【讨论】:

    【解决方案3】:

    对于第三方库提供的可执行文件,我遇到了类似的问题。该二进制文件与发行版未提供的库链接,但所需的库包含在第三方库的 libs 目录中。

    所以运行LD_LIBRARY_PATH=/path/to/thirdparty/lib /path/to/thirdparty/bin/executable 有效。但是包配置脚本没有设置可执行文件来搜索 /path/to/thirdparty/lib 以查找依赖于运行时的文件,因此当 CMake 尝试运行可执行文件时,CMake 会抱怨。

    我通过配置引导脚本并用配置的引导脚本替换 IMPORTED_LOCATION 属性来解决这个问题。

    _thirdpartyExe.in
    #!/bin/bash
    LD_LIBRARY_PATH=@_thirdpartyLibs@ @_thirdpartyExe_LOCATION@ "$@"
    
    CMakeLists.txt
    find_package(ThirdPartyLib)
    get_target_property(_component ThirdPartyLib::component LOCATION)
    get_filename_component(_thirdpartyLibs ${_component} DIRECTORY)
    get_target_property(_thirdpartyExe_LOCATION ThirdPartyLib::exe IMPORTED_LOCATION)
    configure_file(
      ${CMAKE_CURRENT_LIST_DIR} _thirdpartyExe.in
      ${CMAKE_BINARY_DIR}/thirdpartyExeWrapper @ONLY
    )
    set_target_properties(ThirdPartyLib::exe PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/thirdpartyExeWrapper)
    

    老实说,在我修复第三方库本身之前,我认为这是一个临时的权宜之计。但据我尝试,这似乎适用于我投入的所有 IDE,Eclipse、VSCode、Ninja、QtCreator 等

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-05
      • 2022-12-10
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      相关资源
      最近更新 更多