Revision: 77593
          http://sourceforge.net/p/brlcad/code/77593
Author:   starseeker
Date:     2020-10-23 13:08:29 +0000 (Fri, 23 Oct 2020)
Log Message:
-----------
Put new rpath logic in the parent build.

Modified Paths:
--------------
    brlcad/branches/extbuild/misc/CMake/RPath_Setup.cmake

Modified: brlcad/branches/extbuild/misc/CMake/RPath_Setup.cmake
===================================================================
--- brlcad/branches/extbuild/misc/CMake/RPath_Setup.cmake       2020-10-23 
06:42:31 UTC (rev 77592)
+++ brlcad/branches/extbuild/misc/CMake/RPath_Setup.cmake       2020-10-23 
13:08:29 UTC (rev 77593)
@@ -29,57 +29,199 @@
 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+include(CMakeParseArguments)
+
+# Relative path specifiers are platform specific.  Encapsulate them in a
+# function to hide the details from other code.
+function(relative_rpath outvar)
+
+  cmake_parse_arguments(R "" "SUFFIX;LEN" "" ${ARGN})
+
+  if (R_SUFFIX)
+    set(DPATH)
+    set(CPATH "${R_SUFFIX}")
+    while (NOT "${CPATH}" STREQUAL "")
+      set(DPATH "../${DPATH}")
+      get_filename_component(CPATH "${CPATH}" DIRECTORY)
+    endwhile()
+  else ()
+    set(DPATH "../")
+  endif (R_SUFFIX)
+
+  if (APPLE)
+    set(RELATIVE_RPATH ";@loader_path/${DPATH}${LIB_DIR}" PARENT_SCOPE)
+  else (APPLE)
+    set(RELATIVE_RPATH ":\$ORIGIN/${DPATH}${LIB_DIR}" PARENT_SCOPE)
+  endif (APPLE)
+
+  # IFF the caller tells us to, lengthen the relative path to a
+  # specified length.  This is useful in scenarios where the relative
+  # path is the only viable option
+  if (R_LEN)
+    string(LENGTH "${RELATIVE_RPATH}" CURR_LEN)
+    while("${CURR_LEN}" LESS "${R_LEN}")
+      set(RELATIVE_RPATH "${RELATIVE_RPATH}:")
+      string(LENGTH "${RELATIVE_RPATH}" CURR_LEN)
+    endwhile("${CURR_LEN}" LESS "${R_LEN}")
+  endif (R_LEN)
+
+  set(${outvar} "${RELATIVE_RPATH}" PARENT_SCOPE)
+
+endfunction(relative_rpath)
+
+# Set (or restore) a standard BRL-CAD setting for CMAKE_BUILD_RPATH.
+function(std_build_rpath)
+  # If we're in multiconfig mode, we need to look relative to the current
+  # build configuration, not the top level lib directory.
+  if (CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/$<CONFIG>/${LIB_DIR}")
+  else (CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/${LIB_DIR}")
+  endif (CMAKE_CONFIGURATION_TYPES)
+
+  # Done - let the parent know what the answers are
+  set(CMAKE_BUILD_RPATH "${CMAKE_BUILD_RPATH}" PARENT_SCOPE)
+
+  # Set the final install rpath
+  relative_rpath(RELPATH)
+  set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}${RELPATH}" 
PARENT_SCOPE)
+
+endfunction(std_build_rpath)
+
 #---------------------------------------------------------------------
-# The following logic is what allows binaries to run successfully in
-# the build directory AND install directory.  Thanks to plplot for
-# identifying the necessity of setting CMAKE_INSTALL_NAME_DIR on OSX.
-# Documentation of these options is available at
-# http://www.cmake.org/Wiki/CMake_RPATH_handling
+# Settings for CMAKE_RPATH_BUILD that support custom manipulation of
+# external project outputs.
 
-if(NOT COMMAND cmake_set_rpath)
+# TODO - investigate using BUILD_RPATH and INSTALL_RPATH on a per
+# target basis for more precise control (for example, when setting
+# up paths for libs in subdirs...  not sure yet if it could be helpful
+# but should be explored.
 
