CMake post build步骤:根据visual studio配置复制多个文件

时间:2015-12-25 19:48:19

标签: c++ windows visual-studio-2010 cmake

我正在尝试编写一个CMakeLists.txt作为构建后事件的副本,需要dlls从外部库到构建后可执行文件所在的文件夹。我正在研究的操作系统是Win7和VS2010。

有很多外部库,所以我不想在CMakeLists.txt中单独列出它们。我目前的解决方案是使用文件通配并为每个库创建一个后期构建事件:

FILE(GLOB files "${LIBRARY_DIR}/lib/$(ConfigurationName)/*dll")
MESSAGE("FILE LIST IS: ${files}")
FOREACH(file ${files})
    ADD_CUSTOM_COMMAND(
        TARGET mylib
        POST_BUILD
        COMMENT "Copying dll ${file}..."
        COMMAND ${CMAKE_COMMAND} -E copy ${file} "${CMAKE_BINARY_DIR}/$(ConfigurationName)/"
    )
ENDFOREACH()

基本上,如果我将$(ConfigurationName)替换为ReleaseDebug,则上面的代码会在工作文件中剪切。但是,我想从相应的目录中取出依赖于Release或Debug构建模式的库。在上面剪切的代码中,$(ConfigurationName)不会被visual studio构建模式取代。我想这是因为这是一个VS2010变量,在cmake生成时间是不知道的。)

有人知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

ADD_CUSTOM_COMMAND了解生成器表达式,因此您可以使用$<CONFIG>而不是$(Configuration)$(ConfigurationName)。但是,对于FILE命令,这将不起作用。更重要的是,如果这些DLL是作为同一项目的一部分构建的,那么第一次构建项目时文件globbing方法将无法工作,因为当你第一次运行CMake时,没有任何DLL会存在布置。

您可能希望将BundleUtilities视为解决问题的更有效方法。尽管它的名字,它支持所有平台,而不仅仅是Mac。您需要调用fixup_bundle命令作为构建后或安装步骤以实现您描述的内容。已经在线描述了这种方法的一些变体(例如herehere)。 您还可以查看DeployQt4.cmake文件的来源,该文件应包含在CMake安装的Modules子目录中以供创意使用。

答案 1 :(得分:0)

假设您的项目名称已填充_TARGET_NAME,而ADDITIONAL_DLL_PATH包含包含外部dll的文件夹列表,则以下代码将复制使用dumpbin找到的所有外部依赖项在窗户上。

foreach(CONF_TYPE ${CMAKE_CONFIGURATION_TYPES})
 string(TOUPPER ${CONF_TYPE} CONF_TYPE_U)
 get_property(TARGET_LOCATION_${CONF_TYPE_U} TARGET ${_TARGET_NAME} PROPERTY LOCATION_${CONF_TYPE_U})
 get_filename_component(TARGE_DIR ${TARGET_LOCATION_${CONF_TYPE_U}} PATH)
 install(CODE "
   if (\"\${BUILD_TYPE}\" STREQUAL \"${CONF_TYPE}\")
     include(BundleUtilities)
     fixup_bundle(\"${TARGET_LOCATION_${CONF_TYPE_U}}\" \"\" \"${ADDITIONAL_DLL_PATH}\")
  endif()"
  COMPONENT Runtime)
endforeach()

这个解决方案有一些缺点,比如需要在需要复制这些文件(可能不会多次)时构建INSTALL目标,而不是检测延迟加载的dll。