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

如何透明地两次重写CMake的add_executable函数?

解决CMake中add_executable透明重写的无限循环问题

问题本质

你遇到的核心问题是:CMake对函数重写的默认处理会导致多次重写时,前一次自定义函数的调用目标被后续重写覆盖,最终触发无限循环。

当你第一次重写add_executable时,CMake会将原生的add_executable重命名为_add_executable;但第二次重写时,CMake会把**第一次自定义的add_executable**重命名为_add_executable,覆盖了之前原生的备份。此时第一次自定义函数里调用的_add_executable,在执行时会指向它自己,从而引发无限循环。

解决方案

我们需要让每次重写的函数都“捕获”重写前的add_executable实现,而不是依赖执行时的全局_add_executable。可以通过封装一个辅助宏来自动处理这个逻辑,让后续重写无需感知前一次的存在,实现完全透明的链式调用。

步骤1:封装重写宏

这个宏会自动保存当前的add_executable实现,然后生成新的自定义函数,新函数会先执行你的自定义逻辑,再调用之前保存的版本:

macro(override_add_executable NEW_FUNC_BODY)
    # 动态生成临时函数,保存当前add_executable的实现
    cmake_language(EVAL CODE "
        function(_add_executable_prev)
            cmake_language(CALL add_executable \${ARGV})
        endfunction()
    ")
    # 移除旧的add_executable定义,为新定义让路
    unset(add_executable)
    # 定义新的add_executable函数,包含自定义逻辑和链式调用
    function(add_executable)
        ${NEW_FUNC_BODY}
        _add_executable_prev(\${ARGV})
    endfunction()
    # 清理临时函数,避免命名空间污染
    unset(_add_executable_prev)
endmacro()

步骤2:使用宏进行透明重写

现在你可以多次调用这个宏来重写add_executable,每次只需要传入自定义逻辑即可,无需关心前一次的实现:

cmake_minimum_required(VERSION 3.18)
project(interposition LANGUAGES C)

# 第一次重写:添加自定义日志
override_add_executable("
    message(STATUS \"Inside of \${CMAKE_CURRENT_FUNCTION}\")
")

# 第二次重写:添加另一层自定义日志
override_add_executable("
    message(STATUS \"Inside of the second copy of \${CMAKE_CURRENT_FUNCTION}\")
")

# 正常调用add_executable,会触发链式执行
add_executable(main main.c)

执行结果

运行上述代码后,输出会是:

-- Inside of the second copy of add_executable
-- Inside of add_executable

之后会正常调用原生的add_executable完成目标构建,不会出现无限循环。

原理说明

  • cmake_language(EVAL CODE)用于动态生成临时函数_add_executable_prev,这个函数在定义时就绑定了当前的add_executable实现(不管是原生还是上一次自定义的),不会被后续重写影响。
  • unset(add_executable)确保我们可以重新定义函数,避免CMake报错“函数已存在”。
  • 新的add_executable函数先执行你的自定义逻辑,再调用临时函数完成链式传递,完美实现了“后一次重写调用前一次,最终调用原生”的透明效果。

内容的提问来源于stack exchange,提问作者TallChuck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:20:29