From df768ec8a97adb82947fc4b92a199db9a38c044c Mon Sep 17 00:00:00 2001
From: Kimball Thurston <kdt3rd@gmail.com>
Date: Tue, 5 Nov 2019 23:31:08 +1300
Subject: [PATCH] Fixes #593, others - issues with pyilmbase install

The PyIlmBase install logic was incomplete in cmake. This fixes this:
- computes a relative path from the python paths that can then be used
with CMAKE_INSTALL_PREFIX to install python modules to an appropriate
location (can be manually configured as well, install docs updated)
- Fixes #604, pyilmbaseconfig was also not being installed properly

Signed-off-by: Kimball Thurston <kdt3rd@gmail.com>
---
 INSTALL.md                          | 18 ++++++++++++--
 PyIlmBase/CMakeLists.txt            | 38 ++++++++++++++++++++++++++++-
 PyIlmBase/config/CMakeLists.txt     | 32 ++++++++++++------------
 PyIlmBase/config/ModuleDefine.cmake |  4 +--
 4 files changed, 71 insertions(+), 21 deletions(-)

diff --git a/INSTALL.md b/INSTALL.md
index fee631e355..71fa52794f 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -216,11 +216,11 @@ You can customize these options three ways:
 
 * **ILMBASE\_LIB\_SUFFIX**
 
-  Append the given string to the end of all the llmBase libraries. Default is ``-<major>_<minor>`` version string. Please see the section on library names
+  Append the given string to the end of all the IlmBase libraries. Default is ``-<major>_<minor>`` version string. Please see the section on library names
 
 * **OPENEXR\_LIB\_SUFFIX**
 
-  Append the given string to the end of all the llmBase libraries. Default is ``-<major>_<minor>`` version string. Please see the section on library names
+  Append the given string to the end of all the OpenEXR libraries. Default is ``-<major>_<minor>`` version string. Please see the section on library names
 
 ### Namespace Options:
 
@@ -264,8 +264,22 @@ You can customize these options three ways:
  
   Whether the namespace has been customized (so external users know)
 
+### Python Options:
+
+* **PyIlmBase\_Python2\_SITEARCH\_REL**
+
+  This will normally be computed based on where the python2 binary and site-packages live and
+  then be a relative path based on the root of those. For example, if site-packages is in
+  ``/usr/lib/python2.7/site-packages`` and the python binary is ``/usr/bin/python2.7``, this
+  will result in the default install path being ``${CMAKE\_INSTALL\_PREFIX}/lib/python2.7/site-packages``
+
+* **PyIlmBase\_Python3\_SITEARCH\_REL**
+
+  Identical logic to PyIlmBase\_Python2\_SITEARCH\_REL path above, but for python 3.x
+
 ### Linting Options:
 
+These linting options are experimental, and primarily for developer-only use at this time.
 
 * **ILMBASE\_USE\_CLANG\_TIDY**
  
diff --git a/PyIlmBase/CMakeLists.txt b/PyIlmBase/CMakeLists.txt
index 0ee305a845..0c6c7f974d 100644
--- a/PyIlmBase/CMakeLists.txt
+++ b/PyIlmBase/CMakeLists.txt
@@ -58,11 +58,46 @@ endif()
 if (TARGET Python2::Python)
   set(PYILMBASE_BOOST_PY2_COMPONENT "python${Python2_VERSION_MAJOR}${Python2_VERSION_MINOR}")
   message(STATUS "Found Python2 libraries: ${Python2_VERSION_MAJOR}${Python2_VERSION_MINOR}")
-  # ${Python2_SITELIB}
+  # we can't just use the Python2_SITEARCH variable as that then will
+  # ignore CMAKE_INSTALL_PREFIX. Could extract this to a function somewhere
+  # if it is generally useful
+  get_filename_component(_exedir ${Python2_EXECUTABLE} DIRECTORY)
+  string(FIND ${Python2_SITEARCH} ${_exedir} _findloc)
+  string(LENGTH ${_exedir} _elen)
+  while(_findloc EQUAL -1 AND _elen GREATER 0)
+    get_filename_component(_exedir ${_exedir} DIRECTORY)
+    string(FIND ${Python2_SITEARCH} ${_exedir} _findloc)
+    string(LENGTH ${_exedir} _elen)
+  endwhile()
+  math(EXPR _elen "${_elen}+1")
+  string(SUBSTRING ${Python2_SITEARCH} ${_elen} -1 _reldir)
+  set(PyIlmBase_Python2_SITEARCH_REL ${_reldir} CACHE STRING "Destination sub-folder (relative) for the python 2 modules")
+  unset(_elen)
+  unset(_exedir)
+  unset(_findloc)
+  unset(_reldir)
+  message(STATUS "  -> Installing to: \${CMAKE_INSTALL_PREFIX}/${PyIlmBase_Python2_SITEARCH_REL}")
 endif()
 if (TARGET Python3::Python)
   set(PYILMBASE_BOOST_PY3_COMPONENT "python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}")
   message(STATUS "Found Python3 libraries: ${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}")
