预处理之后和使用CMake编译之前的自定义构建步骤
Custom build step after preprocessing and before compilation with CMake
我正试图在预处理和使用CMake编译之间添加一个自定义构建步骤。
在c++预处理器步骤之后,我想在每个预处理的源文件上调用一个python脚本来修改它们。
这里有一个Makefile的例子:
all : prog
# compilation step
prog: main.i
gcc main.i -g -Wall -o prog
# custom step
main.i: main.tmp
./my_script.py main.tmp > main.i
# only preprocessor step
main.tmp: main.c main.h
gcc -E main.c > main.tmp
CMake如何实现这一点?该步骤应应用于项目的每个c
或cpp
文件。
使用add_custom_command
的第一个签名来运行预处理文件的命令,然后运行执行自定义附加处理的命令,并将OUTPUT
定义为自定义处理创建的文件,然后在定义该文件时(通过add_library
/add_executable
)将其列为相关目标的源文件,或者在定义后(通过target_sources
)执行该操作。
如果你想采用我将展示的方法,那么在CMake中使用编译器标志和定义将成为一件非常棘手的事情。通常,您需要确保预处理步骤命令与编译步骤命令具有完全相同的编译器定义和标志。如果预处理和编译之间的标志或定义不同,可能会发生非常奇怪、微妙甚至可能危险的事情。你可能会遇到编译器错误,链接器错误,运行时错误——所有这些都可能很难理解——或者你可能没有遇到任何错误,但仍然犯了一个错误。您需要非常小心,了解编译器并检查预处理器输出,以确保您做得正确。
可能有更好的方法,但我没有想过。我从来没有在真正的项目中这样做过。下面的答案只是理论。把它当作一个起点。它不提供任何保修(<在此处插入您在开源许可证中经常看到的法律保修声明>)。虽然我会努力纠正发现的错误,并保持最新信息,但如果使用此信息导致任何问题,我不会承担责任。
Ex。对于gcc(注意:有关-E
和.ii
的文档,请参阅此处):
list(APPEND my_target_sources "${CMAKE_CURRENT_SOURCE_DIR}/file.cpp")
# this is best placed immediately after the creation of the target so that it knows all the directory compile options and such that the target saw when it got created.
foreach(input_file ${my_target_sources})
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/src-$<CONFIG>/file.ii")
get_target_property(target_compile_opts my_target COMPILE_OPTIONS)
add_custom_command(
OUTPUT "${output_file}"
COMMAND "${CMAKE_CXX_COMPILER}" ${CMAKE_CXX_FLAGS} ${target_compile_opts} -o "${output_file}" -E "${input_file}"
COMMAND my_additional_custom_processing_script "${output_file}" my_arg1 my_arg2 my_arg3
DEPENDS "${input_file}" "my_additional_custom_processing_script"
VERBATIM COMMAND_EXPAND_LISTS # these two args are generally useful, but not actually required here.
)
target_sources(my_target PRIVATE "${output_file}")
# this might be needed since I don't expect cmake to infer CXX from the .ii extension
set_property(SOURCE "${output_file}" TARGET_DIRECTORY my_target PROPERTY LANGUAGE CXX)
endforeach()
当询问者使用python脚本时,为了对其他未来的读者具有通用性,并试图将其他非常相似的问题标记为重复问题,我尝试将该部分保留一点通用性,并且将其编写为主机系统可以在PATH上找到该命令,并且可以自行运行(即,如果脚本假设它有一个适当的shebang)。修改自定义预处理命令部分以适合您的用例。
如果要在每个源文件的基础上设置任何编译器选项,则需要确保在该文件的自定义命令中设置这些选项,并在经过后预处理的源文件的COMPILE_OPTIONS
前缀中设置它们。
如果预处理输出依赖于特定于配置的通用编译器标志(CMAKE_<LANG>_FLAGS_<CONFIG>
),则需要将右生成器表达式中封装的变量添加到COMMAND
,例如"$<$<CONFIG:Debug>:${CMAKE_CXX_FLAGS_DEBUG}>"
。我不知道有什么更漂亮的方法可以为所有配置做到这一点。
当前缺少此答案:
- 预处理时从目标的依赖项设置
INTERFACE
编译器选项 - 将与目标相关联的编译定义传递给预处理器步骤命令。
- 在我或其他人找到一个好方法之前,当涉及到
NDEBUG
宏的存在或不存在时,您可能会立即注意到这一点
- 在我或其他人找到一个好方法之前,当涉及到
我真的希望有人知道更好的方法,因为我的答案已经成熟,有各种各样的错误机会。
事实上,这必须手动完成:我添加了一个自定义目标,在那里我生成预处理文件:
add_custom_target(
start_preprocessor
COMMAND make main.cpp.i
..
)
使用另一个自定义目标,我备份main.cpp,然后将main.cpp.I重命名为main.cpp。然后我可以应用我的预处理过程。之后,我恢复了源文件。
- Android Studio:如何在build.gradle中定义自定义宏(针对不同的构建变体),并让原生C / C++
- 用于自定义调试构建的 CMake qt 输入库后缀
- 自定义构建文件更改不会触发VS 2017中的项目重建
- 从 ParaView 构建自定义 Qt 应用程序示例时出错
- 如何使用C++将MXNET自定义运算符构建到单独的库/包中?
- 有没有办法构建C++自定义限定符?
- 在多个目标上 CMake 后期构建自定义命令?
- 使用 QtCreator 部署自定义构建的项目
- 使用自定义GCC位置构建软件包
- 自定义 Python 构建 - time.so:未定义的符号:PyExc_ValueError
- 预处理之后和使用CMake编译之前的自定义构建步骤
- 针对自定义构建的tcl85.lib的链接器错误,适用于ActiveState发行版的tcl85.lib
- 测试和自定义构建目录的组合
- 如何使用生成 .cpp 和 .h 文件的自定义构建器
- 如何使Sublime Text自动选择自定义构建系统
- 如何在Qt Creator项目向导中添加自定义构建步骤
- 从自定义构建的Python导入自定义模块失败
- 附加自定义构建目录.targets文件
- 用于生成.h文件的VS2010自定义构建工具
- Visual Studio 2010:在单个文件上运行自定义构建工具时指定工作目录