如何使用CMake获取多配置生成器和基于makefile的目标文件的路径?

mlt*_*mlt 5 windows cmake

我想基于动态方式的目标文件中的所有符号生成模块定义文件(想想GTKMMgendef).

为此,我想add_custom_commandPRE_LINK目标迈出一步.但是,看起来没有简单的方法可以使用CMake获取所有目标文件的路径,这些文件适用于普通的makefile以及Visual Studio等多配置生成器.

现在,我有以下内容

add_custom_command(TARGET tgt PRE_LINK
COMMAND gendef ${CMAKE_CURRENT_BINARY_DIR}/tgt.def $<TARGET_FILE_NAME:tgt> ${CMAKE_CURRENT_BINARY_DIR}/$<$<BOOL:${CMAKE_BUILD_TYPE}>:${CMAKE_FILES_DIRECTORY}>/tgt.dir/${CMAKE_CFG_INTDIR}/*.obj
)
Run Code Online (Sandbox Code Playgroud)

然而,由于我不得不在我看来使用生成器表达,这是非常笨拙和笨重的.有没有更好的方法来实现这种效果,即为每个构建配置调用某个外部程序?

它是一个CMake错误(功能?),对于普通的makefile,所有目标文件都转到CMakeFiles/tgt.dir文件夹,而对于多配置生成器,所有文件都转到CMakeFiles 的兄弟,即tgt.dir/$<CONFIG>?我是否错过了一些简单的变量,可以直接指向正确的位置?

Flo*_*ian 1

将我的评论变成答案

由 CMake 生成的 Makefile 项目与为 Visual Studio 生成的解决方案/项目具有完全不同的内部结构。我认为这既不是错误也不是功能,这些结构只是针对其用例进行了优化。

据我所知,没有简单的 CMake 内部方法来获取目标文件列表或中间文件目录的路径,例如读取目标属性。

因此,我采用了您的代码示例,并使用 CMake 3.3.2 使用Visual Studio 14 2015NMake Makefiles生成器对替代方案进行了一些测试。

备择方案

  1. CMake 邮件列表上的一个相关讨论名为“CMake:是否有一种优雅的方法来获取参与库的对象文件列表?” 确实建议使用中间静态库:

    add_library(tgtlib STATIC tgt.c)
    add_custom_command(
        OUTPUT tgt.def
        COMMAND gendef tgt.def $<TARGET_FILE_NAME:tgt> $<TARGET_FILE:tgtLib> 
    )
    file(WRITE dummy.c "")
    add_library(tgt SHARED dummy.c tgt.def)
    target_link_libraries(tgt tgtlib)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您可以将构建环境特定元素添加到您的PRE_LINK步骤中:

    if(CMAKE_CONFIGURATION_TYPES)
        set(_obj_files "$(IntermediateOutputPath)*.obj")
    else()
        set(_obj_files "$?")
    endif()
    add_custom_command(
        TARGET MainProject 
        PRE_LINK
        COMMAND gendef tgt.def $<TARGET_FILE_NAME:tgt> ${_obj_files}
    )
    
    Run Code Online (Sandbox Code Playgroud)

参考