CMake with multilib support on Linux

Multilib distributions tend to put their architecture-specific binaries in /usr/lib64 directories to provide i686 compatibility through legacy /usr/lib directory. This means that if you ever have to deal with binaries compiled against 32-bit architectures, you can install their compatibility versions through your package manager which will reside in /usr/lib. These compatibility packages have a .i686 suffix on Fedora.

Let’s say that you have a 32-bit binary which requires libXrender. After installing libXrender.i686 with yum, take a look at package contents:

$ rpm -ql libXrender.i686
/usr/lib/libXrender.so.1
/usr/lib/libXrender.so.1.3.0
/usr/share/doc/libXrender-0.9.7
/usr/share/doc/libXrender-0.9.7/AUTHORS
/usr/share/doc/libXrender-0.9.7/COPYING
/usr/share/doc/libXrender-0.9.7/ChangeLog

This makes clear that if you build a project from its source tarball or SCM tree, you don’t want to install them under /usr/lib for keeping things clean. This is also a requirement if you prepare an RPM for that application/library. On Fedora, macros.cmake in /etc/rpm checks the system and sets a CMake variable LIB_SUFFIX to 64 for further using it in CMakeLists.txt. All you have to do is to append this suffix in your project to relevant places. But this solution is limited to builds initiated by rpmbuild as it triggers the macro inclusion.

If you would like to apply a more global solution, CMake provides a module called GNUInstallDirs. You can include that and use the CMake variable CMAKE_INSTALL_LIBDIR when appropriate. The value of this variable is lib64 on multilib x86_64 installations. A quick fix for a a Python module installation looks something like this:

diff --git a/src/python.cmake b/src/python.cmake
index e1d1e20..30815e9 100644
--- a/src/python.cmake
+++ b/src/python.cmake
@@ -83,7 +83,7 @@ endif()
 
# Finally, we setup the python installation prefix centrally. This value is
# standardized by Python as defined in http://docs.python.org/install/index.html
-set(PYTHON_SITE_PACKAGES "lib/python${PYTHON_VERSION}/site-packages" CACHE
+set(PYTHON_SITE_PACKAGES "${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION}/site-packages" CACHE
  PATH "Default package installation prefix for Python packages")