CMake鸡生蛋问题:如何在配置阶段先执行Python脚本再处理子目录?
在CMake配置阶段运行Python脚本生成单元测试方案
核心步骤
1. 配置阶段执行Python脚本
在顶层CMakeLists.txt中,使用execute_process命令在CMake配置阶段(运行cmake时)直接调用Python脚本,确保生成代码和子目录CMakeLists先完成。
示例代码:
# 定义路径变量 set(PYTHON_SCRIPT "${CMAKE_SOURCE_DIR}/scripts/generate_unit_tests.py") set(TEST_GENERATED_DIR "${CMAKE_BINARY_DIR}/generated_tests") # 创建生成目录(避免脚本执行报错) file(MAKE_DIRECTORY ${TEST_GENERATED_DIR}) # 执行Python脚本 execute_process( COMMAND ${Python3_EXECUTABLE} ${PYTHON_SCRIPT} --source-root ${CMAKE_SOURCE_DIR}/src --output-dir ${TEST_GENERATED_DIR} RESULT_VARIABLE SCRIPT_EXIT_CODE OUTPUT_VARIABLE SCRIPT_OUTPUT ERROR_VARIABLE SCRIPT_ERROR_MSG ) # 检查脚本执行状态,失败则终止配置 if(NOT SCRIPT_EXIT_CODE EQUAL 0) message(FATAL_ERROR "单元测试生成脚本执行失败:\n${SCRIPT_ERROR_MSG}") endif()
2. 集成生成的测试子目录
脚本生成测试子目录和对应CMakeLists.txt后,直接让CMake导入这些目录:
方式一:自动遍历生成目录
# 遍历生成目录下的所有子测试目录 file(GLOB TEST_SUBDIRS LIST_DIRECTORIES TRUE "${TEST_GENERATED_DIR}/*") foreach(SUBDIR ${TEST_SUBDIRS}) if(IS_DIRECTORY ${SUBDIR}) add_subdirectory(${SUBDIR}) endif() endforeach()
方式二:导入脚本生成的顶层配置
让Python脚本在TEST_GENERATED_DIR下生成一个test_suites.cmake,里面包含所有add_subdirectory命令,然后在顶层CMakeLists中导入:
include(${TEST_GENERATED_DIR}/test_suites.cmake)
3. Python脚本编写要点
- 识别单元测试函数:用正则匹配源码中的
UNIT_TEST_(\w+)\(\)格式函数,提取测试名称 - 生成测试代码:为每个测试生成独立的
main.c,示例:
#include "module_header.h" int main() { UNIT_TEST_somename(); return 0; }
- 生成子目录CMakeLists:每个测试子目录的
CMakeLists.txt要包含:
add_executable(test_somename main.c) target_link_libraries(test_somename PRIVATE your_project_lib) add_test(NAME test_somename COMMAND test_somename)
4. 自动触发重新配置
当源码或Python脚本修改时,让CMake自动重新运行脚本:
# 监控关键文件变化,触发CMake重新配置 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PYTHON_SCRIPT} ${CMAKE_SOURCE_DIR}/src/**/*.c ${CMAKE_SOURCE_DIR}/src/**/*.h )
内容的提问来源于stack exchange,提问作者user3696153
相关产品推荐
相关产品推荐

