C++ CMake仅通过名称链接的可传递依赖项
在C++ CMake仅通过名称链接的可传递依赖项,c++,xcode,cmake,linker,clang,C++,Xcode,Cmake,Linker,Clang,在target\u link\u库中直接链接的dylib似乎是通过绝对路径链接的,但是那些通过CMake-target依赖关系传递进来的dylib正在删除绝对路径并只按名称链接。这破坏了MacOS fixup捆绑包的功能,该功能通常会对.app目录进行后期处理,以重新定位的方式包含库,因为它找不到动态库 例如,我依赖于DCMTK,而DCMTK本身也依赖于libicu。DCMTK由CMake为静态链接构建,因此它有一个目标配置文件,并按绝对路径列出对libicu动态库的依赖关系: $ grep l
target\u link\u库中直接链接的dylib似乎是通过绝对路径链接的,但是那些通过CMake-target依赖关系传递进来的dylib正在删除绝对路径并只按名称链接。这破坏了MacOS fixup捆绑包的功能,该功能通常会对.app
目录进行后期处理,以重新定位的方式包含库,因为它找不到动态库
例如,我依赖于DCMTK,而DCMTK本身也依赖于libicu。DCMTK由CMake为静态链接构建,因此它有一个目标配置文件,并按绝对路径列出对libicu动态库的依赖关系:
$ grep libicu DCMTKTargets-release.cmake
IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "/usr/local/app-libs/icu-67.1/lib/libicuuc.dylib;/usr/local/app-libs/icu-67.1/lib/libicudata.dylib;pthread"
这里是一个要复制的最小CMake,尽管您当然需要在显示的路径中为动态链接构建libicu
,为静态链接构建DCMTK
CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(CatalinaTest)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "" FORCE)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_OSX_SYSROOT})
list(APPEND CMAKE_PREFIX_PATH
/usr/local/app-libs/vscdcmtk-3.6.3/lib/cmake/dcmtk
)
find_package(LibXml2 REQUIRED)
find_package(DCMTK REQUIRED CONFIG)
add_executable(CatalinaTest main.cpp)
target_link_libraries(CatalinaTest
${LIBXML2_LIBRARIES}
ofstd
)
运行的链接器命令是:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -target x86_64-apple-macos10.14 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -L/Users/jake/devel/cmake-test.build/Release -F/Users/jake/devel/cmake-test.build/Release -filelist /Users/jake/devel/cmake-test.build/CatalinaTest.build/Release/CatalinaTest.build/Objects-normal/x86_64/CatalinaTest.LinkFileList -Wl,-search_paths_first -Wl,-headerpad_max_install_names /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/lib/libxml2.tbd /usr/local/app-libs/vscdcmtk-3.6.3/lib/libofstd.a /usr/local/app-libs/icu-67.1/lib/libicuuc.dylib /usr/local/app-libs/icu-67.1/lib/libicudata.dylib -lpthread -Xlinker -dependency_info -Xlinker /Users/jake/devel/cmake-test.build/CatalinaTest.build/Release/CatalinaTest.build/Objects-normal/x86_64/CatalinaTest_dependency_info.dat -o /Users/jake/devel/cmake-test.build/Release/CatalinaTest
因此,它在同一节中通过绝对路径传递直接依赖项和传递依赖项,而不需要任何其他链接器修改标志。现在,在链接的可执行文件中:
$ otool -L Release/CatalinaTest
Release/CatalinaTest:
/usr/lib/libxml2.2.dylib (compatibility version 10.0.0, current version 10.9.0)
libicuuc.67.dylib (compatibility version 67.0.0, current version 67.1.0)
libicudata.67.dylib (compatibility version 67.0.0, current version 67.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 902.1.0)
我们可以看到libxml2
的dylib具有绝对路径,但是libicu
的两个dylib没有。尽管本例中有一个tbd
文件用于libxml2
,但如果我们使用另一个直接传递dylib
的库,行为是相同的。区别似乎在于所有间接/传递的动态库都是名称,而所有直接的动态库都是绝对路径
造成这种差异的原因是什么?我如何让可传递的dylib通过完整路径链接,以便bundle后处理可以按预期进行?您是否可以尝试使用“otool-l”,看看是否有RPATH条目?由于路径可以重写,您是否“进行安装”?或者您是否使用了set(CMAKE\u BUILD\u WITH\u INSTALL\u RPATH TRUE)
?您还可以尝试使用set\u target\u properties(target properties INSTALL\u RPATH“@loader\u path”
要获取可执行文件中的一些相对路径无rpath条目。您可以在上面看到我的test CMakeLists.txt,那里没有rpath指令。我没有使用安装
目标,我在构建目录中的可执行文件上运行了otool。otool
只显示了otool
: