英文:
How can I pass CMake's CMAKE_SOURCE_DIR to C++ source files?
问题
在我的C++程序中,我使用std::source_location
进行日志输出。目前打印的路径是绝对路径。该项目使用CMake构建。我想根据CMake变量CMAKE_SOURCE_DIR
缩短std::source_location
的路径。
如何在我的C++代码中访问CMAKE_SOURCE_DIR
?
我尝试过:
add_compile_definitions(" -DSOURCE_ROOT=\"${CMAKE_SOURCE_DIR}\"")
但是出现了错误:
error: macro names must be identifiers
我安装了CMake 3.22.1,并在我的CMakeLists.txt中使用了cmake_minimum_required(VERSION 3.19)
。我在Ubuntu上使用GCC进行了测试,但我有一种不成熟的预感,我在Windows上使用MSVC和clang时也会遇到相同的问题。
英文:
In my C++ program I use std::source_location
for log output. The printed path is currently absolute. The project is built with CMake. I want to shorten the std::source_location
path according to the CMake variable CMAKE_SOURCE_DIR
.
How can I access CMAKE_SOURCE_DIR
within my C++ code?
I tried:
add_compile_definitions("-DSOURCE_ROOT=\"${CMAKE_SOURCE_DIR}\"")
But got:
error: macro names must be identifiers
I have CMake 3.22.1 installed, and cmake_minimum_required(VERSION 3.19)
in my CMakeLists.txt. I tested with GCC on Ubuntu, but I have an unsubstantiated hunch that I'll observe the same on MSVC and clang on Windows as well.
答案1
得分: 3
通用的 add_compile_definitions
方法是有效的。其中一个原因是你手动添加了 -D
前缀,而 CMake 会为你添加(你不需要包含它)。另一个原因是你不需要在定义值周围添加引号。如果需要的话,CMake 会自动在值周围添加引号(例如,如果它包含空格)。所以你可以简单地执行 add_compile_definitions("SOURCE_ROOT=${CMAKE_SOURCE_DIR}")
(或者在合适的情况下使用 target_compile_definitions
)。
来自 add_compile_definition
文档 的注释:
> 3.26 版本新增: 任何前导的 -D 都将被移除。
这就是为什么我无法重现你的问题的原因(在我撰写这篇文章时,我最初安装的是 3.26 版本)。
还有其他方法可以实现你想要的效果。你可以使用 CMake 生成包含宏定义的头文件,这样做的好处是如果有人想要使用安装版本并且宏需要在已安装的头文件中可用,那就不依赖于任何特定于 CMake 的机制。要做到这一点,你可以使用 configure_file
命令。实际上,这是 CMake 教程的第一步 的一部分。创建一个带有包含保护和 #define VAR ${CMAKE_SOURCE_DIR}
(或者你想要的任何变量)的输入文件,然后配置该文件。通常,生成的文件会被放在 CMAKE_CURRENT_BINARY_DIR
中(或者是其他二进制目录,比如 PROJECT_BINARY_DIR
或 CMAKE_BINARY_DIR
)。然后使用 add_include_directory
或 include_directories
或 target_include_directories
添加适当的包含目录。
请注意,还有其他与 CMAKE_SOURCE_DIR
相关的变量,根据你的实际需求,你可能会更感兴趣使用它们:PROJECT_SOURCE_DIR
,CMAKE_CURRENT_SOURCE_DIR
,CMAKE_CURRENT_LIST_DIR
。
如果你想调试这些东西,你可以使用非标准的(但在 GCC、Clang 和 MSVC 中受支持的)#pragma message ...
指示来打印宏定义,或者如果你的生成器支持的话,可以使用 compile_commands.json 文件。
英文:
The general approach you're taking with add_compile_definitions
works. One part of why it's not working is that you're prefixing with -D
manually, which CMake will add for you (you don't need to include it). Another part is that you don't need to add the quotes around the definition value. CMake will add quotes automatically around the value if it needs them (Ex. if it contains spaces). So you can just do add_compile_definitions("SOURCE_ROOT=${CMAKE_SOURCE_DIR}")
(or use target_compile_definitions
if appropriate).
Note from the add_compile_definition
docs:
> New in version 3.26: Any leading -D on an item will be removed.
which is why I couldn't reproduce your issue (I originally had 3.26 installed at the time of this writing)
There are also other ways to do what you're looking for. You can use CMake to generate a header containing the macro definition, which I suppose could have the benefit that for installations, if someone wants to use the installation and the macro needs to be available in the installed headers, then that wouldn't rely on any CMake-specific mechanism. To do that, you can use the configure_file
command. This is actually part of the very first step of the CMake tutorial. Create an input file with include guards and #define VAR ${CMAKE_SOURCE_DIR}
(or whatever variable you want), and then configure that file. Conventionally, generated files get put somewhere in the CMAKE_CURRENT_BINARY_DIR
(or some other binary directory like PROJECT_BINARY_DIR
or CMAKE_BINARY_DIR
). Then add the appropriate include directory using add_include_directory
or include_directories
or target_include_directories
.
Note that there are other related variables to CMAKE_SOURCE_DIR
that you might actually be interested in using instead based on your actual needs: PROJECT_SOURCE_DIR
, CMAKE_CURRENT_SOURCE_DIR
, CMAKE_CURRENT_LIST_DIR
.
If you want to debug these things, you can use the non-standard (but supported in GCC, Clang, and MSVC) #pragma message ...
pragma to print the macro definition, or if your generator supports it, a compile_commands.json file.
答案2
得分: 1
简单的方法是:
add_compile_definitions("SOURCE_ROOT=${CMAKE_SOURCE_DIR}")
然后你会:
#define STRING(x) #x
#define XSTRING(x) STRING(x)
std::cout << XSTRING(SOURCE_ROOT) << '\n';
英文:
The simple way would be to:
add_compile_definitions("SOURCE_ROOT=${CMAKE_SOURCE_DIR}")
And then you would do:
#define STRING(x) #x
#define XSTRING(x) STRING(x)
std::cout << XSTRING(SOURCE_ROOT) << '\n';
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论