|
libqi
1.12
|
go to the qi::path API reference.
The main idea of the qibuild-based project is that you always end up with the same layout.
For instance, right after having built you project, you end up with a directory looking like this:
Here we assume you have a foo executable which:
bar dynamic libraryfoo.data foo.cfg
src
|__ foo
|__ data
|___ foo.data
|__ etc
|__ foo.cfg
build
|___
sdk
|__ lib
|___ libbar.so
|__ bin
|__ foo
When everything is installed, you have something like:
prefix
|__ lib
|__ libbar.so
|__ bin
|__ foo
|__ share
|__ foo
|__ foo.data
|__ etc
|__ foo
|__ foo.cfg
Here is a list of common requirements:
foo/foo.cfg, foo/foo.data in a clean, simple way, while making sure the solution works whereas the project is built or installedfoo may need to write or update its configuration files or data but we need to make sure nothing will be written inside the installed directoryfoo.cfg files, we need to be able to process then in a correct order.Here is how it works:
/path/to/build/sdk, when something is installed, the prefix is the DESTDIR plus the installation prefix.foo.cfg is placed in build/sdk/foo/foo.cfg (same thing for data)argv0. For instance, if argv0 is /path/to/build/sdk/bin/foo, we can assume the prefix is /path/to/build/sdk.qi::path documentation.
The API of qi::path always make sure that:
For this to work, we must make sure that
Have a look on the API of qi::path for more details
Writing a configuration file is very different from reading one.
Let's assume the foo executable want to make sure that SPAM=42 in foo.cfg.
Here is how it works:
foo.cfg foo.cfg is foundfoo.cfg filefoo.cfg file.You can see that we ask for a list of paths when reading, but that we always write to one file.
Let's go through these steps again, assuming foo is installed in /usr/bin/foo, and foo.cfg in /usr/share/foo/foo.cfg, and that there is nothing else on the machine where foo is running.
foo.cfg using qi::path::getConfigurationPaths [~/.config/foo/foo.cfg, /usr/share/foo/foo.cfg] .config/foo/foo.cfg does not exist, we read /usr/share/foo/foo.cfg SPAM=42 to ~/.config/foo/foo.cfgThen each time a piece of code will ask for the foo.cfg path, it will get a list starting with ~/.config/foo/foo.cfg, so we are sure the setting SPAM=42 will be used.
#include <iostream> #include <fstream> #include <vector> #include <qi/os.hpp> #include <qi/path.hpp> #include <qi/qi.hpp> #include <boost/locale.hpp> #include <boost/filesystem.hpp> #include <locale> int main(int argc, char *argv[]) { // Set the global locale to loc std::locale::global(boost::locale::generator().generate("")); // Make boost.filesystem use it boost::filesystem::path::imbue(std::locale()); // Get the prefix name from argv0 std::cout << "argv0 is: " << argv[0] << std::endl; // Get the prefix name from argv0 // Performs various initializations. // This is usually called by qi::init() qi::init(argc, argv); // Get sdk prefix std::cout << "SDK prefix is: " << qi::path::sdkPrefix() << std::endl; // First argument is the name of the application, used // to build various paths later. std::string fooCfgPath = qi::path::findConf("foo", "foo.cfg"); if (fooCfgPath == "") { std::cerr << "Could not find foo.cfg" << std::endl; std::cerr << "Looked in: " << std::endl; std::vector<std::string > configPaths = qi::path::confPaths("foo"); std::vector<std::string>::const_iterator it; for (it = configPaths.begin(); it != configPaths.end(); ++it) { std::cerr << "\t" << *it << std::endl; } } else { std::cout << "Found foo.cfg: " << fooCfgPath << std::endl; std::cout << "Contents: " << std::endl; char buf[250]; std::ifstream ifs; // Set stream to the right charset ifs.imbue(std::locale()); ifs.open(fooCfgPath.c_str(), std::fstream::in); while (! ifs.eof()) { ifs.getline(buf, 250); std::cout << buf << std::endl; } ifs.close(); } // ... Write back the configuration to userCfgPath std::string userCfgPath = qi::path::userWritableConfPath("foo", "foo.cfg"); std::cout << "Writing config file to: " << userCfgPath << std::endl; std::ofstream ofs(userCfgPath.c_str(), std::fstream::out | std::fstream::trunc); ofs << "Hi, this is foo.cfg" << std::endl; ofs.close(); return 0; }
qi::path documentation.