0

我是 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 工作正常。

谢谢 <

4

1 回答 1

0

您不能仅使用命令行参数来执行此操作。

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,然后使用它。是的,你可以这么做!它是骇人听闻的,但允许你有一个可修改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为将硬编码标志替换为好的脚本的脚本。

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


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

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

您可以使用以下命令在脚本中注入 CMake 文件CMAKE_PROJECT_INCLUDE

cmake .. -DCMAKE_PROJECT_INCLUDE=myfile.cmake

myfile.cmake中,可以编写 cmake 代码。

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

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

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

于 2021-11-02T22:09:23.213 回答