fix(toolchain): pass -L as well as an rpath for a toolchain outside /usr
Inside the Flatpak the bundled toolchain compiled every bootstrap object, then glslang's configure failed its test link with `unable to find library -lc++`. clang searches its per-target runtime directory (lib/<triple>) and the system library paths for libc++, not <prefix>/lib, so with the classic layout a toolchain outside /usr needs the search path spelled out, just as its loader needs the rpath. LibcxxLinkFlags and build.sh now emit both, the same pair an explicit CRAFTER_BUILD_LIBCXX_DIR already got. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
a72d18eeab
commit
d22a8603df
4 changed files with 25 additions and 19 deletions
17
build.sh
17
build.sh
|
|
@ -14,12 +14,13 @@ if [ -n "${CRAFTER_BUILD_LLVM_DIR:-}" ]; then
|
||||||
CC="$CRAFTER_BUILD_LLVM_DIR/bin/clang"
|
CC="$CRAFTER_BUILD_LLVM_DIR/bin/clang"
|
||||||
AR="$CRAFTER_BUILD_LLVM_DIR/bin/llvm-ar"
|
AR="$CRAFTER_BUILD_LLVM_DIR/bin/llvm-ar"
|
||||||
LLVM_CONFIG="$CRAFTER_BUILD_LLVM_DIR/bin/llvm-config"
|
LLVM_CONFIG="$CRAFTER_BUILD_LLVM_DIR/bin/llvm-config"
|
||||||
# A prefix other than the system one keeps its libc++ off the loader's
|
# A prefix other than the system one keeps its libc++ off both the
|
||||||
# default path; the rpath is what lets the binary start.
|
# linker's search path (clang looks in lib/<triple> and the system dirs,
|
||||||
|
# not <prefix>/lib) and the loader's; -L and an rpath cover the two.
|
||||||
if [ "$CRAFTER_BUILD_LLVM_DIR" != /usr ]; then
|
if [ "$CRAFTER_BUILD_LLVM_DIR" != /usr ]; then
|
||||||
RPATH_FLAG="-Wl,-rpath,$CRAFTER_BUILD_LLVM_DIR/lib"
|
LIBCXX_LINK_FLAGS="-L$CRAFTER_BUILD_LLVM_DIR/lib -Wl,-rpath,$CRAFTER_BUILD_LLVM_DIR/lib"
|
||||||
else
|
else
|
||||||
RPATH_FLAG=""
|
LIBCXX_LINK_FLAGS=""
|
||||||
fi
|
fi
|
||||||
if [ -f "$CRAFTER_BUILD_LLVM_DIR/share/libc++/v1/std.cppm" ]; then
|
if [ -f "$CRAFTER_BUILD_LLVM_DIR/share/libc++/v1/std.cppm" ]; then
|
||||||
STD_CPPM="$CRAFTER_BUILD_LLVM_DIR/share/libc++/v1/std.cppm"
|
STD_CPPM="$CRAFTER_BUILD_LLVM_DIR/share/libc++/v1/std.cppm"
|
||||||
|
|
@ -31,7 +32,7 @@ else
|
||||||
CC=clang
|
CC=clang
|
||||||
AR=llvm-ar
|
AR=llvm-ar
|
||||||
LLVM_CONFIG=llvm-config
|
LLVM_CONFIG=llvm-config
|
||||||
RPATH_FLAG=""
|
LIBCXX_LINK_FLAGS=""
|
||||||
STD_CPPM=/usr/share/libc++/v1/std.cppm
|
STD_CPPM=/usr/share/libc++/v1/std.cppm
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -65,8 +66,8 @@ cmake -B build \
|
||||||
-DCMAKE_C_COMPILER="$CC" \
|
-DCMAKE_C_COMPILER="$CC" \
|
||||||
-DCMAKE_CXX_COMPILER="$CXX" \
|
-DCMAKE_CXX_COMPILER="$CXX" \
|
||||||
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
|
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
|
||||||
-DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ $RPATH_FLAG" \
|
-DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ $LIBCXX_LINK_FLAGS" \
|
||||||
-DCMAKE_SHARED_LINKER_FLAGS="-stdlib=libc++ $RPATH_FLAG" \
|
-DCMAKE_SHARED_LINKER_FLAGS="-stdlib=libc++ $LIBCXX_LINK_FLAGS" \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY="$current_dir/build" \
|
-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY="$current_dir/build" \
|
||||||
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY="$current_dir/build" \
|
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY="$current_dir/build" \
|
||||||
|
|
@ -117,7 +118,7 @@ rm -f ./lib/libcrafter-build.a
|
||||||
"$AR" rcs ./lib/libcrafter-build.a $OBJECTS
|
"$AR" rcs ./lib/libcrafter-build.a $OBJECTS
|
||||||
|
|
||||||
"$CXX" --target="$TARGET" -std=c++26 -stdlib=libc++ -O3 -march="$MARCH" -mtune="$MTUNE" -fuse-ld=lld \
|
"$CXX" --target="$TARGET" -std=c++26 -stdlib=libc++ -O3 -march="$MARCH" -mtune="$MTUNE" -fuse-ld=lld \
|
||||||
-Wl,--export-dynamic $RPATH_FLAG \
|
-Wl,--export-dynamic $LIBCXX_LINK_FLAGS \
|
||||||
-L./build \
|
-L./build \
|
||||||
$OBJECTS \
|
$OBJECTS \
|
||||||
./build/main.o \
|
./build/main.o \
|
||||||
|
|
|
||||||
|
|
@ -51,14 +51,17 @@ std::string Toolchain::LibcxxCompileFlags() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Toolchain::LibcxxLinkFlags() const {
|
std::string Toolchain::LibcxxLinkFlags() const {
|
||||||
std::string flags;
|
// clang searches its per-target runtime directory and the system library
|
||||||
|
// paths for -lc++, not <prefix>/lib, so a toolchain outside /usr with the
|
||||||
|
// classic layout needs the search path as well as the run-time path.
|
||||||
|
fs::path lib;
|
||||||
if (!libcxxDir.empty()) {
|
if (!libcxxDir.empty()) {
|
||||||
fs::path lib = libcxxDir / "lib";
|
lib = libcxxDir / "lib";
|
||||||
flags += std::format(" -L{} -Wl,-rpath,{}", lib.string(), lib.string());
|
|
||||||
} else if (!prefix.empty() && prefix != "/usr") {
|
} else if (!prefix.empty() && prefix != "/usr") {
|
||||||
flags += std::format(" -Wl,-rpath,{}", (prefix / "lib").string());
|
lib = prefix / "lib";
|
||||||
}
|
}
|
||||||
return flags;
|
if (lib.empty()) return {};
|
||||||
|
return std::format(" -L{} -Wl,-rpath,{}", lib.string(), lib.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Toolchain::Key() const {
|
std::string Toolchain::Key() const {
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,12 @@ export namespace Crafter {
|
||||||
|
|
||||||
// Flags for compiling against libcxxDir; empty without one.
|
// Flags for compiling against libcxxDir; empty without one.
|
||||||
std::string LibcxxCompileFlags() const;
|
std::string LibcxxCompileFlags() const;
|
||||||
// Flags for linking against the libc++ the compiler will use: an
|
// Flags for linking against the libc++ the compiler will use: a -L
|
||||||
// rpath into the prefix when that is not the system one (a bundled
|
// and an rpath for <prefix>/lib when the prefix is not the system one
|
||||||
// toolchain's libc++.so.1 is not on the loader's default path), plus
|
// (clang searches only its per-target runtime directory and the
|
||||||
// -L and an rpath for an explicit libcxxDir.
|
// system paths, and a bundled toolchain's libc++.so.1 is on neither
|
||||||
|
// the linker's nor the loader's default path), or for an explicit
|
||||||
|
// libcxxDir.
|
||||||
std::string LibcxxLinkFlags() const;
|
std::string LibcxxLinkFlags() const;
|
||||||
// Names this toolchain for cache directory names: the clang version
|
// Names this toolchain for cache directory names: the clang version
|
||||||
// followed by a hash of what decides which headers and libraries a
|
// followed by a hash of what decides which headers and libraries a
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ int main() {
|
||||||
Check(tc.stdCppm == full / "share/libc++/v1/std.cppm", "the prefix's std module source is used");
|
Check(tc.stdCppm == full / "share/libc++/v1/std.cppm", "the prefix's std module source is used");
|
||||||
Check(tc.wasiSysroot == full / "share/wasi-sysroot", "the prefix's wasi sysroot is used");
|
Check(tc.wasiSysroot == full / "share/wasi-sysroot", "the prefix's wasi sysroot is used");
|
||||||
Check(tc.LibcxxCompileFlags().empty(), "the compiler finds its own libc++ headers without flags");
|
Check(tc.LibcxxCompileFlags().empty(), "the compiler finds its own libc++ headers without flags");
|
||||||
Check(Contains(tc.LibcxxLinkFlags(), std::format("-Wl,-rpath,{}", (full / "lib").string())), "binaries get an rpath into the prefix's lib dir");
|
Check(Contains(tc.LibcxxLinkFlags(), std::format("-L{}", (full / "lib").string())) && Contains(tc.LibcxxLinkFlags(), std::format("-Wl,-rpath,{}", (full / "lib").string())), "binaries get -L and an rpath for the prefix's lib dir");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ToolchainInputs in;
|
ToolchainInputs in;
|
||||||
|
|
@ -95,7 +95,7 @@ int main() {
|
||||||
Check(tc.llvmIncludeDir.empty(), "no clang-c headers in the prefix: nothing added");
|
Check(tc.llvmIncludeDir.empty(), "no clang-c headers in the prefix: nothing added");
|
||||||
Check(tc.stdCppm == "/usr/share/libc++/v1/std.cppm", "no std module in the prefix: the system copy");
|
Check(tc.stdCppm == "/usr/share/libc++/v1/std.cppm", "no std module in the prefix: the system copy");
|
||||||
Check(tc.wasiSysroot == "/usr/share/wasi-sysroot", "no wasi sysroot in the prefix: the system one");
|
Check(tc.wasiSysroot == "/usr/share/wasi-sysroot", "no wasi sysroot in the prefix: the system one");
|
||||||
Check(Contains(tc.LibcxxLinkFlags(), std::format("-Wl,-rpath,{}", (bare / "lib").string())), "the rpath follows the explicit prefix");
|
Check(Contains(tc.LibcxxLinkFlags(), std::format("-L{}", (bare / "lib").string())) && Contains(tc.LibcxxLinkFlags(), std::format("-Wl,-rpath,{}", (bare / "lib").string())), "the link flags follow the explicit prefix");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ToolchainInputs in;
|
ToolchainInputs in;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue