coin3d / coin

Coin3D core library
BSD 3-Clause "New" or "Revised" License
281 stars 106 forks source link

Relocatable pkg-config and coin-config files #437

Open rickertm opened 3 years ago

rickertm commented 3 years ago

The files Coin.pc used by pkg-config and coin.cfg used by coin-config contain absolute paths which prevent an installation from being moved to another location, even though the latter includes a comment regarding a moveable package. This is also the case for simage, SoQt etc.

The CMake config files are already relocatable, as PACKAGE_PREFIX_DIR is calculated relative to these files via @PACKAGE_INIT@. Something similar could be achieved in Coin.pc by using setting prefix to ${pcfiledir}, see Helping C/C++ Packages be Relocatable. The other variables however would also need to be updated to be relative to prefix.

file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig" "${CMAKE_INSTALL_PREFIX}")
string(REGEX REPLACE "/$" "" PACKAGE_RELATIVE_PATH "${PACKAGE_RELATIVE_PATH}")
set(prefix "\${pcfiledir}/${PACKAGE_RELATIVE_PATH}")

coin-config already seems to calculate prefix based on its location, however the other variables are not defined relative to this.

VolkerEnderlein commented 3 years ago

I just am on the way to prepare point releases (simage 1.8.1, coin 4.0.1, soqt 1.6.1, ...) and therefore also update the .pc files. Starting with simage is this still present in the current simage.pc file? In my understanding of the pkg-config format the prefix is set at build time to the content of the CMAKE_INSTALL_PREFIX variable. As every distribution has its own place where coin|simage|soqt might be installed this should be sufficient. Am I going wrong here?

Another follow up:

According to the man pages of pkg-config from Ubuntu:

   --define-prefix
   --dont-define-prefix
          These  options  control  whether  pkg-config overrides the value of the variable prefix in each .pc file. With --define-prefix,
          pkg-config uses the installed location of the .pc file to determine the prefix. --dont-define-prefix  prevents  this  behavior.
          The default is usually --define-prefix.

          When  this feature is enabled and a .pc file is found in a directory named pkgconfig, the prefix for that package is assumed to
          be the grandparent of the directory where the file was found, and the prefix variable is overridden for that file accordingly.

          If the value of a variable in a .pc file begins with the original, non-overridden, value of the prefix variable, then the over‐
          ridden  value  of prefix is used instead. This allows the feature to work even when the variables have been expanded in the .pc
          file.

My understanding of this is, that if we make everything in the .pc file dependent on the prefix variable and don't put in other absolute paths it will automagically work. This is how I restructured the simage.pc file so far. As we put our .pc files in the correct location under ${prefix}/lib/pkgconfig this should work as intended.

rickertm commented 3 years ago

The updated pkg-config files in simage look much better, all path variables are now defined relative to prefix.

Regarding the prefix variable in a pkg-config file: this should either point to the absolute path of the installation or use ${pcfiledir} to make it relocatable. The value in CMAKE_INSTALL_PREFIX may not necessarily be identical to the location on disk even without moving it to a new location, e.g., if make DESTDIR=/tmp install is used. This happens after the CMake configure step and is therefore not visible at this time. Even though pkg-config's man page states that --define-prefix is the default behavior, this doesn't always seem to be the case, see the examples below:

$ cmake -DCMAKE_INSTALL_PREFIX=/usr
$ make DESTDIR=/tmp install
$ cat /tmp/usr/lib/x86_64-linux-gnu/pkgconfig/simage.pc
prefix=/usr
...
$ PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_PATH=/tmp/usr/lib/x86_64-linux-gnu/pkgconfig pkg-config --libs simage
-L/usr/lib/x86_64-linux-gnu -lsimage
$ PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_PATH=/tmp/usr/lib/x86_64-linux-gnu/pkgconfig pkg-config --libs simage --define-prefix
-L/tmp/usr/lib/lib/x86_64-linux-gnu -lsimage

Here, the option --define-prefix is not used by default and leads to an incorrect value. Modifying prefix in simage.pc to use ${pcfiledir}/../../.. results in the correct value for both cases:

$ PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_PATH=/tmp/usr/lib/x86_64-linux-gnu/pkgconfig pkg-config --libs simage
-L/tmp/usr/lib/x86_64-linux-gnu/pkgconfig/../../../lib/x86_64-linux-gnu -lsimage
$ PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_PATH=/tmp/usr/lib/x86_64-linux-gnu/pkgconfig pkg-config --libs simage --define-prefix 
-L/tmp/usr/lib/lib/x86_64-linux-gnu -lsimage

Another example that uses stow after installation to /usr/local/stow/simage:

$ cmake -DCMAKE_INSTALL_PREFIX=/usr/local/stow
$ make install
$ cat /usr/local/lib/pkgconfig/simage.pc
prefix=/usr/local/stow/simage
...
$ stow simage
$ pkg-config --libs simage
-L/usr/local/stow/simage/lib -lsimage
$ pkg-config --libs simage --define-prefix 
-L/usr/local/lib -lsimage

Again, the option --define-prefix is not used by default. In this case, both values are correct, however the second one resolves the link from /usr/local/stow/simage to /usr/local. With prefix set to ${pcfiledir}/../.. this results in:

$ pkg-config --libs simage
-L/usr/local/lib/pkgconfig/../../lib -lsimage
$ pkg-config --libs simage --define-prefix 
-L/usr/local/lib -lsimage
VolkerEnderlein commented 3 years ago

Thank you for the valuable explanations and the research about the behavior. I checked the pcfiledir variable and the oldest document mentioning it was found here (2007!). It seems to have been existent for a very long time but undocumented.

rickertm commented 3 years ago

pcfiledir seems to be the best option, as I just noticed another issue with --define-prefix. The man page states

When this feature is enabled and a .pc file is found in a directory named pkgconfig, the prefix for that package is assumed to be the grandparent of the directory where the file was found, and the prefix variable is overridden for that file accordingly.

As can be seen in the examples above, this is not always correct, With an installation into /usr, at least on Debian-based systems, the folder hierarchy is lib/x86_64-linux-gnu/pkgconfig instead of just lib/pkgconfig, therefore resulting in the incorrect value of -L/tmp/usr/lib/lib/x86_64-linux-gnu.