This PR looks bigger than it actually is since it builds on #182. (The last 2 commits are the only ones that introduce changes).
This was split off from #182 because these changes are not strictly required to build Grackle with cmake. These changes exist to add support for installing metadata files that can be used to help downstream applications link against a grackle installation. There are 2 types of metadata files.
pkg-config file: grackle.pc
This file can be used by downstream projects build with any build system. The only requirement to use these files is having the pkg-config utility or pkgconf utility (an alternative implementation) installed. Both of these utilities are run at the command-line.
The downstream build can execute a number of useful commands:
pkg-config --modversion grackle prints the grackle-version (note that we have stripped the -dev suffix to allow for using pkg-config to search for a particular version)
pkg-config --cflags grackle queries required compile-time flags (really just the -I flag -- but historically, this would be more useful)
pkg-config --libs grackle provides the linker flags needed for linking against libgrackle.so. This is just the -L/path/to/loc and -l flags. It's REALLY uninteresting especially since cmake properly handles the openmp runtime linking for shared libraries.
pkg-config --libs --static grackle provides the linker flags needed for linking against libgrackle.a.
this is perhaps the most important thing here!
Linking some codes (like Enzo) against statically compiled grackle might just "work out" without any manual intervention. But, that's because they share the same dependencies (it's sort of a happy accident).
In other codes, the extra dependencies need to be manually specified:
a code must make sure it's linking against -lhdf5 (usually NOT a problem)
a code without any fortran needs to make sure it links against the relevant Fortran runtime directories (can be a problem)
if grackle is compiled with openmp and the downstream application isn't using openmp, the downstream library needs to link against the openmp runtime libraries (can definitely be a tricky problem)
We have provided some extra non-standard grackle-specific variables:
pkg-config --variable=GRACKLE_VERSION_STR grackle prints the full version-string
pkg-config --variable=GRACKLE_USE_DOUBLE grackle prints whether grackle was compiled with double-precision
pkg-config --variable=GRACKLE_USE_OPENMP grackle prints whether grackle was compiled with openmp
the one caveat is that when grackle isn't installed in a standard location, the downstream build system (or the downstream user) will need to specify the location by modifying the PKG_CONFIG_PATH environment variable.
CMake Package Config File: GrackleConfig.cmake
Downstream applications built with cmake (that don't want to directly embed the grackle build within their build) can make use of this file (plus a handful of related auto-generated files).
This basically conveys all the same information as the grackle.pc file, but has some theoretical advantages. In grackle's current form, these advantage don't matter much and this format is provided mostly as a convenience (it makes integration of grackle into a downstream cmake MUCH more seamless).
For posterity, the theoretical disadvantages of pkg-config (that cmake addresses) are:
pkg-config directly specifies compiler flags. This may involve making some assumptions about the compiler and linker toolchains that a downstream project linking to grackle will employ:
since usage of libgrackle.a or libgrackle.so currently only requires -l, -L, and -I flags this is basically a non-issue
problems arise when you need to pass toolchain-specific flags. In other words, you essentially need to assume that the downstream application uses the same compiler and linker tool chains (which is definitely reasonable). But again, this is mostly academic for us right now.[^1]
it could become more of an issue when we add GPU support
if you had multiple grackle installations on your machine, there's a remote chance (based on your -L flags) that you could end up with a mismatch between the grackle header and grackle shared library (this really isn't an issue for grackle)
Other thoughts
If we ultimately decide not to use cmake, it would probably make a lot of sense to rework most of this and try to work it into the existing build-system (with that said, I'm a little skeptical that we could get robust-generalized-solutions without significantly more work)
[^1]: Technically, there is very specific, rare edge-case right now related to use libgrackle.a compiled with OpenMP that could arise if we didn't use cmake to build the package-config file. Currently, we use CMake to identify the exact runtime-openmp libraries that need to be linked (so we can convert those requirements to -L and -l arguments). If we weren't using openmp, we would need to list the openmp compiler-specific flag in grackle.pc's linker arguments (so -fopenmp for gcc/clang or -qopenmp for intel, -qsmp=omp for ibm, -mp for pgi). If the downstream application didn't use openmp outside of grackle, problems would arise if they directly invoked ld for linking or uses a different compiler toolchain altogether. (If the downstream application did use openmp outside of grackle, this would be a non-issue). This would be extremely rare, and I'd be fine with it... But, this is mostly to provide a concrete example
This PR looks bigger than it actually is since it builds on #182. (The last 2 commits are the only ones that introduce changes).
This was split off from #182 because these changes are not strictly required to build Grackle with cmake. These changes exist to add support for installing metadata files that can be used to help downstream applications link against a grackle installation. There are 2 types of metadata files.
pkg-config file:
grackle.pc
This file can be used by downstream projects build with any build system. The only requirement to use these files is having the pkg-config utility or
pkgconf
utility (an alternative implementation) installed. Both of these utilities are run at the command-line.The downstream build can execute a number of useful commands:
pkg-config --modversion grackle
prints the grackle-version (note that we have stripped the-dev
suffix to allow for using pkg-config to search for a particular version)pkg-config --cflags grackle
queries required compile-time flags (really just the-I
flag -- but historically, this would be more useful)pkg-config --libs grackle
provides the linker flags needed for linking againstlibgrackle.so
. This is just the-L/path/to/loc
and-l
flags. It's REALLY uninteresting especially since cmake properly handles the openmp runtime linking for shared libraries.pkg-config --libs --static grackle
provides the linker flags needed for linking againstlibgrackle.a
.-lhdf5
(usually NOT a problem)pkg-config --variable=GRACKLE_VERSION_STR grackle
prints the full version-stringpkg-config --variable=GRACKLE_USE_DOUBLE grackle
prints whether grackle was compiled with double-precisionpkg-config --variable=GRACKLE_USE_OPENMP grackle
prints whether grackle was compiled with openmpPKG_CONFIG_PATH
environment variable.CMake Package Config File:
GrackleConfig.cmake
Downstream applications built with cmake (that don't want to directly embed the grackle build within their build) can make use of this file (plus a handful of related auto-generated files).
This basically conveys all the same information as the
grackle.pc
file, but has some theoretical advantages. In grackle's current form, these advantage don't matter much and this format is provided mostly as a convenience (it makes integration of grackle into a downstream cmake MUCH more seamless).For posterity, the theoretical disadvantages of pkg-config (that cmake addresses) are:
libgrackle.a
orlibgrackle.so
currently only requires-l
,-L
, and-I
flags this is basically a non-issue-L
flags) that you could end up with a mismatch between the grackle header and grackle shared library (this really isn't an issue for grackle)Other thoughts
If we ultimately decide not to use cmake, it would probably make a lot of sense to rework most of this and try to work it into the existing build-system (with that said, I'm a little skeptical that we could get robust-generalized-solutions without significantly more work)
[^1]: Technically, there is very specific, rare edge-case right now related to use
libgrackle.a
compiled with OpenMP that could arise if we didn't use cmake to build the package-config file. Currently, we use CMake to identify the exact runtime-openmp libraries that need to be linked (so we can convert those requirements to-L
and-l
arguments). If we weren't using openmp, we would need to list the openmp compiler-specific flag ingrackle.pc
's linker arguments (so-fopenmp
for gcc/clang or-qopenmp
for intel,-qsmp=omp
for ibm,-mp
for pgi). If the downstream application didn't use openmp outside of grackle, problems would arise if they directly invokedld
for linking or uses a different compiler toolchain altogether. (If the downstream application did use openmp outside of grackle, this would be a non-issue). This would be extremely rare, and I'd be fine with it... But, this is mostly to provide a concrete example