From cbdd8182db13972d80edd1825a83a41b9b1bc98f Mon Sep 17 00:00:00 2001
From: Markus Blatt <markus@dr-blatt.de>
Date: Tue, 7 Jan 2014 15:41:27 +0100
Subject: [PATCH] [cmake,release] Correctly treat multiarch triplets in Debian.

Debian uses multiarch-triplets (e.g. i386-gnu-linux) when installing
object libraries. These are installed to lib/$multiarch-triplet and not
to lib directly. In CMake this concept is partially supported by
GNUInstallDirs.cmake by setting CMAKE_INSTALL_LIBDIR to
lib/$multiarch-triplet. Unfortunately, this is only half the way through
as we also install libraries that do not differ between architectures (e.g.
our shell libraries.

This patch addes multiarch support for CMake to the best of my knowledge,
which might be limited, though:

- All not architecture dependent libraries are installed below the variable
  DUNE_INSTALL_NONOBJECTLIBDIR, which defaults to lib, but might be adjusted
  by the user.
- If the module ships an object library then the pkg-config and CMake package
  configuration files are installed in lib/$multiarch-triplet/pkg-config and
  lib/$multiarch-triplet/cmake/modules, respectively.
- If not then they are installed in lib/pkg-config and
  lib/cmake/modules, respectively.

Note that for autotool no such difference exists and always the latter approach
is used.
---
 bin/dunecontrol                   | 73 ++++++++++++++++++++++++-------
 cmake/modules/DuneMacros.cmake    | 37 ++++++++++++----
 cmake/modules/DunePkgConfig.cmake | 62 +++++++++++++-------------
 3 files changed, 118 insertions(+), 54 deletions(-)

diff --git a/bin/dunecontrol b/bin/dunecontrol
index 513ef5b0f..9ce68c1e9 100755
--- a/bin/dunecontrol
+++ b/bin/dunecontrol
@@ -78,17 +78,6 @@ if test "x$DEBUG" = "xyes"; then
   set -v
 fi
 
-export PREFIX_DIR="`canonicalpath "$0"`/.."
-
-# create PKG_CONFIG_PATH for installed dune modules
-if test -d "$PREFIX_DIR/lib/pkgconfig"; then
-  export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$PREFIX_DIR/lib/pkgconfig"
-fi
-
-# Read the modules find part
-. "$PREFIX_DIR/lib/dunemodules.lib"
-
-###############################################
 
 onbuildfailure() {
   echo "Terminating $(basename "$0") due to previous errors!" >&2
@@ -218,6 +207,54 @@ load_opts() {
   fi
 }
 
+# Uses the current compiler to extract information about the
+# multiarch triplets and sets the export variable MULTIARCH_LIBDIR
+# according to it.
+# If not compiler is specified then cc or gcc is used.
+extract_multiarch(){
+  local my_cxx_compiler
+  if test "x$MULTIARCH_LIBDIR" != "x"; then
+    return
+  fi
+  if test "x$USE_CMAKE" = "xyes"; then
+    load_opts "cmake"
+    my_cxx_compiler=`echo $CMAKE_FLAGS | sed "s/.*\(-DCMAKE_CXX_COMPILER[:FILEPATH]*=\"[^\"]*\"\|$i='[^']*'\|$i=[^\s^ ]*\).*/\1/"`
+  fi
+  if test "x$my_cxx_compiler" == "x"; then
+    load_opts "configure"
+    my_cxx_compiler=`echo $CONFIGURE_FLAGS | sed "s/.*\(CXX=\"[^\"]*\"\|$i='[^']*'\|$i=[^\s^ ]*\).*/\1/"`
+  fi
+  if test "x$my_cxx_compiler" == "x"; then
+    set +e
+    $(which cc &>/dev/null)
+    if test $? -eq "0"; then
+      my_cxx_compiler=cc
+    else
+      my_cxx_compiler=gcc
+    fi
+  fi
+  set -e
+  export MULTIARCH_LIBDIR="lib/$($my_cxx_compiler --print-multiarch)"
+}
+
+export PREFIX_DIR="`canonicalpath "$0"`/.."
+
+extract_multiarch
+
+# create PKG_CONFIG_PATH for installed dune modules
+for i in $MULTIARCH_LIBDIR lib64 lib32 lib; do
+  if test -d "$PREFIX_DIR/$i/pkgconfig"; then
+    export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$PREFIX_DIR/$i/pkgconfig"
+    break;
+  fi
+done
+
+# Read the modules find part
+. "$PREFIX_DIR/lib/dunemodules.lib"
+
+###############################################
+
+
 ###############################################
 ###
 ### Commands
@@ -555,6 +592,7 @@ run_default_autogen () {
 }
 
 run_default_configure () {
+  extract_multiarch
   PARAMS="$CMD_FLAGS"
   if test "x$USE_CMAKE" = "xyes" && test -e "$(eval "echo \$PATH_$module")/CMakeLists.txt"; then
     LOCAL_USE_CMAKE=yes
@@ -595,11 +633,14 @@ run_default_configure () {
           if test -d "$path/$BUILDDIR"; then
 	      CMAKE_PARAMS="$CMAKE_PARAMS \"-D""$name""_DIR=$path/$BUILDDIR\""
           else
-              if test -d "$path/lib/cmake/$name"; then
-                  CMAKE_PARAMS="$CMAKE_PARAMS \"-D""$name""_DIR=$path/lib/cmake/$name\""
-              else
-                  CMAKE_PARAMS="$CMAKE_PARAMS \"-D""$name""_DIR=$path\""
-              fi
+	      TMP_PARAMS="\"-D""$name""_DIR=$path\""
+	      for i in $MULTIARCH_LIBDIR lib lib64 lib32; do
+		  if test -d "$path/$i/cmake/$name"; then
+                      TMP_PARAMS="\"-D""$name""_DIR=$path/$i/cmake/$name\""
+		      break;
+		  fi
+	      done
+	      CMAKE_PARAMS="$CMAKE_PARAMS $TMP_PARAMS"
           fi
       fi
     done
diff --git a/cmake/modules/DuneMacros.cmake b/cmake/modules/DuneMacros.cmake
index e7af3b044..cb3299e6b 100644
--- a/cmake/modules/DuneMacros.cmake
+++ b/cmake/modules/DuneMacros.cmake
@@ -139,7 +139,7 @@ endfunction(convert_deps_to_list var)
 macro(dune_module_information MODULE_DIR)
   file(READ "${MODULE_DIR}/dune.module" DUNE_MODULE)
 
-  # find version string
+  # find version strings
   extract_line("Version:" MODULE_LINE "${DUNE_MODULE}")
   if(NOT MODULE_LINE)
     message(FATAL_ERROR "${MODULE_DIR}/dune.module is missing a version.")
@@ -529,7 +529,12 @@ macro(dune_project)
       "Installation directory for CMake modules. Default is \${CMAKE_INSTALL_DATAROOTDIR}/dune/cmake/modules when not set explicitely")
     set(DUNE_INSTALL_MODULEDIR ${CMAKE_INSTALL_DATAROOTDIR}/dune/cmake/modules)
   endif(NOT DUNE_INSTALL_MODULEDIR)
-
+  if(NOT DUNE_INSTALL_NONOBJECTLIBDIR)
+    set(DUNE_INSTALL_NONOBJECTLIBDIR ""
+      CACHE PATH
+      "Installation directory for libraries that are not architecture dependent. Default is lib when not set explicitely")
+    set(DUNE_INSTALL_NONOBJECTLIBDIR lib)
+  endif(NOT DUNE_INSTALL_NONOBJECTLIBDIR)
   # set up make headercheck
   include(Headercheck)
   setup_headercheck()
@@ -631,9 +636,22 @@ endif(NOT @DUNE_MOD_NAME@_FOUND)")
     set(CONFIG_SOURCE_FILE ${PROJECT_SOURCE_DIR}/cmake/pkg/${DUNE_MOD_NAME}-config.cmake.in)
   endif(NOT EXISTS ${PROJECT_SOURCE_DIR}/cmake/pkg/${DUNE_MOD_NAME}-config.cmake.in)
   get_property(DUNE_MODULE_LIBRARIES GLOBAL PROPERTY DUNE_MODULE_LIBRARIES)
+
+  # compute under which libdir the package configuration files are to be installed.
+  # If the module installs an object library we use CMAKE_INSTALL_LIBDIR
+  # to capture the multiarch triplet of Debian/Ubuntu.
+  # Otherwise we fall back to DUNE_INSTALL_NONOBJECTLIB which is lib
+  # if not set otherwise.
+  get_property(DUNE_MODULE_LIBRARIES GLOBAL PROPERTY DUNE_MODULE_LIBRARIES)
+  if(DUNE_MODULE_LIBRARIES)
+    set(DUNE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
+  else(DUNE_MODULE_LIBRARIES)
+    set(DUNE_INSTALL_LIBDIR ${DUNE_INSTALL_NONOBJECTLIBDIR})
+  endif(DUNE_MODULE_LIBRARIES)
+
   configure_package_config_file(${CONFIG_SOURCE_FILE}
     ${PROJECT_BINARY_DIR}/cmake/pkg/${DUNE_MOD_NAME}-config.cmake
-    INSTALL_DESTINATION  lib/cmake/${DUNE_MOD_NAME}
+    INSTALL_DESTINATION  ${DUNE_INSTALL_LIBDIR}/cmake/${DUNE_MOD_NAME}
     PATH_VARS CMAKE_INSTALL_DATAROOTDIR DUNE_INSTALL_MODULEDIR CMAKE_INSTALL_INCLUDEDIR
     DOXYSTYLE_DIR SCRIPT_DIR)
 
@@ -702,18 +720,21 @@ endif()
     ${PROJECT_BINARY_DIR}/${DUNE_MOD_NAME}-version.cmake @ONLY)
 
   #install dune.module file
-  install(FILES dune.module DESTINATION lib/dunecontrol/${DUNE_MOD_NAME})
+  install(FILES dune.module DESTINATION ${DUNE_INSTALL_NONOBJECTLIBDIR}/dunecontrol/${DUNE_MOD_NAME})
 
-  #install cmake-config files
+  # install cmake-config files
   install(FILES ${PROJECT_BINARY_DIR}/cmake/pkg/${DUNE_MOD_NAME}-config.cmake
     ${PROJECT_BINARY_DIR}/${DUNE_MOD_NAME}-version.cmake
-    DESTINATION lib/cmake/${DUNE_MOD_NAME})
+    DESTINATION ${DUNE_INSTALL_LIBDIR}/cmake/${DUNE_MOD_NAME})
 
   #install config.h
   if(EXISTS ${CMAKE_SOURCE_DIR}/config.h.cmake)
   install(FILES config.h.cmake DESTINATION share/${DUNE_MOD_NAME})
   endif(EXISTS ${CMAKE_SOURCE_DIR}/config.h.cmake)
 
+  #install pkg-config files
+  create_and_install_pkconfig(${DUNE_INSTALL_LIBDIR})
+
   if("${ARGC}" EQUAL "1")
     message(STATUS "Adding custom target for config.h generation")
     dune_regenerate_config_cmake()
@@ -883,9 +904,9 @@ macro(dune_add_library basename)
       endif(NOT _MODULE_EXPORT_USED)
       # install targets to use the libraries in other modules.
       install(TARGETS ${_created_libs}
-        EXPORT ${DUNE_MOD_NAME}-targets DESTINATION lib)
+        EXPORT ${DUNE_MOD_NAME}-targets DESTINATION ${CMAKE_INSTALL_LIBDIR})
       install(EXPORT ${DUNE_MOD_NAME}-targets
-        DESTINATION lib/cmake/${DUNE_MOD_NAME})
+        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${DUNE_MOD_NAME})
 
       # export libraries for use in build tree
       export(TARGETS ${_created_libs} ${_append}
diff --git a/cmake/modules/DunePkgConfig.cmake b/cmake/modules/DunePkgConfig.cmake
index 0b6e3fa87..a917b33e5 100644
--- a/cmake/modules/DunePkgConfig.cmake
+++ b/cmake/modules/DunePkgConfig.cmake
@@ -5,37 +5,39 @@
 
 find_package(PkgConfig)
 
-# set some variables that are used in the pkg-config file
-set( prefix ${CMAKE_INSTALL_PREFIX})
-set(exec_prefix "\${prefix}")
-set(libdir "\${exec_prefix}/lib")
-set(includedir "\${prefix}/include")
-set(PACKAGE_NAME ${DUNE_MOD_NAME})
-set(VERSION ${DUNE_MOD_VERSION})
-set(CC ${CMAKE_C_COMPILER})
-set(CXX "${CMAKE_CXX_COMPILER} ${CXX_STD11_FLAGS}")
+function(create_and_install_pkconfig installlibdir)
+  # set some variables that are used in the pkg-config file
+  include(GNUInstallDirs)
+  set( prefix ${CMAKE_INSTALL_PREFIX})
+  set(exec_prefix "\${prefix}")
+  set(libdir "\${exec_prefix}/${installlibdir}")
+  set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
+  set(PACKAGE_NAME ${DUNE_MOD_NAME})
+  set(VERSION ${DUNE_MOD_VERSION})
+  set(CC ${CMAKE_C_COMPILER})
+  set(CXX "${CMAKE_CXX_COMPILER} ${CXX_STD11_FLAGS}")
 
-if(DUNE_DEPENDS)
-  foreach(_DUNE_DEPEND ${DUNE_DEPENDS})
-    string(REGEX REPLACE "\\(" "" REQF1 ${_DUNE_DEPEND})
-    string(REGEX REPLACE "\\)" "" LR ${REQF1})
-    if(REQUIRES)
-      set(REQUIRES "${REQUIRES} ${LR}")
-    else()
-      set(REQUIRES ${LR})
-    endif(REQUIRES)
-  endforeach(_DUNE_DEPEND ${DUNE_DEPENDS})
-endif(DUNE_DEPENDS)
+  if(DUNE_DEPENDS)
+    foreach(_DUNE_DEPEND ${DUNE_DEPENDS})
+      string(REGEX REPLACE "\\(" "" REQF1 ${_DUNE_DEPEND})
+      string(REGEX REPLACE "\\)" "" LR ${REQF1})
+      if(REQUIRES)
+	set(REQUIRES "${REQUIRES} ${LR}")
+      else()
+	set(REQUIRES ${LR})
+      endif(REQUIRES)
+    endforeach(_DUNE_DEPEND ${DUNE_DEPENDS})
+  endif(DUNE_DEPENDS)
 
-#create pkg-config file
-configure_file(
-  ${PROJECT_SOURCE_DIR}/${DUNE_MOD_NAME}.pc.in
-  ${PROJECT_BINARY_DIR}/${DUNE_MOD_NAME}.pc
-  @ONLY
-)
+  #create pkg-config file
+  configure_file(
+    ${PROJECT_SOURCE_DIR}/${DUNE_MOD_NAME}.pc.in
+    ${PROJECT_BINARY_DIR}/${DUNE_MOD_NAME}.pc
+    @ONLY
+    )
 
-# install pkgconfig file
-if(PKG_CONFIG_FOUND)
+  # install pkgconfig file
   install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DUNE_MOD_NAME}.pc
-    DESTINATION lib/pkgconfig)
-endif(PKG_CONFIG_FOUND)
+    DESTINATION ${installlibdir}/pkgconfig)
+
+endfunction(create_and_install_pkconfig)
-- 
GitLab