Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 642668 - cmake-utils.eclass: Adjust rpath settings for macOS and current LLVM/clang
Summary: cmake-utils.eclass: Adjust rpath settings for macOS and current LLVM/clang
Status: RESOLVED FIXED
Alias: None
Product: Gentoo/Alt
Classification: Unclassified
Component: Prefix Support (show other bugs)
Hardware: All OS X
: Normal normal (vote)
Assignee: Gentoo Prefix
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-12-29 19:31 UTC by Michael Weiser
Modified: 2018-03-02 08:47 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Attachments
Proposed change to cmake-utils.eclass (cmake-utils.eclass.patch,803 bytes, patch)
2017-12-29 19:31 UTC, Michael Weiser
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Weiser 2017-12-29 19:31:19 UTC
cmake-utils.eclass currently forces the following settings for cmake projects:

SET(CMAKE_PREFIX_PATH "${EPREFIX}/usr" CACHE STRING "" FORCE)
SET(CMAKE_SKIP_BUILD_RPATH OFF CACHE BOOL "" FORCE)
SET(CMAKE_SKIP_RPATH OFF CACHE BOOL "" FORCE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE CACHE BOOL "")
SET(CMAKE_INSTALL_RPATH "${EPREFIX}/usr/lib;${EPREFIX}/usr/${CHOST}/lib/gcc;${EPREFIX}/usr/${CHOST}/lib;${EPREFIX}/usr/$(get_libdir);${EPREFIX}/$(get_libdir)" CACHE STRING "" FORCE)
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE BOOL "" FORCE)
SET(CMAKE_INSTALL_NAME_DIR "${EPREFIX}/usr/lib" CACHE STRING "" FORCE)

1. These are influenced by another setting that is not explicitly set: CMAKE_MACOSX_RPATH[1]:

For cmake projects compatible with cmake older than 3.0 this defaults to OFF, using static, non-relocatable install names for dylibs. In this mode, setting CMAKE_INSTALL_NAME_DIR takes effect and forces the directory part of all install names to be the EPREFIX/usr/lib directory. This seems to work well although it might break with projects that install their libraries somewhere else and do not override that setting themselves. This is relevant because of the cmake_minimum_required(VERSION 2.x.y) setting in CMakeLists.txt of a project may keep this the default even with cmake 3.[2]

For projects requiring cmake 3+ the default changes to ON, using @rpath in install names in dylibs. This requires rpaths to be added to all binaries linking against these libraries. cmake handles that through setting CMAKE_INSTALL_RPATH_USE_LINK_PATH[3]. However this only works on projects built using cmake and only for libraries, cmake knows about. Since e.g. -lc++ is transparently added by the C++ compiler, some rpaths may still be missing in the end. Non-cmake packages have to add -Wl,-rpath options themselves (which at least texlive does not do for libpoppler). This is exacerbated by binutils-config's ldwrapper making libraries in EPREFIX{,/usr}/lib linkable without -L so that some packages might not add -Wl,-rpath for them.

Possible workarounds:
a. Force CMAKE_MACOSX_RPATH OFF for all cmake projects, reverting to fully-qualified install names. This might be the only option (if not cmake's default) to support macOS 10.4 and earlier since they have no rpath support. Setting of CMAKE_INSTALL_NAME_DIR might need tuning for slotted LLVM/clang then.

b. Extend ldwrapper to also add -rpath on macOS as proposed in https://bugs.gentoo.org/642616, at least for EPREFIX{,/usr}/lib. Then CMAKE_MACOSX_RPATH can be forced to ON for all cmake projects and CMAKE_INSTALL_NAME_DIR and CMAKE_INSTALL_RPATH become unnecessary[5] and even counterproductive.

2. As discussed on gentoo-alt[4], setting CMAKE_BUILD_WITH_INSTALL_RPATH has the potential to cause builds to fail if they call newly built binaries inside the build directory. This is the case with LLVM and clang upon upgrade from an older verson.

I have successfully upgraded an installed prefix as well as bootstrapped on macOS 10.13 (directly into LLVM/clang-5.0.1) using the following settings in cmake-utils.eclass and above ldwrapper extension:

	cat >> "${build_rules}" <<- _EOF_ || die
		# in Prefix we need rpath and must ensure cmake gets our default linker path
		# right ... except for Darwin hosts
[...]
		SET(CMAKE_PREFIX_PATH "${EPREFIX}/usr" CACHE STRING "" FORCE)
		SET(CMAKE_MACOSX_RPATH ON CACHE BOOL "" FORCE)
		SET(CMAKE_SKIP_BUILD_RPATH OFF CACHE BOOL "" FORCE)
		SET(CMAKE_SKIP_RPATH OFF CACHE BOOL "" FORCE)
		SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE BOOL "" FORCE)

Here, CMAKE_INSTALL_RPATH_USE_LINK_PATH takes care of automatically extending the rpath to library paths external to the project. This seems to work nicely even with LLVM/clang and their slot directory. What isn't caught by this cmake magic is taken care of by ldwrapper adding -rpath transparently.

This also gets order right: cmake adds the LLVM slot library directory either as desired by the project when building as @loader_path/../lib or as absolute path as referenced when linking. ldwrapper then puts the prefix library directories after that. Example binaries:

