CMake,生成的依赖项和Visual Studio 2017

时间:2018-02-12 05:57:41

标签: visual-studio cmake visual-studio-2017

我有一个涉及从数据生成头文件的项目。会有很多这样的,所以我想要一种可扩展的方法。

我有一个适用于Linux和OS X(Makefiles和XCode)的解决方案,但不适用于Visual Studio。无论如何,始终在Visual Studio上重新生成头文件。

这是一个简洁的例子来说明我的意思。对于代码转储感到抱歉,但这是我能做到的最小代码。

CMakeLists.txt

project(the_project)

cmake_minimum_required(VERSION 3.1)

SET(GEN_INCLUDES_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated_includes")
FILE(MAKE_DIRECTORY ${GEN_INCLUDES_DIR})

# Generator
SET_SOURCE_FILES_PROPERTIES(header_generator PROPERTIES GENERATED TRUE)
ADD_EXECUTABLE(header_generator
    ${CMAKE_CURRENT_SOURCE_DIR}/generator.c
)

# Symbolic target for all generated includes
ADD_CUSTOM_TARGET(GeneratedIncludes)
SET_SOURCE_FILES_PROPERTIES(GeneratedIncludes PROPERTIES SYMBOLIC TRUE)

# Macro for generating a single header
macro(GenerateHeader tag input_file target_header)
    SET_SOURCE_FILES_PROPERTIES(Generate${tag} PROPERTIES SYMBOLIC TRUE)
    SET_SOURCE_FILES_PROPERTIES(${target_header} PROPERTIES GENERATED TRUE)
    ADD_CUSTOM_TARGET(Generate${tag} DEPENDS ${GEN_INCLUDES_DIR}/${target_header})
    ADD_CUSTOM_COMMAND(
        OUTPUT ${GEN_INCLUDES_DIR}/${target_header}
        COMMAND $<TARGET_FILE:header_generator>
        ARGS ${input_file} ${target_header}
          DEPENDS header_generator ${input_file}
        WORKING_DIRECTORY ${GEN_INCLUDES_DIR}
        COMMENT "Generating ${target_header}"
    )
    ADD_DEPENDENCIES(GeneratedIncludes Generate${tag})
    INSTALL(FILES "${GEN_INCLUDES_DIR}/${target_header}" DESTINATION include)
endmacro()

# The headers to generate
GenerateHeader(File1 input1.txt generated1.h)
GenerateHeader(File2 input2.txt generated2.h)

# A real target
ADD_EXECUTABLE(product main.c)
ADD_DEPENDENCIES(product GeneratedIncludes)
TARGET_INCLUDE_DIRECTORIES(product PRIVATE ${GEN_INCLUDES_DIR})

generator.c

#include <stdio.h>

int main(int argc, char* argv[]) {
    FILE* out = fopen(argv[2], "wt");
    fprintf(out, "/* Pretend we used the file %s somehow */\n", argv[1]);
    fclose(out);
}

main.c

#include "generated1.h"
#include "generated2.h"

int main() { return 0; }

您还需要两个名为input1.txtinput2.txt的数据文件。他们可能是空的。您可以验证在OS X或Linux上,除非您触摸生成器源代码或其中一个数据文件,否则不会重建头文件。在Visual Studio上,它每次都会重建它们。

我打开了MSBuild的“诊断”级别输出,这是输出的一部分似乎是问题所在:

3>------ Up-To-Date check: Project: GenerateFile1.vcxproj, Configuration: Debug x64 ------
3>Project not up to date because the following 0 build outputs were missing:
3> up to date is missing: 'C:\BLAH\CMAKE_EXAMPLE_BUILD\CMAKEFILES\GENERATEFILE1'
3>
3>------ Build started: Project: GenerateFile1, Configuration: Debug x64 ------
4>------ Up-To-Date check: Project: GenerateFile2.vcxproj, Configuration: Debug x64 ------
4>Project not up to date because the following 0 build outputs were missing:
4> up to date is missing: 'C:\BLAH\CMAKE_EXAMPLE_BUILD\CMAKEFILES\GENERATEFILE2'
4>
4>------ Build started: Project: GenerateFile2, Configuration: Debug x64 ------

如果我正确阅读,MSBuild似乎正在寻找未生成的文件。

有什么想法吗?

软件版本:CMake 3.10.2,Visual Studio 15 2017

1 个答案:

答案 0 :(得分:1)

根据构建日志,MSBuild会查找CMAKEFILES\GENERATEFILE1中列为目标的文件CMAKEFILES\GENERATEFILE2CMakeLists.txt,而不是文件。最有可能的是,由于调用

,会生成此类文件的依赖项
SET_SOURCE_FILES_PROPERTIES(Generate${tag} PROPERTIES SYMBOLIC TRUE)

但我认为这次电话没有理由。

调用本身是错误的:命令SET_SOURCE_FILES_PROPERTIES只能用于文件,而不能用于目标

此外,您无需在代码中设置文件的 GENERATED 属性: CMake会根据add_custom_commandCMakeLists.txt OUTPUT 选项中列出的文件自动设置此属性,这取决于这些文件。这正是你的情况。