2

我正在使用 CMake 编译和测试 C++ 项目。假设我有这样的结构:

inc/
    ..
src/
    ..
data/
    dataFile

文件dataFile是从代码访问的,将安装在<prefix>/share或类似的目录下。在我的代码中,我执行以下操作:

std::ifstream dataFile(DATAFILE_PATH);

我知道我可以DATAFILE_PATH使用 CMake 进行配置(使用标头模板,或编译选项,或任何东西),所以我不必直接在我的代码中硬编码文件路径。另外,我知道如何将文件安装到安装树,并且可以复制文件以将文件复制到构建树,例如运行测试或简单地从构建树运行可执行文件。

我的问题是,我应该如何配置 CMake,或者我的 C++ 代码,以便我可以编译我的程序并从构建树(访问构建树dataFile中的副本)安装树(访问dataFile安装的副本<prefix>/share)运行和测试它?在 CMake 中实现了我缺少的任何模式或技术吗?

谢谢。

4

1 回答 1

1

我不知道 CMake 的细节,所以也许我没有给你最简单的解决方案。但我可以想到两种处理方法,不需要在测试和安装之间重新编译程序。

第一种是不要使用单一路径,而是使用它们的列表,并使用第一个可以成功打开的路径。

const char* datafile_paths[] = { DATAFILE_PATH };
...
std::ifstream dataFile;
for(int i = 0; i < sizeof(datafile_paths)/sizeof(char*); i++)
{
    data.open(datafile_paths[i]);
    if(data.is_open()) break;
}
if(!data.is_open()) handle error;

这里的 DATAFILE_PATH 可能如下所示,例如“/foo/bar/data.dat”、“/foo/data.dat”,即以逗号分隔的路径列表。

另一种是使用环境变量。对于某些项目,这可能是更可取的,因为它更灵活,让用户选择保存资源文件的位置。但这通常意味着需要修改 .bashrc 或类似文件,这有点恶心。

char * datapath = getenv("MYPROJECT_DATAPATH");
if(!datapath) handle error;
std::ifstream data(datapath);

通常人们不会单独使用这种技术,而是将其与上述技术结合使用,首先检查环境变量,如果失败则返回编译路径列表。

于 2012-10-29T13:24:44.260 回答