koga: give installed binaries an rpath pointing at the install prefix - #1832
Open
dg1sbg wants to merge 1 commit into
Open
koga: give installed binaries an rpath pointing at the install prefix#1832dg1sbg wants to merge 1 commit into
dg1sbg wants to merge 1 commit into
Conversation
The link step emits a single rpath: the absolute path of the build tree's
lib directory. `install' copies the binary but cannot rewrite an rpath baked
in at link time, so an INSTALLED clasp keeps resolving libclasp through the
build tree. Consequences, none of them signalled:
- removing the build directory breaks the installed clasp
- rebuilding it silently changes which clasp the installed binary runs
- the libclasp copied into the install prefix is never loaded
- two installs cannot coexist: both resolve to whatever the build tree
currently holds, so each reports the other's version
Observed by installing two versions into separate prefixes and asking each
for its version: both answered with the build tree's, and
DYLD_PRINT_LIBRARIES confirmed both loaded the same library.
Emit a loader-relative rpath ahead of the absolute one. In the install
layout the binary is <prefix>/bin/iclasp and the library <prefix>/lib, so
../lib resolves. In the build tree the binary is <build>/<variant>/iclasp
with its library in <build>/<variant>/lib, so ../lib names <build>/lib,
which does not exist and is skipped -- the in-tree binary falls through to
the absolute entry exactly as before. One link therefore serves both, with
no install-time rewriting and no dependency on install_name_tool or patchelf.
$ORIGIN has to survive ninja and /bin/sh to reach the linker, hence the
doubled dollar and the single quotes.
Verified on both platforms. macOS: rpaths are
(@loader_path/../lib, <build>/boehmprecise/lib); the in-tree binary still
loads from the build tree, and a copy in an install layout loads
/tmp/rpx/lib/libclasp.dylib. Linux: RUNPATH is
[$ORIGIN/../lib:<build>/boehmprecise/lib], the in-tree binary runs, and a
copy in an install layout resolves through its own prefix while the build
tree is still present.
Fixes clasp-developers#1831.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1831 — installed binaries keep loading
libclaspout of the build tree.The bug
The link step emits one rpath: the absolute build lib directory.
installcopies the binary but cannot rewrite an rpath baked in at link time, so an installed clasp resolveslibclaspthrough the build tree.Even with a single install this means removing the build tree breaks the install, rebuilding it silently changes which clasp the installed binary runs, and the
libclaspcopied into the prefix is never loaded. With two installs neither works: both resolve to whatever the build tree currently holds, so each reports the other's version. I found it exactly that way.The change
Emit a loader-relative rpath ahead of the absolute one:
../libresolves to<prefix>/bin/iclasp<prefix>/lib<prefix>/lib✓<build>/<variant>/iclasp<build>/<variant>/lib<build>/lib— absent, skippedSo one link serves both: installed binaries prefer their own prefix, and the in-tree binary falls through to the absolute entry exactly as before. No install-time rewriting, and no dependency on
install_name_toolorpatchelf(the latter is often not installed).$ORIGINmust survive two layers to reach the linker — ninja ($$) and/bin/sh(single quotes). Confirmed vianinja -t commands:Verification
macOS (arm64, LLVM 22):
x86-64 Linux (LLVM 18, bytecode):
In both cases the install-layout copy prefers its own prefix while the build tree exists, and the in-tree binary is unchanged.
One thing worth your eye
The relative entry is inert in the build tree only because
<build>/libdoes not exist. That holds for every variant today, but it is a load-bearing assumption: a future layout that createsbuild/libwould make the in-tree binary prefer it. If you would rather not depend on that, the alternative is rewriting the rpath duringinstall(what CMake does), at the cost of requiringinstall_name_tool/patchelf— happy to do it that way instead.The reproducible-build branch of that
condis untouched; it already remaps paths for its own reasons and I did not want to disturb it without understanding the intent.