-  function(cmake_set_rpath)
+# Note in particular that BUILD_RPATH supports generator expressions,
+# in case that's of use to pull other properties on which to base
+# rpaths...
 
-    if(NOT CMAKE_RPATH_SET)
+# Can use set_property:  https://stackoverflow.com/a/40147991
 
-      # We want the full RPATH set in the build tree so we can run programs 
without
-      # needing to set LD_LIBRARY_PATH
-      set(CMAKE_SKIP_BUILD_RPATH FALSE PARENT_SCOPE)
+# To allow CMake to manipulate RPaths, we need to make sure they are all the
+# same length and long enough to hold the longest candidate path we will need.
+#
+# NOTE: Since we haven't yet created any lib subdirectories that may be created
+# by 3rd party builds, we can't check them for explicit length - for now, we
+# use 20 as an upper bound on how long a directory name we might need there,
+# but that will need to be updated in the event a more verbosely named library
+# subdirectory shows up.
+function(longest_rpath outvar)
 
-      # We DON'T want the final install directory RPATH set in the build 
directory
-      # - it should only be set to the installation value when actually 
installed.
-      set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE PARENT_SCOPE)
+  cmake_parse_arguments(R "" "SUFFIX" "" ${ARGN})
 
-      # Set RPATH value to use when installing.  This should be set to always
-      # prefer the version in the installed path when possible, but fall back 
on a
-      # location relative to the loading file's path if the installed version 
is
-      # not present.  How to do so is platform specific.
-      if(NOT APPLE)
-       set(CMAKE_INSTALL_RPATH 
"${CMAKE_INSTALL_PREFIX}/${LIB_DIR}:\$ORIGIN/../${LIB_DIR}" PARENT_SCOPE)
-      else(NOT APPLE)
-       set(CMAKE_INSTALL_RPATH 
"${CMAKE_INSTALL_PREFIX}/${LIB_DIR};@loader_path/../${LIB_DIR}" PARENT_SCOPE)
-      endif(NOT APPLE)
+  # Microsoft platforms don't do RPATH
+  if (MSVC)
+    return()
+  endif (MSVC)
 
-      # On OSX, we need to set INSTALL_NAME_DIR instead of RPATH for CMake < 
3.0
-      # 
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#variable:CMAKE_INSTALL_NAME_DIR
-      # http://www.cmake.org/cmake/help/v3.2/policy/CMP0042.html
-      if ("${CMAKE_VERSION}" VERSION_LESS 3.0)
-       set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}" 
PARENT_SCOPE)
-      endif ("${CMAKE_VERSION}" VERSION_LESS 3.0)
+  # The possible roots are CMAKE_INSTALL_PREFIX and CMAKE_BINARY_DIR.
+  # Find out which is longer
+  string(LENGTH "${CMAKE_INSTALL_PREFIX}" ILEN)
+  string(LENGTH "${CMAKE_BINARY_DIR}" BLEN)
+  if ("${ILEN}" GREATER "${BLEN}")
+    set(ROOT_LEN "${ILEN}")
+  else ("${ILEN}" GREATER "${BLEN}")
+    set(ROOT_LEN "${BLEN}")
+  endif ("${ILEN}" GREATER "${BLEN}")
 
-      # Add the automatically determined parts of the RPATH which point to
-      # directories outside the build tree to the install RPATH
-      set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE PARENT_SCOPE)
+  # Find the longest of the configuration string names
+  # (this will be zero in a non-multiconfig build)
+  set(CONF_LEN 0)
+  foreach(cfg ${CMAKE_CONFIGURATION_TYPES})
+    string(LENGTH "/${cfg}" CLEN)
+    if ("${CLEN}" GREATER "${CONF_LEN}")
+      set(CONF_LEN ${CLEN})
+    endif ("${CLEN}" GREATER "${CONF_LEN}")
+  endforeach(cfg ${CMAKE_CONFIGURATION_TYPES})
 
