From 43f3a35150f162ec36de96022c2d4c58388ea01b Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Sat, 27 Apr 2024 16:49:20 +0200 Subject: gcc: generate spec file and fix external libc default paths after install from cache (#43839) Co-authored-by: Massimiliano Culpo --- var/spack/repos/builtin/packages/gcc/package.py | 61 +++++++++++++++++++++++ var/spack/repos/builtin/packages/glibc/package.py | 4 ++ var/spack/repos/builtin/packages/musl/package.py | 4 ++ 3 files changed, 69 insertions(+) (limited to 'var') diff --git a/var/spack/repos/builtin/packages/gcc/package.py b/var/spack/repos/builtin/packages/gcc/package.py index b70ff7586d..6d94e2785d 100644 --- a/var/spack/repos/builtin/packages/gcc/package.py +++ b/var/spack/repos/builtin/packages/gcc/package.py @@ -16,6 +16,7 @@ from llnl.util.symlink import readlink import spack.platforms import spack.util.executable +import spack.util.libc from spack.operating_systems.mac_os import macos_sdk_path, macos_version from spack.package import * @@ -1152,3 +1153,63 @@ class Gcc(AutotoolsPackage, GNUMirrorPackage): ) # The version of gcc-runtime is the same as the %gcc used to "compile" it pkg("gcc-runtime").requires(f"@={str(spec.version)}", when=f"%{str(spec)}") + + def _post_buildcache_install_hook(self): + if not self.spec.satisfies("platform=linux"): + return + + # Setting up the runtime environment shouldn't be necessary here. + relocation_args = [] + gcc = self.spec["gcc"].command + specs_file = os.path.join(self.spec_dir, "specs") + dryrun = gcc("test.c", "-###", output=os.devnull, error=str).strip() + if not dryrun: + tty.warn(f"Cannot relocate {specs_file}, compiler might not be working properly") + return + dynamic_linker = spack.util.libc.parse_dynamic_linker(dryrun) + if not dynamic_linker: + tty.warn(f"Cannot relocate {specs_file}, compiler might not be working properly") + return + + libc = spack.util.libc.libc_from_dynamic_linker(dynamic_linker) + + # We search for crt1.o ourselves because `gcc -print-prile-name=crt1.o` can give a rather + # convoluted relative path from a different prefix. + startfile_prefix = spack.util.libc.startfile_prefix(libc.external_path, dynamic_linker) + + gcc_can_locate = lambda p: os.path.isabs( + gcc(f"-print-file-name={p}", output=str, error=os.devnull).strip() + ) + + if not gcc_can_locate("crt1.o"): + relocation_args.append(f"-B{startfile_prefix}") + + # libc headers may also be in a multiarch subdir. + header_dir = spack.util.libc.libc_include_dir_from_startfile_prefix( + libc.external_path, startfile_prefix + ) + if header_dir and all( + os.path.exists(os.path.join(header_dir, h)) + for h in libc.package_class.representative_headers + ): + relocation_args.append(f"-isystem {header_dir}") + else: + tty.warn( + f"Cannot relocate {specs_file} include directories, " + f"compiler might not be working properly" + ) + + # Delete current spec files. + try: + os.unlink(specs_file) + except OSError: + pass + + # Write a new one and append flags for libc + self.write_specs_file() + + if relocation_args: + with open(specs_file, "a") as f: + print("*self_spec:", file=f) + print(f"+ {' '.join(relocation_args)}", file=f) + print(file=f) diff --git a/var/spack/repos/builtin/packages/glibc/package.py b/var/spack/repos/builtin/packages/glibc/package.py index 16315c4bbc..f09f455ab6 100644 --- a/var/spack/repos/builtin/packages/glibc/package.py +++ b/var/spack/repos/builtin/packages/glibc/package.py @@ -22,6 +22,10 @@ class Glibc(AutotoolsPackage, GNUMirrorPackage): build_directory = "build" tags = ["runtime"] + # This is used when the package is external and we need to find the actual default include path + # which may be in a multiarch subdir. + representative_headers = ["ieee754.h"] + license("LGPL-2.1-or-later") provides("libc") diff --git a/var/spack/repos/builtin/packages/musl/package.py b/var/spack/repos/builtin/packages/musl/package.py index 4b503feb64..622bd004e8 100644 --- a/var/spack/repos/builtin/packages/musl/package.py +++ b/var/spack/repos/builtin/packages/musl/package.py @@ -29,6 +29,10 @@ class Musl(MakefilePackage): license("MIT") + # This is used when the package is external and we need to find the actual default include path + # which may be in a multiarch subdir. + representative_headers = ["iso646.h"] + provides("libc") version("1.2.4", sha256="7a35eae33d5372a7c0da1188de798726f68825513b7ae3ebe97aaaa52114f039") -- cgit v1.2.3-70-g09d2