[CMake] Best way to handle application data path for local run vs. installation

Roger Leigh rleigh at codelibre.net
Wed Dec 2 16:59:19 EST 2015


On 30/11/2015 02:10, Dmitry Marakasov wrote:
> Hi!
>
> This question bugs me for a long time so I though maybe someone has
> a solution. I have a project which includes an application and some
> data for it. An application needs to know path to its data files, so
> I pass it via compiler definition: ADD_DEFINITIONS(-DDATADIR="...")
>
> The problem is that this path is different based on whether I want to
> run the application from build directory:
>
> ADD_DEFINITIONS(-DDATADIR="${PROJECT_SOURCE_DIR}/data")
>
> or want to install it systemwide:
>
> ADD_DEFINITIONS(-DDATADIR="${CMAKE_INSTALL_PREFIX}/share/myapp")
>
> I want my project to both run from build directory and to be
> installable systemwide, without the need to rebuild or specify extra
> options.
>
> Any ideas?

I don't claim this is a universal solution, but it works for me.  It's 
also likely to be further improved--this is the first functional 
implementation.

 
https://github.com/openmicroscopy/bioformats/blob/dev_5_1/cpp/lib/ome/common/module.cpp

While you can configure and use hardcoded install paths, it will also 
optionally introspect itself at runtime and compute the install paths 
dynamically.  This means you can have a relocatable installation and it 
will discover this on the fly.  Lastly, you can overrride each path 
component with an environment variable.  This is used to run inside the 
install tree where the path layout doesn't match the installed layout. 
It's also useful for testing or overriding things after installation, if 
needed, or overriding the autodetection on platforms where autodetection 
doesn't work.

This approach requires this source file to be in a shared library 
(Linux/FreeBSD/MacOS X - using dlopen(3)/dladdr(3)) or in a DLL (Windows 
- uses GetModuleHandleExW()/GetModuleFileNameW()).  It would also work 
in an executable compiled with -rdynamic with suitable adjustment for 
the install path computation.  Other platforms could be added, but this 
covers all my needs at the present.  Basically we get the path to the 
.so/.dylib/.dll, then remove the library runtime path to get the 
installation root, then add on any relative path we need, e.g. the 
datadir or anything else.  This works for system installations or 
relocatable installs anywhere.

This uses the CMake GNUInstallDirs module variables via a generated 
header to store all the paths.


Regards,
Roger


More information about the CMake mailing list