You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CMakeLists.txt中定义通用文件转换规则(替代Makefile模式规则)?

如何在CMakeLists.txt中定义通用文件转换规则(替代Makefile模式规则)?

嗨,我明白你想要用CMake实现Makefile里那种模式规则的效果——不用逐个指定文件,只要是.sql文件就自动转换成对应的目标文件对吧?其实CMake没有直接和Makefile模式规则完全等价的语法,但我们可以通过循环配合add_custom_command来实现同样的通用转换效果,下面就一步步来教你怎么做:

核心思路

我们会先收集所有需要处理的.sql文件,然后对每个文件单独定义转换规则,最后把生成的文件加入到主程序的构建目标中。这样只要新增.sql文件,CMake就能自动识别并处理它们(如果用GLOB收集的话,注意新增文件后需要重新运行CMake)。

具体实现代码

下面是对应你需求的CMake配置示例,我们会把.sql文件处理成C风格字符串的.c文件,再由CMake自动编译成目标文件链接到主程序:

# 1. 收集当前目录下所有的.sql文件(如果需要子目录可以用GLOB_RECURSE,或者更严谨地手动列出文件)
file(GLOB SQL_SOURCES *.sql)

# 2. 初始化一个变量,用来存储所有生成的C文件
set(GENERATED_C_SOURCES "")

# 3. 遍历每个.sql文件,定义转换规则
foreach(sql_file ${SQL_SOURCES})
    # 获取文件名(不含路径和后缀),用来作为生成的C字符串变量名
    get_filename_component(sql_name ${sql_file} NAME_WE)
    # 定义输出的C文件路径(放在构建目录下,避免污染源码目录)
    set(output_c ${CMAKE_CURRENT_BINARY_DIR}/${sql_name}_sql.c)
    
    # 添加自定义命令:将sql文件处理成C风格字符串的.c文件
    add_custom_command(
        OUTPUT ${output_c}                # 生成的输出文件
        COMMAND sed -e 's/--.*$$//' -e '/^$$/d' ${sql_file} | xxd -i -n ${sql_name} > ${output_c}
        DEPENDS ${sql_file}               # 依赖的源文件,sql文件修改时会重新生成
        COMMENT "Generating C string from ${sql_file}"  # 构建时显示的提示信息
    )
    
    # 把生成的C文件加入到全局列表中
    list(APPEND GENERATED_C_SOURCES ${output_c})
endforeach()

# 4. 定义主程序目标,包含源码和所有生成的C文件
add_executable(your_main_app main.c ${GENERATED_C_SOURCES})

如果你想直接生成目标文件(.o)

如果你想跳过生成.c文件的步骤,直接生成.o文件,可以把上面的转换命令改成这样:

foreach(sql_file ${SQL_SOURCES})
    get_filename_component(sql_name ${sql_file} NAME_WE)
    set(output_o ${CMAKE_CURRENT_BINARY_DIR}/${sql_name}_sql.o)
    
    add_custom_command(
        OUTPUT ${output_o}
        # 用CMake自带的C编译器变量替代硬编码的gcc,提升跨平台性
        COMMAND sed -e 's/--.*$$//' -e '/^$$/d' ${sql_file} | xxd -i -n ${sql_name} | ${CMAKE_C_COMPILER} -c -x c -o ${output_o} -
        DEPENDS ${sql_file}
        COMMENT "Compiling object file from ${sql_file}"
    )
    
    list(APPEND GENERATED_OBJECTS ${output_o})
endforeach()

# 直接把生成的目标文件加入到可执行目标中
add_executable(your_main_app main.c ${GENERATED_OBJECTS})

关键说明

  • CMake是基于目标的构建系统,它的add_custom_command是绑定到具体输出文件的,不像Makefile的模式规则那样是全局的,但通过循环遍历文件,我们能实现几乎一样的通用效果。
  • 把生成的文件放在CMAKE_CURRENT_BINARY_DIR(构建目录)下,能避免修改源码目录,保持源码干净。
  • 如果不想用file(GLOB)(因为新增文件后需要重新运行CMake),可以手动列出所有.sql文件,比如set(SQL_SOURCES file1.sql file2.sql),这样更严谨。

备注:内容来源于stack exchange,提问作者White Owl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:04:39