CMake应该如何为共享库工作?

x8diyxa7  于 2022-11-29  发布在  其他
关注(0)|答案(1)|浏览(136)

我试图弄清楚CMake应该如何为共享库工作。我创建了一个共享库,如下所示:
(in /mdp_opt/CMakeLists.txt:)

add_library (mdp_opt SHARED librarycomponent.cpp)

现在,测试可执行文件使用此库:
/test/CMakeLists.txt:)

add_executable (test test.cpp)

target_link_libraries(test PRIVATE mdp_opt)

如果库被标记为STATIC(而不是上面的SHARED),我可以cmake-〉built(在Visual Studio下)并成功运行可执行文件。当它被标记为SHARED(如上面的),我需要做两件事。第一件事,添加:

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

这是好的。但是,现在它仍然只有当我复制文件mdp_opt.dllbuild/x64-debug/mdp_optbuild/x64-debug/test的工作。* 但我不明白为什么需要这样做?*
在《专业CMake》一书中,我读到:
链接库
此目标属性包含目标应直接链接到的所有库的列表。创建目标时,它最初为空,并且支持生成器表达式。支持关联的接口属性INTERFACE_LINK_LIBRARIES。列出的每个库都可以是以下库之一(强调我的):
·库的路径,通常指定为绝对路径。
·只有库名称,没有路径,通常也没有任何特定于平台的文件名前缀(例如lib)或后缀(例如. a,. so,. dll)。
·CMake库目标的名称。**在生成链接器命令时,CMake会将其转换为已构建库的路径,包括为文件名提供适合平台的任何前缀或后缀。**因为CMake代表项目处理所有各种平台差异和路径,所以使用CMake目标名称通常是首选方法。
我的印象是

target_link_libraries(test PRIVATE mdp_opt)

表示我打算将与目标mdp_opt相关的输出与测试可执行文件链接起来?而且,在我阅读上述书籍摘录时,我的理解是.dll的位置将转换为路径?如果这种转换的目的不是以某种方式告诉可执行文件在哪里可以找到共享库,那么这种转换是为了什么?
基本上,谁能告诉我CMake应该如何为共享库工作,为什么是这样工作的?是否真的需要手动后拷贝(可能通过CMake指令),以及最适合这个场景(开发时的中间构建)?

qxsslcnc

qxsslcnc1#

在Windows上,您需要导出共享库的符号,或者添加一个链接器选项来导出符号;否则就不会生成用于链接dll的.lib文件。

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

,请使用__declspec( dllexport )或类似命令。
另一个问题是windows定位dll的方式:基本上,它首先搜索包含可执行文件的目录,然后通过PATH环境变量继续搜索。这可能导致在运行时定位dll时出现问题。
您可以通过在生成第一个相关目标之前设置放置运行时工件的目录来避免此问题:

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
...

add_library(mdp_opt ...)

...

add_executable(test ...)

或者,您可以只变更vs调试工具可见的环境变量:

set_target_properties(test PROPERTIES VS_DEBUGGER_ENVIRONMENT "PATH=$<TARGET_FILE_DIR:mdp_opt>;$ENV{PATH}")

如果您使用CTest,测试也有一个类似的属性:ENVIRONMENT
如果[target_link_libraryes]的目的不是以某种方式告诉可执行文件在哪里可以找到共享库,那么转换的目的是什么?
您仍然需要链接一个dll,或者更准确地说是相应的导入库;这就是target_link_libraries所做的,除了添加构建系统依赖项,转移一些属性(例如,包括具有PUBLIC可见性的目录)等。

相关问题