我的项目有这个简化的目录结构:
+-src
| +-CMakeLists.txt
+-example
| +-CMakeLists.txt
+-_builds
| +-win
| | +-src
| | +-example
| +-linux
| | +-src
| | +-example
+-CMakeLists.txt
在
example/CMakeLists.txt
中,我使用依赖于平台的编译器将着色器编译到相应的 _builds/*/example
目录中,然后将路径传递给 C++ 代码,如下所示:
target_compile_definitions(vulkan_tutorial PRIVATE EXAMPLE_BIN_DIR=${CMAKE_CURRENT_BINARY_DIR})
在 C++ 中我这样做:
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define GET_EXAMPLE_BIN_DIR() TOSTRING(MYLIB_EXAMPLE_BIN_DIR)
std::cout << GET_EXAMPLE_BIN_DIR() << std::endl;
在 Windows 上,这按我的预期工作,并且打印
D:/Dev/mylib/_builds/win/example
。
但是,在 Ubuntu 虚拟机上它会打印
/mnt/hgfs/dev/mylib/_builds/1/example
。所以linux这个词被替换为1。为什么呢?怎么解决?
我将我的项目命名为
mylib
只是为了这个问题。它的真实名称是不同的,以防万一。它很简单,仅包含几个核心 ASCII 字符,仅下划线字母。
我检查了二进制目录结构是否包含名为 1 的文件夹。没有。它包含上面列出的内容。我搜索了类似的 CMake 变量但没有找到任何解决方案。我还意识到,如果出现语法错误,CMake 会显示整个命令。滥用这个,我检查了我的 CMake 构建命令,发现它看起来不错。它包含这个:
-DEXAMPLE_BIN_DIR=/mnt/hgfs/dev/mylib/_builds/linux/example
整个命令行看起来像这样(我没有简化这个,不是为了隐藏任何可能的错误):
/bin/x86_64-linux-gnu-g++-9 -DMYLIB_ASSERT_TO_CERR -DMYLIB_ENABLE_EXCEPTIONS -DMYLIB_EXAMPLE_BIN_DIR=/mnt/hgfs/dev/mylib/_builds/linux/example -DMYLIB_LINKED_WITH_VULKAN -DMYLIB_LOGLEVEL=3 -DMYLIB_PRINT_CONFIG -I/mnt/hgfs/dev/mylib/include -I/mnt/hgfs/dev/mylib/third_party/glad2/include -I/mnt/hgfs/dev/mylib/_builds/linux/_deps/glfw-src/include -I/mnt/hgfs/dev/mylib/_builds/linux/_deps/glm-src -g -std=gnu++17 -MD -MT example/CMakeFiles/vulkan_tutorial.dir/vulkan.cpp.o -MF example/CMakeFiles/vulkan_tutorial.dir/vulkan.cpp.o.d -o example/CMakeFiles/vulkan_tutorial.dir/vulkan.cpp.o -c /mnt/hgfs/dev/mylib/example/vulkan.cpp
linux
被定义为 1
,MYLIB_EXAMPLE_BIN_DIR
中的部分字符串在字符串化之前会被扩展。如果您希望宏成为字符串,只需将其作为字符串传递给编译器即可,然后您可以跳过字符串化,并保证不会得到任何奇怪的扩展:
-DMYLIB_EXAMPLE_BIN_DIR=\"/mnt/hgfs/dev/mylib/_builds/linux/example\"
#include <iostream>
#define GET_EXAMPLE_BIN_DIR() MYLIB_EXAMPLE_BIN_DIR
int main()
{
std::cout << GET_EXAMPLE_BIN_DIR() << std::endl;
}
https://godbolt.org/z/ev4aq4eMx 要在 cmake 中执行此操作:
target_compile_definitions(vulkan_tutorial PRIVATE EXAMPLE_BIN_DIR="${CMAKE_CURRENT_BINARY_DIR}")