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