Skip to content

Commit

Permalink
Merge pull request #1573 from opensim-org/macOS_RPATH_relative
Browse files Browse the repository at this point in the history
On macOS, use relative RPATHs to make the installation relocatable.
  • Loading branch information
aymanhab committed Mar 22, 2017
2 parents 4480425 + 6b1996b commit c89138b
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 37 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ script:
- make -j8 install > /dev/null

## Test python wrapping.
# Since we use OPENSIM_COPY_SIMBODY=ON, ensure the Python bindings are not
# relying on the original Simbody libraries but rather the copied ones.
# This should make sure we have the correct RPATH for Simbody on macOS.
- rm -r ~/simbody
# Go to the python wrapping package directory.
- if [ "$WRAP" = "on" ]; then cd $OPENSIM_HOME/lib/python2.7/site-packages; fi
# Run the python tests, verbosely.
Expand Down
11 changes: 9 additions & 2 deletions Bindings/Java/OpenSimJNI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,15 @@ set_source_files_properties(
PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS}")

if(${OPENSIM_USE_INSTALL_RPATH})
set_target_properties(osim${KIT} PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
# TODO @loader_path only makes sense on macOS, so we need to revisit for
# Linux (use $ORIGIN).

# The osim libraries that osimJavaJNI needs are in the same folder as
# osimJavaJNI. Adding @loader_rpath (the \ is to escape the @) to the
# run-path list will let osimJavaJNI find osimTools, etc.
# Use APPEND to include the BTK RPATH, set in CMAKE_INSTALL_RPATH.
set_property(TARGET osim${KIT} APPEND PROPERTY
INSTALL_RPATH "\@loader_path/"
)
endif()

Expand Down
4 changes: 3 additions & 1 deletion Bindings/Python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ macro(OpenSimAddPythonModule)
endif()

if(${OPENSIM_USE_INSTALL_RPATH})
set_target_properties(${_libname} PROPERTIES
# Use APPEND to include the BTK RPATH, set in CMAKE_INSTALL_RPATH.
# TODO test that NOT using APPEND causes BTK to not be found.
set_property(TARGET ${_libname} APPEND PROPERTY
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
)
endif()
Expand Down
68 changes: 37 additions & 31 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,17 @@ from the internet, we turn this option OFF." ON)
set(SIMBODY_HOME $ENV{SIMBODY_HOME} CACHE
PATH "The location of the Simbody installation to use; you can change this. Set as empty to let CMake search for Simbody automatically.")

# TODO rename to OPENSIM_COPY_DEPENDENCIES and handle BTK.
option(OPENSIM_COPY_SIMBODY "Copy Simbody headers and libraries into the
OpenSim installation. This way, you can treat OpenSim and Simbody as one
package, and you only need to set environment variables (e.g., PATH,
LD_LIBRARY_PATH, DYLD_LIBRARY_PATH) for OpenSim. On Windows, this also copies
Simbody dll's and exe's into the OpenSim build directory, so that you don't
need to set PATH to run OpenSim tests and examples; this is done via the
SimbodyFiles project. If OFF, you likely must set those environment variables
for both OpenSim and Simbody." ON)
for both OpenSim and Simbody. To make a distributable installation on macOS,
this should be set to ON to avoid using absolute paths for RPATHs to Simbody
libraries." ON)

option(BUILD_API_ONLY "Build/install only headers, libraries,
wrapping, tests; not applications (opensim, ik, rra, etc.)." OFF)
Expand Down Expand Up @@ -457,39 +460,40 @@ if(${CMAKE_C_COMPILER} MATCHES "cc" OR ${CMAKE_C_COMPILER} MATCHES "clang")
endif()


## On APPLE, use MACOSX_RPATH.
## On Linux, this variable has no effect.
set(OPENSIM_USE_INSTALL_RPATH FALSE)
## RPATH
# If it is necesasry to not put RPATHS in the installed binaries, set
# set CMAKE_SKIP_INSTALL_RPATH to OFF.
if(APPLE)
option(OPENSIM_NO_LIBRARY_PATH_ENV_VAR
"If ON, you don't need to set
DYLD_LIBRARY_PATH (on OSX) to make use of OpenSim's executables.
Instead, we bake the location of OpenSim's libraries into the
executables, so the executables already know where to find the
libraries. This uses the RPATH mechanism." ON)
if(${OPENSIM_NO_LIBRARY_PATH_ENV_VAR})
# CMake 2.8.12 introduced the ability to set RPATH for shared libraries on
# OSX. This helps executables find the libraries they depend on without
# having to set the DYLD_LIBRARY_PATH environment variable.
# The code below is all taken from the link below, and implements the
# scenario "Always use full RPATH".
# http://www.cmake.org/Wiki/CMake_RPATH_handling
# Note: the RPATH won't succeed if the libraries are moved; in this case,
# one will still need to set DYLD_LIBRARY_PATH (or alter the RPATH in the
# executables/libraries that depend on Simbody's libraries).
set(CMAKE_MACOSX_RPATH ON)

# Add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH.
# CMake 2.8.12 introduced the ability to set RPATH for shared libraries
# on OSX. This helps executables find the libraries they depend on
# without having to set the DYLD_LIBRARY_PATH environment variable.
# See http://www.cmake.org/Wiki/CMake_RPATH_handling and `man dydl`.
# We have attempted to make the RPATH work even if the
# installation is relocated (using relative paths), but you may need to
# use DYLD_LIBRARY_PATH (or alter the RPATH using install_name_tool) in
# these cases.
## On Linux, this variable has no effect.
set(CMAKE_MACOSX_RPATH ON)

if(NOT OPENSIM_COPY_SIMBODY)
# Add the automatically determined parts of the RPATH which point
# to directories outside the build tree to the install RPATH.
# If we are copying Simbody into OpenSim's installation, then
# there's no need to link to the libraries in Simbody's original
# installation. Furthermore, we may be distributing OpenSim to
# other computers that will not have our original Simbody
# installation, and so the RPATH would point to a nonexistant
# directory on others' computers.
# TODO handle copying BTK.
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()

# The RPATH to be used when installing, but only if it's not a system
# directory.
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(OPENSIM_USE_INSTALL_RPATH TRUE)
endif()
# Set RPATH so that OpenSim can find its own libraries, but only if
# OpenSim is not installed into a system library directory.
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(OPENSIM_USE_INSTALL_RPATH TRUE)
endif()
endif()
## Add rpath to the binaries on Linux.
Expand Down Expand Up @@ -522,6 +526,7 @@ if(WITH_BTK)
include(${BTK_USE_FILE})
add_definitions(-DWITH_BTK)
CopyDependencyDLLsForWin(BTK ${BTK_INSTALL_PREFIX})
# TODO this should be handled separately between macOS and Linux.
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH};${BTK_LIBRARY_DIRS}")
endif()

Expand Down Expand Up @@ -606,6 +611,7 @@ include_directories("${Simbody_INCLUDE_DIR}")
# Copy files over from the Simbody installation.
# ----------------------------------------------
if(${OPENSIM_COPY_SIMBODY})
# TODO copy BTK as well.

# Install Simbody headers into OpenSim installation.
install(DIRECTORY "${Simbody_INCLUDE_DIR}/"
Expand Down
38 changes: 35 additions & 3 deletions cmake/OpenSimMacros.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,38 @@ function(OpenSimAddLibrary)
DESTINATION ${_INCLUDE_PREFIX}/${_INCLUDE_LIBNAME})
endif()

# RPATH (so that libraries find library dependencies)
if(${OPENSIM_USE_INSTALL_RPATH})
# TODO @loader_path only makes sense on macOS, so we need to revisit
# for Linux (use $ORIGIN).

set(run_path_list "\@loader_path/")
# TODO if/when Simbody and BTK libraries are installed in their own
# directories (not beside OpenSim libraries), we will have to add the
# following (also for BTK; this commented code has not been tested):
#if(${OPENSIM_COPY_SIMBODY})
# file(RELATIVE_PATH lib_dir_to_install_dir
# "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
# "${CMAKE_INSTALL_PREFIX}")
# # The location of Simbody's libraries within the Simbody root.
# file(RELATIVE_PATH simbody_root_dir_to_simbody_lib_dir
# "${SIMBODY_ROOT_DIR}" "${SIMBODY_LIB_DIR}")
# )
# # The location of Simbody's libraries relative to OpenSim's
# # installation root (OPENSIM_INSTALL_SIMBODYDIR does not exist).
# file(install_dir_to_simbody_lib_dir
# "${OPENSIM_INSTALL_SIMBODYDIR}${simbody_root_dir_to_simbody_lib_dir}"
# )
# set(lib_dir_to_simbody_lib_dir
# "${lib_dir_to_install_dir}${install_dir_to_simbody_lib_dir}")
# list(APPEND run_path_list
# "\@loader_path/${lib_dir_to_simbody_lib_dir}")
#endif()
# Use APPEND to include the BTK RPATH, set in CMAKE_INSTALL_RPATH.
set_property(TARGET ${OSIMADDLIB_LIBRARY_NAME} APPEND PROPERTY
INSTALL_RPATH "${run_path_list}"
)
endif()

# Testing.
# --------
Expand Down Expand Up @@ -255,16 +287,16 @@ function(OpenSimAddApplication)

# RPATH (so that the executable finds libraries without using env. vars).
if(${OPENSIM_USE_INSTALL_RPATH})
# TODO @executable_path only makes sense on OSX, so if we use RPATH on
# Linux we'll have to revisit.
# TODO @executable_path only makes sense on macOS, so we need to revisit
# for Linux (use $ORIGIN).

# bin_dir_to_install_dir is most likely "../"
file(RELATIVE_PATH bin_dir_to_install_dir
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}"
"${CMAKE_INSTALL_PREFIX}")
set(bin_dir_to_lib_dir
"${bin_dir_to_install_dir}${CMAKE_INSTALL_LIBDIR}")
set_target_properties(${OSIMADDAPP_NAME} PROPERTIES
set_property(TARGET ${OSIMADDAPP_NAME} APPEND PROPERTY
INSTALL_RPATH "\@executable_path/${bin_dir_to_lib_dir}"
)
endif()
Expand Down

0 comments on commit c89138b

Please sign in to comment.