configure_file输入文件中#cmakedefine与#define的差异及问题解析
问题解答
核心差异与报错原因
#define vs #cmakedefine
#define是无条件替换:不管CMake变量的值是什么,configure_file都会直接把@VAR@替换为变量的实际值,生成有效的#define语句。比如你的Tutorial_VERSION_MINOR是0,最终会生成#define Tutorial_VERSION_MINOR 0,C++代码能正常识别这个宏。#cmakedefine是条件式生成:CMake会先判断变量是否为「非假值」——在CMake的规则里,0、OFF、NO、FALSE、空字符串等都会被判定为假。如果变量被判定为假,#cmakedefine VAR会被替换成/* #undef VAR */,而不是#define。你的Tutorial_VERSION_MINOR值为0,刚好触发了这个逻辑,导致宏未定义,编译时自然找不到这个标识符。
教程里用#define是合理的:版本号哪怕是0也是有效的业务值,必须无条件定义,不需要做条件判断。
更多文档参考
除了configure_file的官方文档,你可以查看CMake中条件判断和布尔值规则的相关文档,里面会详细说明哪些值会被判定为假。另外,#cmakedefine01是另一个常用变体:
- 当CMake变量为真时,生成
#define VAR 1 - 当变量为假时,生成
#define VAR 0
适合需要将CMake布尔选项转为C语言布尔值的场景。
最小可复现示例
tutorial.cxx
#include <cstdlib> #include <iostream> #include <string> #include "TutorialConfig.h" int main() { std::cout << "Version: " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; return 0; }
正常工作的TutorialConfig.h.in
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(Tutorial VERSION 1.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) configure_file(TutorialConfig.h.in TutorialConfig.h @ONLY) add_executable(Tutorial tutorial.cxx) target_include_directories(Tutorial PUBLIC ${PROJECT_BINARY_DIR})
复现步骤
- 在文件目录下执行
mkdir build创建构建目录 - 进入构建目录:
cd build - 运行CMake:
cmake .. - 编译:
make - 运行程序:
./Tutorial,正常输出Version: 1.0 - 返回上级目录:
cd .. - 修改TutorialConfig.h.in为:
#cmakedefine Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #cmakedefine Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ - 重复上述编译步骤,会出现编译错误:
Step1/tutorial.cxx:8:64: error: ‘Tutorial_VERSION_MINOR’ was not declared in this scope; did you mean ‘Tutorial_VERSION_MAJOR’? 8 | std::cout << "Version: " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; | ^~~~~~~~~~~~~~~~~~~~~~ | Tutorial_VERSION_MAJOR
使用CMake版本:3.22.1
内容的提问来源于stack exchange,提问作者topher217
相关产品推荐
相关产品推荐

