如何让CMake构建系统接受用户指定的任意文件作为输入
实现方案
核心逻辑是拆分CMake的配置、构建两个阶段:配置阶段仅执行一次生成缓存,后续所有调用都只执行构建阶段,通过不同自定义目标对应不同输入文件的处理逻辑,无需重复生成缓存。
1. 编写CMakeLists.txt
首先在项目根目录创建CMakeLists.txt,定义通用的文件处理规则:
cmake_minimum_required(VERSION 3.15) project(FileProcessor LANGUAGES NONE) # 通用文件处理函数,可根据你的实际需求修改内部处理逻辑 function(process_file INPUT_PATH) # 基于输入文件名生成唯一的目标名和输出文件名 get_filename_component(FILE_WE ${INPUT_PATH} NAME_WE) set(TARGET_NAME ${FILE_WE}) set(OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${FILE_WE}.out) # 自定义构建目标,替换COMMAND为你实际的处理命令 add_custom_target(${TARGET_NAME} COMMAND ${CMAKE_COMMAND} -E echo "Processing ${INPUT_PATH}" # 示例为复制文件,可替换为调用你的转换器、编译器等工具 COMMAND ${CMAKE_COMMAND} -E copy ${INPUT_PATH} ${OUTPUT_PATH} MAIN_DEPENDENCY ${INPUT_PATH} COMMENT "Generating ${OUTPUT_PATH}" ) endfunction() # 支持构建时传入输入文件动态注册目标 if(DEFINED INPUT_FILE) process_file(${INPUT_FILE}) endif() # 如果你提前知道所有待处理的输入文件,也可以在这里提前注册所有目标 # 后续构建时无需传参,直接指定目标名即可,完全不会触发重配置 # process_file(MyFile.in) # process_file(OtherFile.in)
2. 编写build.cmd脚本
在项目根目录创建build.cmd,实现自动判断缓存状态、调用CMake的逻辑:
@echo off setlocal :: 校验输入参数 if "%~1"=="" ( echo Usage: build.cmd ^<input_file.in^> exit /b 1 ) set INPUT_FILE=%~f1 set TARGET_NAME=%~n1 set BUILD_DIR=build :: 缓存不存在则执行一次配置生成缓存,仅首次运行会执行 if not exist "%BUILD_DIR%\CMakeCache.txt" ( cmake -S . -B %BUILD_DIR% -G "Ninja" :: 如需使用Visual Studio生成器,替换为对应版本即可,示例为VS2022 :: cmake -S . -B %BUILD_DIR% -G "Visual Studio 17 2022" -A x64 ) :: 调用构建流程,仅处理指定输入文件对应的目标 cmake --build %BUILD_DIR% --target %TARGET_NAME% -- -DINPUT_FILE="%INPUT_FILE%"
使用说明
- 首次执行任意输入文件的构建时,会自动完成CMake缓存生成,后续所有调用都不会重新生成全量缓存
- 首次处理新的输入文件时仅会做极轻量的增量配置(仅注册新目标),重复处理同一文件时直接使用缓存,速度和原生命令行工具一致
- 可随时修改CMakeLists.txt中的process_file函数,替换为你实际的文件处理逻辑
:: 首次运行,自动生成缓存并处理MyFile.in C:\> build.cmd MyFile.in :: 后续运行,直接使用缓存处理OtherFile.in C:\> build.cmd OtherFile.in
内容的提问来源于stack exchange,提问作者Tumbleweed53
相关产品推荐
相关产品推荐

