cmake 'add_custom_command' 预处理头文件?
cmake 'add_custom_command' to pre-process header files?
我正在做一个需要 cmake 的项目。我想在我的 makefile 中添加一些自定义规则,但我不太清楚如何去做。
c源文件和头文件都在同一个目录下。在同一目录中还有许多 .def
文件,它们是编译期间源代码中包含的一些头文件的源代码。
如果我要在 makefile 中执行此操作,我会使用类似
的简单规则
.SUFFIXES: .def
.def.h:
$(PREPROC) $< > $@
我如何使用 cmake 执行此操作??
我已经尝试了以下的各种排列,有和没有 cmake 工作目录规范:
add_custom_command(
OUTPUT vvr_const.h
PRE_BUILD
COMMAND preproc vvr_const.def > vvr_const.h
DEPENDS vvr_const.def
)
add_custom_target(vvr_const.h DEPENDS vvr_const.def)
但是编译c源文件时没有生成头文件,所以编译失败。我还尝试了一种变体,我将上面的最后一行替换为
set_property(SOURCE main.c APPEND PROPERTY OBJECT_DEPENDS vvr_const.h)
本例提前正确生成了头文件,但是make
找不到,报错没有规则做目标.h
.
理想情况下,这将是一个通用规则,就像上面的 make
规则一样,但我不反对为每个 .def
文件制定一个单独的规则,如果需要的话。
干杯。
来自 cmake 的文档:
PRE_BUILD
On Visual Studio Generators, run before any other rules are executed within the target. On other generators, run just before PRE_LINK commands.
所以你的命令可能 运行 太迟了。
您提出的 add_custom_command
方法有 2 个问题:
- 您没有指定工作目录;默认情况下,命令是 运行 在构建目录中,而不是在源目录中。
- 您在这里依赖 shell 功能(重定向到文件)。即使这可能仍然有效。您应该采用不依赖于 shell.
的方法
为了解决问题 1 和 2,我建议创建一个单独的 cmake 脚本文件,接收输入和输出文件的绝对路径,并在自定义命令中使用它们。这允许您使用 execute_process
指定要写入的文件而不依赖于平台。
preprocess_def.cmake
# preprocess def file
# parameters INPUT_FILE and OUTPUT_FILE denote the file to use as source
# and the file to write the results to respectively
# use preproc tool to get data to write to the output file
execute_process(COMMAND preproc "${INPUT_FILE}"
RESULT_VARIABLE _EXIT_CODE
OUTPUT_FILE "${OUTPUT_FILE}")
if (_EXIT_CODE)
message(FATAL_ERROR "An error occured when preprocessing the file ${INPUT_FILE}")
endif()
CMakeLists.txt
set(_INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.def")
set(_OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.h")
# not necessary to use build event here, if we mark the output file as generated
add_custom_command(OUTPUT "${_OUTPUT_FILE}"
COMMAND "${CMAKE_BUILD_TOOL}" -D "OUPUT_FILE=${_OUTPUT_FILE}" -D "INPUT_FILE=${_INPUT_FILE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_def.cmake"
DEPENDS "${_INPUT_FILE}")
add_executable(my_target vvr_const.h ...)
set_source_files_properties(vvr_const.h PROPERTIES GENERATED 1)
我正在做一个需要 cmake 的项目。我想在我的 makefile 中添加一些自定义规则,但我不太清楚如何去做。
c源文件和头文件都在同一个目录下。在同一目录中还有许多 .def
文件,它们是编译期间源代码中包含的一些头文件的源代码。
如果我要在 makefile 中执行此操作,我会使用类似
的简单规则.SUFFIXES: .def
.def.h:
$(PREPROC) $< > $@
我如何使用 cmake 执行此操作??
我已经尝试了以下的各种排列,有和没有 cmake 工作目录规范:
add_custom_command(
OUTPUT vvr_const.h
PRE_BUILD
COMMAND preproc vvr_const.def > vvr_const.h
DEPENDS vvr_const.def
)
add_custom_target(vvr_const.h DEPENDS vvr_const.def)
但是编译c源文件时没有生成头文件,所以编译失败。我还尝试了一种变体,我将上面的最后一行替换为
set_property(SOURCE main.c APPEND PROPERTY OBJECT_DEPENDS vvr_const.h)
本例提前正确生成了头文件,但是make
找不到,报错没有规则做目标.h
.
理想情况下,这将是一个通用规则,就像上面的 make
规则一样,但我不反对为每个 .def
文件制定一个单独的规则,如果需要的话。
干杯。
来自 cmake 的文档:
PRE_BUILD
On Visual Studio Generators, run before any other rules are executed within the target. On other generators, run just before PRE_LINK commands.
所以你的命令可能 运行 太迟了。
您提出的 add_custom_command
方法有 2 个问题:
- 您没有指定工作目录;默认情况下,命令是 运行 在构建目录中,而不是在源目录中。
- 您在这里依赖 shell 功能(重定向到文件)。即使这可能仍然有效。您应该采用不依赖于 shell. 的方法
为了解决问题 1 和 2,我建议创建一个单独的 cmake 脚本文件,接收输入和输出文件的绝对路径,并在自定义命令中使用它们。这允许您使用 execute_process
指定要写入的文件而不依赖于平台。
preprocess_def.cmake
# preprocess def file
# parameters INPUT_FILE and OUTPUT_FILE denote the file to use as source
# and the file to write the results to respectively
# use preproc tool to get data to write to the output file
execute_process(COMMAND preproc "${INPUT_FILE}"
RESULT_VARIABLE _EXIT_CODE
OUTPUT_FILE "${OUTPUT_FILE}")
if (_EXIT_CODE)
message(FATAL_ERROR "An error occured when preprocessing the file ${INPUT_FILE}")
endif()
CMakeLists.txt
set(_INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.def")
set(_OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.h")
# not necessary to use build event here, if we mark the output file as generated
add_custom_command(OUTPUT "${_OUTPUT_FILE}"
COMMAND "${CMAKE_BUILD_TOOL}" -D "OUPUT_FILE=${_OUTPUT_FILE}" -D "INPUT_FILE=${_INPUT_FILE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_def.cmake"
DEPENDS "${_INPUT_FILE}")
add_executable(my_target vvr_const.h ...)
set_source_files_properties(vvr_const.h PROPERTIES GENERATED 1)