[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