# otool -l usr/lib/llvm/5/bin/llvm-as| grep LC_LOAD_DYLIB\\\|LC_RPATH\\\|path\\\|\ name
         name /usr/lib/dyld (offset 12)
          cmd LC_LOAD_DYLIB
         name @rpath/libLLVMAsmParser.dylib (offset 24)
          cmd LC_LOAD_DYLIB
         name @rpath/libLLVMBitWriter.dylib (offset 24)
          cmd LC_LOAD_DYLIB
         name @rpath/libLLVMCore.dylib (offset 24)
          cmd LC_LOAD_DYLIB
         name @rpath/libLLVMSupport.dylib (offset 24)
          cmd LC_LOAD_DYLIB
         name @rpath/libc++.1.dylib (offset 24)
          cmd LC_LOAD_DYLIB
         name /usr/lib/libSystem.B.dylib (offset 24)
          cmd LC_RPATH
         path @loader_path/../lib (offset 12)
              ^^^ set by LLVM build system because it will install its libs there
          cmd LC_RPATH
         path /Users/michael/nobak/gentoo3/usr/lib (offset 12)
          cmd LC_RPATH
         path /Users/michael/nobak/gentoo3/lib (offset 12)
              ^^^ added by ldwrapper

# otool -l usr/lib/llvm/5/bin/clang | grep LC_LOAD_DYLIB\\\|LC_RPATH\\\|path\\\|\ name
         name /usr/lib/dyld (offset 12)
          cmd LC_LOAD_DYLIB
         name @rpath/libLLVMX86CodeGen.dylib (offset 24)
          cmd LC_LOAD_DYLIB
[... more boring LLVM and clang libs]
         name @rpath/libclangFrontendTool.dylib (offset 24)
          cmd LC_LOAD_DYLIB
         name @rpath/libc++.1.dylib (offset 24)
          cmd LC_LOAD_DYLIB
         name /usr/lib/libSystem.B.dylib (offset 24)
          cmd LC_RPATH
         path @loader_path/../lib (offset 12)
              ^^^ set by clang build system because it will install its libs there
          cmd LC_RPATH
         path /Users/michael/nobak/gentoo3/usr/lib/llvm/5/lib (offset 12)
              ^^^ added by cmake because it links against installed LLVM libs
          cmd LC_RPATH
         path /Users/michael/nobak/gentoo3/usr/lib (offset 12)
          cmd LC_RPATH
         path /Users/michael/nobak/gentoo3/lib (offset 12)
              ^^^ added by ldwrapper

[1] https://cmake.org/cmake/help/v3.0/prop_tgt/MACOSX_RPATH.html#prop_tgt:MACOSX_RPATH
[2] https://cmake.org/cmake/help/v3.0/policy/CMP0042.html
[3] https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH.html
[4] https://archives.gentoo.org/gentoo-alt/message/8ca587dd9bcb66a67fb6b7c0a974082b
[5] https://cmake.org/Wiki/CMake_RPATH_handling#Always_full_RPATH: CMAKE_INSTALL_RPATH_USE_LINK_PATH[...] If this option is enabled, all these directories except those which are also in the build tree will be added to the install RPATH automatically. The only directories which may then still be missing from the RPATH are the directories where the libraries from the same project (i.e. libbar.so) are installed to. If the install directory for the libraries is not one of the systems default library directories, you have to add this directory yourself to the install RPATH by setting CMAKE_INSTALL_RPATH accordingly.

Reproducible: Always
Comment 1 Michael Weiser 2017-12-29 19:31:44 UTC
Created attachment 511990 [details, diff]
Proposed change to cmake-utils.eclass
Comment 2 Larry the Git Cow gentoo-dev 2018-01-02 15:55:21 UTC
The bug has been closed via the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=995aa8f608f9e28e5da8da60fddf081ba7bf5224

commit 995aa8f608f9e28e5da8da60fddf081ba7bf5224
Author:     Fabian Groffen <grobian@gentoo.org>
AuthorDate: 2018-01-02 15:53:08 +0000
Commit:     Fabian Groffen <grobian@gentoo.org>
CommitDate: 2018-01-02 15:55:11 +0000

    eclass/cmake-utils: switch Darwin to rpath mode, bug #642668
    
    By Michael Weiser, relying on the other support that enables @rpath
    entries, supported in macOS 10.5 and up.
    
    Closes: https://bugs.gentoo.org/642668

 eclass/cmake-utils.eclass | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
Comment 3 Michael Weiser 2018-01-02 16:25:33 UTC
Rebuilt cmake and poppler with changed cmake-utils.eclass and all seems fine.
Comment 4 Larry the Git Cow gentoo-dev 2018-03-02 08:47:43 UTC
The bug has been closed via the following commit(s):

https://gitweb.gentoo.org/proj/kde.git/commit/?id=5bf7eac4ccee5315cd88bc47106dc0b9bab5b8c6

commit 5bf7eac4ccee5315cd88bc47106dc0b9bab5b8c6
Author:     Fabian Groffen <grobian@gentoo.org>
AuthorDate: 2018-01-02 15:53:08 +0000
Commit:     Michael Palimaka <kensington@gentoo.org>
CommitDate: 2018-03-02 08:47:29 +0000

    cmake-utils.eclass: switch Darwin to rpath mode, bug #642668
    
    By Michael Weiser, relying on the other support that enables @rpath
    entries, supported in macOS 10.5 and up.
    
    Closes: https://bugs.gentoo.org/642668

 eclass/cmake-utils.eclass | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)