在我看来,您正在寻找的是一个可重定位的构建。
在 CMake 中实现此目的的一种方法是使用配置文件将资源路径合并到您的代码中。我准备了一个最小且可重复的示例,让您了解它的工作原理。
首先,假设您在磁盘上有以下程序结构:
main
CMakeLists.txt
main.cpp
data
CMakeLists.txt
Resources.h.in (Thats the configuration file)
resource.txt
resource.txt 文件只包含一个字符串。该程序只需打开该文件,读取其内容并将其显示到终端。所以你有类似的东西:
#include <fstream>
#include <iostream>
#include <string>
#include <Resources.h>
const std::string MY_FILE = "/resource.txt";
int main(int argc, char *argv[])
{
std::string line;
std::ifstream myfile (RESOURCE_PATH + MY_FILE);
if(myfile.is_open())
{
while(std::getline(myfile,line))
{
std::cout << line << '\n';
}
myfile.close();
}
else
{
std::cout << "Unable to open file";
}
return 0;
}
注意这个文件#includes 是一个Resources.h 文件,但是这个文件在我们的项目中不存在。但是,我们有一个 Resources.h.in 配置文件,CMake 将在生成时将其转换为 Resources.h 文件。然后,这个生成的文件将在 RESOURCE_PATH 变量中包含我们需要的资源路径。以下是配置文件包含的内容:
#define RESSOURCE_PATH "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATADIR@"
一个简单的#define 带有这个奇怪的@something@ 符号。在生成时,CMake 将进行适当的替换并将结果写入Resource.h,然后我们可以使用它。主要的CMakeLists.txt 文件非常简单:
cmake_minimum_required(VERSION 3.10)
project(example)
# Sets up classic installation directories. However,
# you can override them:
include(GNUInstallDirs)
add_subdirectory(data)
add_subdirectory(main)
为了方便起见,我使用GNUInstallDirs 填充变量,例如CMAKE_INSTALL_DATADIR。 main/CMakeLists.txt 文件:
add_executable(example main.cpp)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Ressources.h.in" "Ressources.h")
target_include_directories(example
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
install(
TARGETS example
DESTINATION ${CMAKE_INSTALL_BINDIR}
)
这是设置配置文件的地方。添加了下面的target_include_directories 以便CMake 能够找到生成的Resource.h 文件,该文件将驻留在构建目录中。最后,data/CMakeLists.txt 文件:
install(
FILES resource.txt
DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}
)
只有一个简单的安装说明。从那里,您可以照常安装。只需创建一个构建目录并照常使用 CMake。例如,如果构建目录与项目位于同一级别:
mkdir ../build
cd ../build
cmake ../project
make
sudo make install
因为默认情况下(在 Linux 上)我们有:
CMAKE_INSTALL_PREFIX=/usr/local
CMAKE_INSTALL_BINDIR=bin
CMAKE_INSTALL_DATADIR=share
程序将安装到/usr/local/bin,资源安装到/usr/local/share。请注意,一旦由 CMake 生成,Resource.h 文件将为您提供正确的路径。然而,现在很好的是,您可以通过像这样调用 CMake 来修改 CMAKE_INSTALL_PREFIX 的值以指向其他地方(例如,这可能是一个开发构建目录):
cmake -DCMAKE_INSTALL_PREFIX=/home/someone/example ../project
你将拥有这些值:
CMAKE_INSTALL_PREFIX=/home/someone/example
CMAKE_INSTALL_BINDIR=bin
CMAKE_INSTALL_DATADIR=share
Resources.h 文件也将更新为指向正确的位置,您的资源仍会被找到。