+  # and figure out the install root here
+  get_filename_component(_exedir ${Python3_EXECUTABLE} DIRECTORY)
+  string(FIND ${Python3_SITEARCH} ${_exedir} _findloc)
+  string(LENGTH ${_exedir} _elen)
+  while(_findloc EQUAL -1 AND _elen GREATER 0)
+    get_filename_component(_exedir ${_exedir} DIRECTORY)
+    string(FIND ${Python3_SITEARCH} ${_exedir} _findloc)
+    string(LENGTH ${_exedir} _elen)
+  endwhile()
+  math(EXPR _elen "${_elen}+1")
+  string(SUBSTRING ${Python3_SITEARCH} ${_elen} -1 _reldir)
+  set(PyIlmBase_Python3_SITEARCH_REL ${_reldir} CACHE STRING "Destination sub-folder (relative) for the python 3 modules")
+  unset(_elen)
+  unset(_exedir)
+  unset(_findloc)
+  unset(_reldir)
+  message(STATUS "  -> Installing to: \${CMAKE_INSTALL_PREFIX}/${PyIlmBase_Python3_SITEARCH_REL}")
 endif()
 # different flavors of O.S. have multiple versions of python
 # some of them have both. Then for boost, some versions of boost
@@ -71,6 +106,7 @@ endif()
 # let's run a search and see what we get instead of making it
 # an explicit required. The older names are not portable, but
 # we'll do the best we can
+set(Boost_NO_BOOST_CMAKE ON)
 find_package(Boost OPTIONAL_COMPONENTS
   python
   python2
diff --git a/PyIlmBase/config/CMakeLists.txt b/PyIlmBase/config/CMakeLists.txt
index 1e1fa98bb0..8b6c3d34bc 100644
--- a/PyIlmBase/config/CMakeLists.txt
+++ b/PyIlmBase/config/CMakeLists.txt
@@ -8,24 +8,24 @@ configure_file(PyIlmBaseConfigInternal.h.in_cmake ${CMAKE_CURRENT_BINARY_DIR}/Py
 add_library(PyIlmBaseConfig INTERFACE)
 target_include_directories(PyIlmBaseConfig INTERFACE
   $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
+install(TARGETS PyIlmBaseConfig EXPORT ${PROJECT_NAME})
 add_library(PyIlmBase::Config ALIAS PyIlmBaseConfig)
 
 # The main export of the configuration - This is the
 # moral equivalent of a pkg-config file for cmake
 # and replaces the Find*.cmake of the "old" cmake
-if(PYILMBASE_BUILD_SUPPORT_LIBRARIES)
-  include(CMakePackageConfigHelpers)
-  write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
-    VERSION ${PYILMBASE_VERSION}
-    COMPATIBILITY SameMajorVersion
-  )
-  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
-    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
-  )
-  install(EXPORT ${PROJECT_NAME}
-    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
-    FILE ${PROJECT_NAME}Config.cmake
-    NAMESPACE ${PROJECT_NAME}::
-    EXPORT_LINK_INTERFACE_LIBRARIES
-  )
-endif()
+include(CMakePackageConfigHelpers)
+
+write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
+  VERSION ${PYILMBASE_VERSION}
+  COMPATIBILITY SameMajorVersion
+)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
+  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
+)
+install(EXPORT ${PROJECT_NAME}
+  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
+  FILE ${PROJECT_NAME}Config.cmake
+  NAMESPACE ${PROJECT_NAME}::
+  EXPORT_LINK_INTERFACE_LIBRARIES
+)
diff --git a/PyIlmBase/config/ModuleDefine.cmake b/PyIlmBase/config/ModuleDefine.cmake
index e37499797a..57e2eaf1e7 100644
--- a/PyIlmBase/config/ModuleDefine.cmake
+++ b/PyIlmBase/config/ModuleDefine.cmake
@@ -123,7 +123,7 @@ function(PYILMBASE_DEFINE_MODULE modname)
       LIBRARY_OUTPUT_NAME "${modname}"
       DEBUG_POSTFIX ""
     )
-    #### TODO: Define installation rules
+    install(TARGETS ${modname}_python2 DESTINATION ${PyIlmBase_Python2_SITEARCH_REL})
   endif()
 
   if(TARGET Python3::Python AND TARGET Boost::${PYILMBASE_BOOST_PY3_COMPONENT})
@@ -150,6 +150,6 @@ function(PYILMBASE_DEFINE_MODULE modname)
       LIBRARY_OUTPUT_NAME "${modname}"
       DEBUG_POSTFIX ""
     )
-    #### TODO: Define installation rules
+    install(TARGETS ${modname}_python3 DESTINATION ${PyIlmBase_Python3_SITEARCH_REL})
   endif()
 endfunction()