仅限 Cmake 命令行参数 - 使用链接外部库

Cmake Commandline parameters only - Linking external library using

我是 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是一个目标属性。这意味着它只有在将其应用于 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

现在正如您在评论中提到的,您无法更改 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 使用的 link 程序替换为带有命令行参数的自定义程序:

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 替换为脚本,该脚本会将硬编码标志替换为正确的标志。

非常 骇人听闻。预计事情会破裂或行为不正确。


如果您无法创建单独的 CMakeLists 脚本并且替换 link 程序也不是一个选项,那么您可以使用另一种 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 命令,我会假设您的文件系统是不可变的并且您的错误无法修复;)