CMake检测C编译器失败及变量CMakeLists.txt用法咨询
咱们先把问题拆解清楚:你想用一个独立的CMakeLists.txt来集中管理项目变量,然后通过add_subdirectory在其他目录引入,这个思路本身是可行的,但直接单独运行这个vars目录下的CMakeLists.txt是不符合它的设计初衷的——这也是导致编译器检测错误的核心原因。
为什么会出现C编译器检测错误?
CMake默认会把任何直接执行的CMakeLists.txt当成一个完整的项目来处理,而完整项目的初始化流程必然包含C/C++编译器的自动检测。你的vars目录里的文件只做了变量设置,没有定义任何编译目标,但CMake还是会走完整的项目初始化流程。
从错误日志能看到,CMake误将g++(C编译器)当成了C编译器来使用,进而触发了#error "The CMAKE_C_COMPILER is set to a C++ compiler"的报错。这大概率是因为你的环境中默认C编译器的配置存在小问题,而当CMake处理这个“不完整”的项目时,没有正确区分C和C编译器的路径。
你的写法是否正确?
如果只是作为主项目的子目录通过add_subdirectory引入,这个写法是没问题的——主项目的CMakeLists.txt会负责完成编译器检测等初始化工作,引入子目录时只会执行里面的set命令,不会重复触发编译器检测流程。
但如果要让这个vars目录的CMakeLists.txt单独运行也不报错(虽然实际场景中没必要这么做),就需要调整写法了。
解决方案
方案1:不要单独运行这个vars目录的CMakeLists.txt
这是最直接的方案,因为它本来就是为了被主项目引入而设计的。在主项目的CMakeLists.txt中通过add_subdirectory(top_directory/vars)引入后,主项目的编译器配置会生效,变量也能正常被其他目录使用。
方案2:修改vars目录的CMakeLists.txt,跳过编译器检测
在文件开头添加project命令并指定项目类型为NONE,告诉CMake这是一个不需要编译器的项目,从而跳过编译器检测流程:
cmake_minimum_required(VERSION 2.8) project(VarStorage NONE) # 关键:指定无编译器需求的项目类型 set(VARIABLE "value")
这样单独运行这个目录的cmake时,就不会再触发编译器检测了。
方案3:改用.cmake模块文件管理变量(更推荐)
其实CMake更推荐用.cmake模块文件来集中管理全局变量,而不是用CMakeLists.txt。具体做法:
- 在
top_directory/vars/下创建vars.cmake文件,内容仅保留变量设置:set(VARIABLE "value") - 在其他需要使用这些变量的CMakeLists.txt中,通过
include命令引入:include(${CMAKE_SOURCE_DIR}/top_directory/vars/vars.cmake)
这种方式更清晰,.cmake文件本身不是项目入口,不会触发任何初始化流程,完全避免了单独运行的问题,也更符合CMake的最佳实践。
内容的提问来源于stack exchange,提问作者SailorCire

