Windows上的Cmake没有添加共享库路径(在Linux上可以工作)

10

我已经在Linux上使用CMake和Eclipse一段时间了,并且一直在处理包含多个可执行文件和共享对象的项目。

我使用独立于源代码的构建方式,而在Linux上,二进制文件被放置在它们自己的目录中。当我在Linux上这样做时,Eclipse可以找到共享对象并正常运行可执行文件,但是在Windows上这种情况不会发生。

在Windows上,我不得不添加一个指向dll的PATH环境变量,或者将其构建到单个bin和lib目录中(尽管过去我忘记了与CMake相关的问题使我想避免这样做)。

为什么在Windows上和Linux上的工作方式不同?是否缺少某些设置或者这在Windows上不起作用?

构建本身完全正常。我正在使用MinGW、Eclipse Kepler和Windows 7 64位。

提前感谢。

3个回答

11

对于Windows而言,它没有一些必要的概念来允许CMake设置你的构建环境。在链接时,Windows会在与二进制文件相同的目录中查找,然后搜索你PATH中的目录。没有像大多数Unix平台上使用的RPATH这样的东西,可以注入其他更合适的路径。DLL应该通常与你的二进制文件一起安装在同一个目录中。

在我看来,在Windows上最佳实践是将DLL放在二进制文件旁边。CMake试图让这变得更加容易,

install(TARGETS MyTarget
  EXPORT "MyProjectTargets"
  RUNTIME DESTINATION "${INSTALL_RUNTIME_DIR}"
  LIBRARY DESTINATION "${INSTALL_LIBRARY_DIR}"
  ARCHIVE DESTINATION "${INSTALL_ARCHIVE_DIR}")

会将DLL安装到运行时目录,但将库文件放在库目标中。这意味着通常在类Unix操作系统中,lib包含共享对象,但CMake知道DLL实际上是运行时的,应该放在bin目录中。希望这样更清楚了解这个问题。对于CMake / Eclipse来说,除了在从Eclipse运行时注入额外的目录(不确定是否可能)之外,真的很难有所改进。

如果您担心构建树,则可以像下面的评论中建议的那样使用以下方法:

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

如果您希望允许这些被覆盖(可能很有用),那么它们也应该由 if(NOT var_name) 块进行保护。


1
是的,那就是我当时发现的。我曾经考虑过Eclipse对PATH进行注入,但我认为它不可能这样做,因为它需要解释Makefile,而且可能并非所有构建的可执行文件都需要构建所有库,所以会变得混乱。我目前不使用install,因为我没有需要。也许我需要研究一下。我想我之前使用过CMAKE_RUNTIME_OUTPUT_DIRECTORY和它的朋友们,但在某个时候,当CMake似乎迷失了二进制文件的位置时,它会导致CMake崩溃,所以我停止了使用。 - Matt_JD
1
我通过设置以下内容解决了这个问题。它类似,但不需要安装:set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $ {CMAKE_BINARY_DIR} / bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY $ {CMAKE_BINARY_DIR} / lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY $ {CMAKE_BINARY_DIR} / lib) - Matt_JD
是的,如果您正在使用构建树,则他们是完全正确的。我将更新答案以包括构建树的变体。这是我们在几个项目中使用的方法,效果很好。 - Marcus D. Hanwell

2

这只是对我自己问题的可能答案。我认为在 Linux 上,rpath 被用来标识依赖库的位置,但在使用 mingw 的 Windows 上,我无法使用 elf 解析器,因此无法使用 rpath。


0

感谢大家的问题和回答。我只想总结一下关于 Windows 支持需要做什么:

请在 根目录CMakeLists.txt 中添加以下代码:

# Common output directory is required for OS without rpath support.
set (CMAKE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/result")
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_OUTPUT_DIRECTORY})
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_OUTPUT_DIRECTORY})
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_OUTPUT_DIRECTORY})

你需要为每个"add_test"添加工作目录。
add_test (
  NAME ${TEST_NAME}
  COMMAND ${TEST_TARGET}
  WORKING_DIRECTORY ${CMAKE_OUTPUT_DIRECTORY}
)

请注意,TEST_TARGET 应在当前项目内唯一。
我使用这种方法为 lzws 库添加了 Windows 支持。您可以随时检出源代码并澄清剩余的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接