我们使用CMake在SVN中生成源代码的Visual Studio文件。现在我的工具需要一些DLL文件与可执行文件位于同一文件夹中。 DLL文件位于源旁边的文件夹中。
如何更改CMakeLists.txt
以使生成的Visual Studio项目在发布/调试文件夹中已经包含特定的DLL文件,或者在编译时将其复制?
答案 0 :(得分:107)
我会使用add_custom_command
与cmake -E copy_if_different...
一起实现这一目标。完整信息运行
cmake --help-command add_custom_command
cmake -E
所以在你的情况下,如果你有以下目录结构:
/CMakeLists.txt
/src
/libs/test.dll
以及该命令适用的CMake目标是MyTest
,然后您可以将以下内容添加到CMakeLists.txt:
add_custom_command(TARGET MyTest POST_BUILD # Adds a post-build event to MyTest
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..."
"${PROJECT_SOURCE_DIR}/libs/test.dll" # <--this is in-file
$<TARGET_FILE_DIR:MyTest>) # <--this is out-file path
如果您只想复制/libs/
目录的全部内容,请使用cmake -E copy_directory
:
add_custom_command(TARGET MyTest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/libs"
$<TARGET_FILE_DIR:MyTest>)
如果您需要根据配置(Release,Debug等)复制不同的dll,那么您可以在具有相应配置命名的子目录中使用这些dll:/libs/Release
和/libs/Debug
。然后,您需要将配置类型注入add_custom_command
调用中dll的路径,如下所示:
add_custom_command(TARGET MyTest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/libs/$<CONFIGURATION>"
$<TARGET_FILE_DIR:MyTest>)
答案 1 :(得分:17)
我把这些行放在我的顶级CMakeLists.txt文件中。由CMake编译的所有库和可执行文件都将放在构建目录的顶层,以便可执行文件可以找到库并且很容易运行所有库。
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
请注意,这并不能解决OP从项目源目录复制预编译二进制文件的问题。
答案 2 :(得分:7)
今天,当我尝试制作程序的Windows版本时遇到了这个问题。我最终自己做了一些研究,因为所有这些答案都使我不满意。主要存在三个问题:
我希望将调试版本与库的调试版本链接 和发布版本与库的发布版本相关联,
除此之外,我还想要正确版本的DLL文件 (调试/发布)复制到输出目录。
我想在不编写复杂而脆弱的脚本的情况下实现所有这些目标。
在github上浏览了一些CMake手册和一些多平台项目之后,我找到了这个解决方案:
使用“导入”属性将您的库声明为目标,引用其调试并释放.lib和.dll文件。
add_library(sdl2 SHARED IMPORTED GLOBAL)
set_property(TARGET sdl2 PROPERTY IMPORTED_IMPLIB_RELEASE "${SDL_ROOT_PATH}/lib/SDL2.lib")
set_property(TARGET sdl2 PROPERTY IMPORTED_LOCATION_RELEASE "${SDL_ROOT_PATH}/bin/SDL2.dll")
set_property(TARGET sdl2 PROPERTY IMPORTED_IMPLIB_DEBUG "${SDL_ROOT_PATH}/lib/SDL2d.lib")
set_property(TARGET sdl2 PROPERTY IMPORTED_LOCATION_DEBUG "${SDL_ROOT_PATH}/bin/SDL2d.dll")
通常将此目标与您的项目链接
target_link_libraries(YourProg sdl2 ...)
如果自上次构建以来已对其进行了某些更改,则执行自定义构建步骤以将dll文件复制到其目标位置
add_custom_command ( TARGET YourProg POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:sdl2> $<TARGET_FILE_DIR:YourProg>
)
答案 3 :(得分:5)
接受答案的附录,作为单独的答案添加,以便我获得代码格式:
如果要在同一个项目中构建dll,它们通常位于Release,Debug等目录中。您必须使用Visual Studio环境变量来正确复制它们。 e.g:
"${PROJECT_BINARY_DIR}/your_library/\$\(Configuration\)/your_library.dll"
代码来源和
"${CMAKE_CURRENT_BINARY_DIR}/\$\(Configuration\)/your_library.dll"
目的地。注意逃避!
您不能将CMake CMAKE_BUILD_TYPE变量用于配置,因为它在VS项目生成时解析,并且始终是默认值。
答案 4 :(得分:2)
这对其中一个很有用
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
${PROJECT_SOURCE_DIR}/lib CACHE
PATH "Directory where all the .lib files are dumped." FORCE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY
${PROJECT_SOURCE_DIR}/bin CACHE
PATH "Directory where .exe and .dll files are dumped." FORCE)
答案 5 :(得分:1)
您可能需要add custom target并使其依赖于您的某个可执行目标。要使用上述功能复制文件,请使用
COMMAND ${CMAKE_PROGRAM} -E copy_if_different ${CMAKE_BINARY_DIR}/path/to/file.dll ${CMAKE_BINARY_DIR}/where/to/put/file.dll
。
答案 6 :(得分:0)
我是CMake的初学者,但我仍然想分享自己的经验。就我而言,我需要安装后的副本,以便将所有二进制文件都放入其中。 对于可以在CMake中导入的第三方二进制文件,以下对我有用:
find_package( dependency REQUIRED )
if( MSVC )
# If done properly and if the dependency has a correct config file, IMPORTED_LOCATION_RELEASE should be defined
get_target_property( DEP_SHARED_LIB_PATH dependency IMPORTED_LOCATION_RELEASE )
# Create a bin directory in the install folder
add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_INSTALL_PREFIX}/bin/)
# Copy the shared lib file
add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${DEP_SHARED_LIB_PATH} ${CMAKE_INSTALL_PREFIX}/bin/)
endif()
很明显,IMPORTED_LOCATION_RELEASE可以具有变体,具体取决于构建/安装共享库的方式。可能是IMPORTED_LOCATION_DEBUG。
我不知道,也许有更好的方法来获取该属性名称。
答案 7 :(得分:0)
install
在尝试遵循Step 9上的CMake官方教程时遇到了这个问题。这是我要移动的文件的位置:
src
|_build
|_Debug
- `MathFunctions.dll`
这是我希望文件所在的位置:
src
|_build
|_install
|_bin
- `MathFunctions.dll`
由于此DLL是作为共享库生成的,所以我要做的就是将此行包含在包含库{{1}的源代码的子目录中的CMakeLists.txt
中}
src/Mathfunctions/CMakeLists.txt
感谢您的回答,我可以考虑一下。只是一行而已,所以我认为还可以。根据项目的构建方式,install(FILES ${PROJECT_BINARY_DIR}/$<CONFIG>/MathFunctions.dll
DESTINATION bin)
可以具有两个值 Debug 或 Release ,作为原始问题。
答案 8 :(得分:0)
当前评分最高的答案中的以下命令取决于放入 /libs/ 中的输出。
add_custom_command(TARGET MyTest POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/libs/$<CONFIGURATION>"
$<TARGET_FILE_DIR:MyTest>)
我使用以下命令进行复制,这对我在任何地方都适用。请注意,我在这里只复制了输出 dll,而不是整个目录。另请注意,我正在硬编码一个特定于该项目的目标 /bin/ 目录。但我想分享 $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>/$<TARGET_FILE_NAME:${CMAKE_PROJECT_NAME}>
语法,我认为它很简洁:
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>/$<TARGET_FILE_NAME:${CMAKE_PROJECT_NAME}>
${CMAKE_CURRENT_SOURCE_DIR}/bin/$<TARGET_FILE_NAME:${CMAKE_PROJECT_NAME}>)
答案 9 :(得分:-1)
您还可以使用命令find_library:
find_library(<some_var> NAMES <name_of_lib> PATHS "<path/to/lib>")
使用定义的EXECUTABLE_PATH,例如:
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
您可以使用
移动可执行文件所需的.dll文件file(COPY ${<some_var>}
DESTINATION ${EXECUTABLE_OUTPUT_PATH})