【问题标题】:Cmake Commandline parameters only - Linking external library using仅 Cmake 命令行参数 - 使用链接外部库
【发布时间】:2021-12-17 08:23:45
【问题描述】:

我是 Cmake 和学习的新手。我正在使用 Ubuntu 20

我不允许更改 CMakeLists.txt 文件。我正在尝试使用 -DIMPORTED_LOCATION=/home/map/third_party 来链接位于用户定义位置而不是默认位置的外部库(libdlt.so)。但是使用此命令,我收到以下错误

/usr/bin/ld: cannot find -ldlt
collect2: error: ld returned 1 exit status

您能否帮助澄清为什么它不选择此参数?如果此库(libdlt.so)位于默认位置(/etc/local/lib),则 CMake 工作正常。

谢谢

【问题讨论】:

  • "请您帮忙解释一下为什么它没有选择这个参数?" - 您设置了名为 IMPORTED_LOCATION 的 变量,但库的位置由 目标属性 IMPORTED_LOCATION 确定。在 CMake 中,变量和属性是不同的东西。并非所有东西都可以从命令行进行配置。如果 CMakeLists.txt 通过名称链接到 dlt 库,则无法通过命令行影响该库的位置。

标签: c++ cmake cmakelists-options


【解决方案1】:

你不能只使用命令行参数来做到这一点。

IMPORTED_LOCATION 是目标属性。这意味着它只有在将其应用于 CMake 目标时才对 CMake 有意义。

CMake 中的依赖项通常通过导入的目标进行管理,该目标具有IMPORTED_LOCATION 属性。

应该是这样的:

find_path(DLT_INCLUDE_DIRECTORY dlt/dlt.h)
find_library(DLT_LIBRARY NAMES dlt)

add_library(dlt::dlt IMPORTED)
set_target_properties(dlt::dlt PROPERTIES
    IMPORTED_LOCATION ${DLT_LIBRARY}
    INTERFACE_INCLUDE_DIRECTORIES ${DLT_INCLUDE_DIRECTORY}
)

# then, later in your CMake scripts...

target_link_libraries(yourExecutable PUBLIC dlt::dlt)

你首先找到路径。包括目录和库路径。

然后,您创建一个导入的目标并将路径设置为其属性。

然后使用正确的前缀路径调用 CMake,以便 find_* 命令在正确的目录中搜索:

cmake .. -DCMAKE_PREFIX_PATH=/home/map/third_party

现在正如您在 cmets 中提到的,您无法更改 CMakeLists 文件。

如果您使用的库包含这个损坏的 CMake 脚本,我建议您分叉它并修复他们的 CMake 文件,使其不被硬编码。

如果您坚持不修改 CMake 文件,您可以做几件事。

您可以创建自己的CMakeLists.txt,然后使用它。是的,你可以这样做!它是 hackish,但允许您拥有一个可修改的 CMakeLists.txt,您可以修复它的行为。

为不可修改的项目创建一个兄弟目录,并在其中添加一个CMakeLists.txt和一个build/目录。

在那些 CMake 中,使用这样的相对路径:

add_library(yourlib STATIC)
target_sources(yourlib ../yourproject/file1.cpp ../yourproject/file2.cpp)

然后,使用正确的find_XXX 函数,以便 CMake 有机会找到正确的库而不是硬编码路径。


还有另一种 hack,但它更 hackish。

您可以将 CMake 使用的链接程序替换为带有命令行参数的自定义链接程序:

cmake .. -DCMAKE_LINKER=/path/to/linker -DCMAKE_CXX_LINK_EXECUTABLE="<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>"

您可以将/path/to/linker 替换为一个脚本,该脚本将用好的标志替换硬编码的标志。

这是 非常 hackish。预计事情会中断或行为不正确。


如果您无法创建单独的 CMakeLists 脚本并且替换链接程序也不是一种选择,那么您可以进行另一种 hack。这是令人难以置信的hackish,难以创建,难以维护,初学者不友好的解决方案,而且非常脆弱并且很容易损坏。

我必须警告你,这比将补丁应用到第三方库要糟糕得多,而且这比创建自己的 CMake 脚本要糟糕得多。我不会向任何人推荐它。它还处理 CMake 最糟糕的部分。

您可以使用带有CMAKE_PROJECT_INCLUDE 的cmd 在脚本中注入CMake 文件:

cmake .. -DCMAKE_PROJECT_INCLUDE=myfile.cmake

myfile.cmake,可以写cmake代码。

此时,您可以使用宏修补 CMake 内置命令以捕获不需要的行为并将其替换为想要的行为。

macro(link_libraries)
    # find and replace in ARGV
endmacro()

如果您无法编写 CMake 文件替换 CMake 命令,我将假设您的文件系统是不可变的,并且您的错误无法修复;)

【讨论】:

  • 如果不允许修改 CMakeLists.txt,是否可以使用环境变量进行任何变通?
  • 如果您无法更改的 CMake 列表足以使用 find_XXX,那么在 cmd 中添加前缀路径就可以了。如果这是因为您的依赖,我会建议分叉并修复他们的 CMake 文件。阅读错误,他们似乎已经对链接标志进行了硬编码。这意味着您的环境必须像硬编码一样固定。
  • @user1833852 我添加了您可以执行的破解和补丁列表。他们都不会解决问题,但可能会使事情暂时正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
相关资源
最近更新 更多