@@ -647,38 +647,46 @@ void patchelf_walk(const std::filesystem::path& dir,
647647 }
648648}
649649
650- // xim's gcc tarball is built with an absolute hardcoded path
651- // `/home/xlings/.xlings_data/subos/linux/lib/...` baked into the gcc specs
652- // (both as `--dynamic-linker` and `-rpath`). xim's gcc-specs-config.lua
653- // tries to override these but only matches `/lib64/ld-linux-x86-64.so.2`,
654- // not the baked-in `/home/xlings/...`, so the override silently no-ops.
650+ // xim bakes the installing user's XLINGS_HOME into gcc specs at install
651+ // time (as `--dynamic-linker` and `-rpath`). When mcpp uses its own
652+ // isolated sandbox (MCPP_HOME/registry/), the baked-in paths point to
653+ // xlings' home, not mcpp's sandbox glibc — binaries would fail to exec.
655654//
656- // TODO(xim-pkgindex-upstream): file an issue against xim-pkgindex's
657- // gcc-specs-config.lua to also match the `/home/xlings/...` baked-in
658- // path. Once fixed, this whole post-install fixup can be deleted.
659- //
660- // Result: gcc compiles user binaries with PT_INTERP pointing at
661- // `/home/xlings/.xlings_data/...` AND an rpath pointing at the same
662- // non-existent directory. `elfpatch.auto` (now functional thanks to the
663- // patchelf bootstrap) only fixes ELF binaries it scans; it doesn't touch
664- // the gcc specs text file.
665- //
666- // Mcpp does the post-install spec rewrite itself:
667- // - The dynamic-linker path becomes <glibc_lib64>/ld-linux-x86-64.so.2.
668- // - The rpath becomes <glibc_lib64>:<gcc_lib64> so user binaries can find
669- // both libc.so.6 (glibc) and libstdc++.so.6 + libgcc_s.so.1 (gcc).
670- // Idempotent.
655+ // Mcpp does a post-install spec rewrite:
656+ // - Dynamically detects the baked-in lib dir from the specs file
657+ // - Replaces the dynamic-linker path with <glibc_lib64>/ld-linux-x86-64.so.2
658+ // - Replaces the rpath with <glibc_lib64>:<gcc_lib64>
659+ // Idempotent — skips if already pointing at the correct glibc.
660+ // Extract the baked-in lib directory from a gcc specs file by finding
661+ // the dynamic-linker path that ends with `/ld-linux-x86-64.so.2`.
662+ // xim bakes the installing user's XLINGS_HOME into specs at install
663+ // time, so the path varies per machine — we cannot hardcode it.
664+ std::string detect_baked_lib_dir (const std::string& specsContent) {
665+ constexpr std::string_view kLoader = " /ld-linux-x86-64.so.2" ;
666+ auto pos = specsContent.find (kLoader );
667+ if (pos == std::string::npos) return " " ;
668+ // Walk backwards to find start of the absolute path
669+ auto start = pos;
670+ while (start > 0 && specsContent[start - 1 ] != ' '
671+ && specsContent[start - 1 ] != ' :'
672+ && specsContent[start - 1 ] != ' ;'
673+ && specsContent[start - 1 ] != ' \n ' ) {
674+ --start;
675+ }
676+ auto dir = specsContent.substr (start, pos - start);
677+ // Sanity: must be absolute
678+ if (dir.empty () || dir[0 ] != ' /' ) return " " ;
679+ // Skip if it already points to the target glibc (no fixup needed)
680+ return dir;
681+ }
682+
671683void fixup_gcc_specs (const std::filesystem::path& gccPkgRoot,
672684 const std::filesystem::path& glibcLibDir,
673685 const std::filesystem::path& gccLibDir)
674686{
675687 auto specsParent = gccPkgRoot / " lib" / " gcc" / " x86_64-linux-gnu" ;
676688 if (!std::filesystem::exists (specsParent)) return ;
677689
678- constexpr std::string_view kBakedDir =
679- mcpp::xlings::pinned::kXlingsBuildHostLib ;
680- auto kBakedLoader = std::format (" {}/ld-linux-x86-64.so.2" , kBakedDir );
681-
682690 auto loaderReplacement = (glibcLibDir / " ld-linux-x86-64.so.2" ).string ();
683691 auto rpathReplacement = std::format (" {}:{}" ,
684692 glibcLibDir.string (),
@@ -702,12 +710,17 @@ void fixup_gcc_specs(const std::filesystem::path& gccPkgRoot,
702710 std::stringstream ss; ss << is.rdbuf ();
703711 std::string content = ss.str ();
704712
705- if (content.find (kBakedDir ) == std::string::npos) continue ;
713+ auto bakedDir = detect_baked_lib_dir (content);
714+ if (bakedDir.empty ()) continue ;
715+ // Already pointing at the right place — no fixup needed.
716+ if (bakedDir == glibcLibDir.string ()) continue ;
717+
718+ auto bakedLoader = bakedDir + " /ld-linux-x86-64.so.2" ;
706719
707720 // Order matters: replace the full loader file path first so the
708721 // shorter dir pattern doesn't eat its prefix.
709- replace_all (content, kBakedLoader , loaderReplacement);
710- replace_all (content, kBakedDir , rpathReplacement);
722+ replace_all (content, bakedLoader , loaderReplacement);
723+ replace_all (content, bakedDir , rpathReplacement);
711724
712725 std::ofstream os (specs);
713726 os << content;
0 commit comments