我有一个涉及从数据生成头文件的项目。会有很多这样的,所以我想要一种可扩展的方法。
我有一个适用于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.txt
和input2.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
答案 0 :(得分:1)
根据构建日志,MSBuild会查找CMAKEFILES\GENERATEFILE1
中列为目标的文件CMAKEFILES\GENERATEFILE2
和CMakeLists.txt
,而不是文件。最有可能的是,由于调用
SET_SOURCE_FILES_PROPERTIES(Generate${tag} PROPERTIES SYMBOLIC TRUE)
但我认为这次电话没有理由。
调用本身是错误的:命令SET_SOURCE_FILES_PROPERTIES
只能用于文件,而不能用于目标。
此外,您无需在代码中设置文件的 GENERATED 属性:
CMake会根据add_custom_command
中CMakeLists.txt
的 OUTPUT 选项中列出的文件自动设置此属性,这取决于这些文件。这正是你的情况。