我正在使用CMake编译和测试C ++项目。假设我有这样的结构:
inc/
..
src/
..
data/
dataFile
可以从代码访问文件dataFile
,并将其安装在<prefix>/share
或类似内容下。在我的代码中,我做了类似的事情:
std::ifstream dataFile(DATAFILE_PATH);
我知道我可以使用CMake配置DATAFILE_PATH
(使用标题模板,或编译选项,或任何其他内容),因此我不必直接在代码中对文件路径进行硬编码。此外,我知道如何将文件安装到安装树,并且可以将文件复制到复制文件以构建树,例如运行测试,只需从构建树运行可执行文件。
我的问题是,我应该如何配置CMake,或者我的C ++代码,以便我可以编译我的程序并从构建树运行并测试它(访问构建树中的dataFile
副本)和来自安装树(访问dataFile
下的<prefix>/share
已安装副本)?在CMake中是否有任何我缺失的模式或技术?
感谢。
答案 0 :(得分: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或类似需要修改,这有点icky。
char * datapath = getenv("MYPROJECT_DATAPATH");
if(!datapath) handle error;
std::ifstream data(datapath);
通常一个人不会单独使用这种技术,而是将它与上面的技术结合起来,首先检查环境变量,如果失败则回退到编译路径列表中。