Managing data

The problem

Let’s assume the foo executable needs a file named foo.dat

You may want to put foo.dat under version control, and have the foo executable find the foo.dat file when run:

  • from the build dir
  • when installed

The solution

Here is a possible solution, assuming you have the following layout:

<worktree>
  foo
    CMakeLists.txt
    main.cpp
    share
      foo
        foo.dat
# in CMakeLists.txt
qi_create_bin(foo main.cpp)

# mark this directory as a potential prefix for
# qi::path::findData()
qi_stage_dir()

# create an install rule for foo.dat:
qi_install_data(share/foo/foo.dat SUBFOLDER foo)
// in main.cpp

#include <qi/application.hpp>
#include <qi/path.hpp>


int main(int argc, char* argv[])
{
    // Mandatory for qi::path to work:
    qi::Application app(argc, argv);

    std::string fooPath = qi::path::findData("foo", "foo.dat");
}

How it works

When run from the build dir

The constructor of qi::Application starts by figuring out the exact path of the binary currently running.

(For instance, /path/to/build/sdk/bin/foo).

It then sets the SDK prefix to /path/to/build/sdk, then tries to parse the path.conf in /path/to/build/sdk/share/qi/path.conf.

Every path in this file is added to the list of possible SDK prefixes, recursively.

The path.conf is generated by qibuild configure and contains paths to every possible SDK prefix (the <build/sdk> folder for every project in the worktree, and the path to every package in the toolchain).

Then qi_stage_dir() can find out the directory of the CMakeLists.txt it was called from, and add it at the top of the path.conf file.

When installed

When installed, say to /tmp/foo, the SDK prefix will be /tmp/foo, and since everything is installed to the same destination, qi::path::findData() will find foo.dat in /tmp/foo/share/foo/foo.dat