-      # RPATH setup is now complete
-      set(CMAKE_RPATH_SET 1 PARENT_SCOPE)
+  # The length of LIB_DIR itself needs to be factored in
+  if (R_SUFFIX)
+    string(LENGTH "/${LIB_DIR}/${R_SUFFIX}" LIB_LEN)
+  else (R_SUFFIX)
+    string(LENGTH "/${LIB_DIR}" LIB_LEN)
+  endif (R_SUFFIX)
 
-    endif(NOT CMAKE_RPATH_SET)
+  # Hardcoded estimate of maximum lib subdir length
+  #
+  #  *** UPDATE THIS IF UNABLE TO SET RPATH FOR LIBRARIES IN SUBDIRS ***
+  #
+  set(SUBLIB_LEN 20)
 
-  endfunction(cmake_set_rpath)
+  # Include the relative path specifier length:
+  if (R_SUFFIX)
+    relative_rpath(RELPATH SUFFIX "${R_SUFFIX}")
+  else (R_SUFFIX)
+    relative_rpath(RELPATH)
+  endif (R_SUFFIX)
+  string(LENGTH "${RELPATH}" REL_LEN)
 
-endif(NOT COMMAND cmake_set_rpath)
+  math(EXPR len "${ROOT_LEN} + ${CONF_LEN} + ${LIB_LEN} + ${SUBLIB_LEN} + 
${REL_LEN}")
 
+  set(${outvar} ${len} PARENT_SCOPE)
+
+endfunction(longest_rpath)
+
+
+function(ext_build_rpath)
+
+  # Microsoft platforms don't do RPATH
+  if (MSVC)
+    return()
+  endif (MSVC)
+
+  cmake_parse_arguments(R "" "SUFFIX" "" ${ARGN})
+
+  if (R_SUFFIX)
+    longest_rpath(LLEN SUFFIX "${R_SUFFIX}")
+  else (R_SUFFIX)
+    longest_rpath(LLEN)
+  endif (R_SUFFIX)
+
+  # If we're in multiconfig mode, we want to target the config subdir, not just
+  # the build dir itself.
+  if (CMAKE_CONFIGURATION_TYPES)
+    if (R_SUFFIX)
+      set(BUILD_RPATH "${CMAKE_BINARY_DIR}/$<CONFIG>/${LIB_DIR}/${R_SUFFIX}")
+    else (R_SUFFIX)
+      set(BUILD_RPATH "${CMAKE_BINARY_DIR}/$<CONFIG>/${LIB_DIR}")
+    endif (R_SUFFIX)
+  else (CMAKE_CONFIGURATION_TYPES)
+    if (R_SUFFIX)
+      set(BUILD_RPATH "${CMAKE_BINARY_DIR}/${LIB_DIR}/${R_SUFFIX}")
+    else (R_SUFFIX)
+      set(BUILD_RPATH "${CMAKE_BINARY_DIR}/${LIB_DIR}")
+    endif (R_SUFFIX)
+  endif (CMAKE_CONFIGURATION_TYPES)
+
+  # This is the key to the process - the ":" characters appended to the build
+  # time path result in a path string in the compile outputs that has
+  # sufficient length to hold the install directory, while is what allows
+  # CMake's file command to manipulate the paths.  At the same time, the colon
+  # lengthened paths do not break the functioning of the shorter build path.
+  # Normally this is an internal CMake detail, but we need it to supply to
+  # external build systems so their outputs can be manipulated as if they were
+  # outputs of our own build.
+  string(LENGTH "${BUILD_RPATH}" CURR_LEN)
+  while("${CURR_LEN}" LESS "${LLEN}")
+    set(BUILD_RPATH "${BUILD_RPATH}:")
+    string(LENGTH "${BUILD_RPATH}" CURR_LEN)
+  endwhile("${CURR_LEN}" LESS "${LLEN}")
+
+  # Done - let the parent know what the answers are
+  set(CMAKE_BUILD_RPATH "${BUILD_RPATH}" PARENT_SCOPE)
+
+  # Set the final install rpath
+  relative_rpath(RELPATH)
+  set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}${RELPATH}" 
PARENT_SCOPE)
+
+endfunction(ext_build_rpath)
+
 # Local Variables:
 # tab-width: 8
 # mode: cmake

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to