|
| 1 | +# Copyright Spack Project Developers. See COPYRIGHT file. |
| 2 | +# SPDX-License-Identifier: (Apache-2.0 OR MIT) |
| 3 | + |
| 4 | +from pathlib import Path |
| 5 | +from typing import ClassVar, Dict |
| 6 | + |
| 7 | +from spack_repo.builtin.build_systems.compiler import CompilerPackage |
| 8 | +from spack_repo.builtin.build_systems.generic import Package |
| 9 | +from spack_repo.builtin.packages.llvm.package import LlvmDetection |
| 10 | + |
| 11 | +from spack.package import * |
| 12 | + |
| 13 | +_VERSIONS = { |
| 14 | + "21.1.1": { |
| 15 | + "ubuntu22.04": ( |
| 16 | + "8132ef95e4671c20a5f2b21dbe2d7ad8ae16137ea634e3e11096a8b87a3ffeee", |
| 17 | + "https://developer.arm.com/packages/arm-toolchains%3Aubuntu-22/jammy/arm64/arm-toolchain-for-linux_21.1-81_arm64.deb", |
| 18 | + ), |
| 19 | + "ubuntu24.04": ( |
| 20 | + "18f210fb04f27c50af932e1549deeda394a4ff351f9388957de0b096ab5f1db0", |
| 21 | + "https://developer.arm.com/packages/arm-toolchains%3Aubuntu-24/noble/arm64/arm-toolchain-for-linux_21.1-81_arm64.deb", |
| 22 | + ), |
| 23 | + "rhel8": ( |
| 24 | + "c5f0c3f7a25e269160aa3d684cb14edc57252bc38643929c67cda892f1c28dda", |
| 25 | + "https://developer.arm.com/packages/arm-toolchains%3Arhel-8/el8/aarch64/arm-toolchain-for-linux-21.1-81.aarch64.rpm", |
| 26 | + ), |
| 27 | + "rhel9": ( |
| 28 | + "3ead2888f8aa71b79a944270b1f7f723f56a7d161aeb2abaad14b3333f91f0e9", |
| 29 | + "https://developer.arm.com/packages/arm-toolchains%3Arhel-9/el9/aarch64/arm-toolchain-for-linux-21.1-81.aarch64.rpm", |
| 30 | + ), |
| 31 | + "rhel10": ( |
| 32 | + "a2fc22f18b7ee764ca11af48e6215b43ab47597cc67ba63fcccf0e40f9859a76", |
| 33 | + "https://developer.arm.com/packages/arm-toolchains%3Arhel-10/el10/aarch64/arm-toolchain-for-linux-21.1-81.aarch64.rpm", |
| 34 | + ), |
| 35 | + "amzn2023": ( |
| 36 | + "f7bc8c156aaa367dff1d6ced922e90581a04c8bac92e5675cc107eb3cd28428a", |
| 37 | + "https://developer.arm.com/packages/arm-toolchains%3Aamzn-2023/al2023/aarch64/arm-toolchain-for-linux-21.1-81.aarch64.rpm", |
| 38 | + ), |
| 39 | + "sles15": ( |
| 40 | + "8de2e35511d7f59a933c40e2e20ed2e01d018f51caba36dc5e9e0c6da71a3619", |
| 41 | + "https://developer.arm.com/packages/arm-toolchains%3Asles-15/sl15/aarch64/arm-toolchain-for-linux-21.1-81.aarch64.rpm", |
| 42 | + ), |
| 43 | + }, |
| 44 | + "20.1.0": { |
| 45 | + "ubuntu22.04": ( |
| 46 | + "944cf6420fb7b49c52d6c3d6f139fbb4896073ad401204a0cdf609faea360e73", |
| 47 | + "https://developer.arm.com/packages/arm-toolchains%3Aubuntu-22/jammy/arm64/arm-toolchain-for-linux_20.1-65_arm64.deb", |
| 48 | + ), |
| 49 | + "ubuntu24.04": ( |
| 50 | + "b9f7db08da8d579daad06999a65136e6b449b79c870a16264fbef1a7ab0cbe6b", |
| 51 | + "https://developer.arm.com/packages/arm-toolchains%3Aubuntu-24/noble/arm64/arm-toolchain-for-linux_20.1-65_arm64.deb", |
| 52 | + ), |
| 53 | + "rhel8": ( |
| 54 | + "795e6b74b2b538cc8431ff164c145aa7920ad9394ccf1d544a06667663b70f01", |
| 55 | + "https://developer.arm.com/packages/arm-toolchains%3Arhel-8/el8/aarch64/arm-toolchain-for-linux-20.1-65.aarch64.rpm", |
| 56 | + ), |
| 57 | + "rhel9": ( |
| 58 | + "453fc0f4d62968a833499f40a3d04deddbf292c9ff40fd3d246e84ba5b9d7d7a", |
| 59 | + "https://developer.arm.com/packages/arm-toolchains%3Arhel-9/el9/aarch64/arm-toolchain-for-linux-20.1-65.aarch64.rpm", |
| 60 | + ), |
| 61 | + "amzn2023": ( |
| 62 | + "87b2031290b9a48b0f2c700aff5f38560f7d1cb7d7f0b0f537ce18965260a54a", |
| 63 | + "https://developer.arm.com/packages/arm-toolchains%3Aamzn-2023/al2023/aarch64/arm-toolchain-for-linux-20.1-65.aarch64.rpm", |
| 64 | + ), |
| 65 | + "sles15": ( |
| 66 | + "506a9ddff6d7daf60e1d5b8cfed95f6f25e70db3cc9545d8ea3e9745056740f9", |
| 67 | + "https://developer.arm.com/packages/arm-toolchains%3Asles-15/sl15/aarch64/arm-toolchain-for-linux-20.1-65.aarch64.rpm", |
| 68 | + ), |
| 69 | + }, |
| 70 | +} |
| 71 | + |
| 72 | + |
| 73 | +class Atfl(Package, LlvmDetection, CompilerPackage): |
| 74 | + """Arm Toolchain for Linux (ATfL): LLVM-based AArch64 compilers. |
| 75 | +
|
| 76 | + Installs the distro package (RPM/DEB) from Arm's repos, without root. |
| 77 | + """ |
| 78 | + |
| 79 | + maintainers("pawosm-arm") |
| 80 | + homepage = "https://developer.arm.com/documentation/110477" |
| 81 | + |
| 82 | + _alias: ClassVar[Dict[str, str]] = {"rocky10": "rhel10", "rocky9": "rhel9", "rocky8": "rhel8"} |
| 83 | + for ver, per_os in _VERSIONS.items(): |
| 84 | + pkg = per_os.get(_alias.get(host_platform().default_os, host_platform().default_os), None) |
| 85 | + if pkg: |
| 86 | + version(ver, sha256=pkg[0], url=pkg[1], expand=False) |
| 87 | + |
| 88 | + # Linux AArch64 only |
| 89 | + requires("platform=linux", msg="ATfL is only available on Linux") |
| 90 | + requires("target=aarch64:", msg="ATfL provides AArch64-native compilers") |
| 91 | + |
| 92 | + provides("c", "cxx") |
| 93 | + provides("fortran") |
| 94 | + |
| 95 | + # Optional: allow opt-in to lld via the spec. Default is GNU ld for |
| 96 | + # maximum compatibility; packages that prefer lld can request `%atfl+lld`. |
| 97 | + variant("lld", default=False, description="Use lld linker (adds -fuse-ld=lld)") |
| 98 | + |
| 99 | + # Arm Performance Libraries are required: ATfL's default configuration |
| 100 | + # links against ArmPL (e.g. -fveclib=ArmPL -> -lamath). Ensure it's |
| 101 | + # present and wired into the environment so linking always succeeds. |
| 102 | + depends_on("armpl-gcc~examples", type="run") |
| 103 | + |
| 104 | + compiler_languages = ["c", "cxx", "fortran"] |
| 105 | + compiler_version_regex = r"Arm Toolchain for Linux [\d\.]+ [cf]lang version ([\d\.]+)" |
| 106 | + c_names = ["armclang"] |
| 107 | + cxx_names = ["armclang++"] |
| 108 | + fortran_names = ["armflang"] |
| 109 | + compiler_wrapper_link_paths = { |
| 110 | + "c": join_path("arm", "armclang"), |
| 111 | + "cxx": join_path("arm", "armclang++"), |
| 112 | + "fortran": join_path("arm", "armflang"), |
| 113 | + } |
| 114 | + implicit_rpath_libs = ["libclang"] |
| 115 | + stdcxx_libs = ("-lstdc++",) |
| 116 | + |
| 117 | + debug_flags = [ |
| 118 | + "-gcodeview", |
| 119 | + "-gdwarf-2", |
| 120 | + "-gdwarf-3", |
| 121 | + "-gdwarf-4", |
| 122 | + "-gdwarf-5", |
| 123 | + "-gline-tables-only", |
| 124 | + "-gmodules", |
| 125 | + "-g", |
| 126 | + ] |
| 127 | + |
| 128 | + opt_flags = ["-O0", "-O1", "-O2", "-O3", "-Ofast", "-Os", "-Oz", "-Og", "-O", "-O4"] |
| 129 | + |
| 130 | + def archspec_name(self) -> str: |
| 131 | + """Return the compiler name to use for archspec queries.""" |
| 132 | + return "clang" |
| 133 | + |
| 134 | + def install(self, spec: Spec, prefix: Prefix) -> None: |
| 135 | + """Install the package.""" |
| 136 | + archive = self.stage.archive_file |
| 137 | + extract_dir = join_path(self.stage.path, "extract") |
| 138 | + mkdir(extract_dir) |
| 139 | + if archive.endswith(".rpm"): |
| 140 | + Executable("bsdtar")("-xf", archive, "-C", str(extract_dir)) |
| 141 | + elif archive.endswith(".deb"): |
| 142 | + Executable("dpkg-deb")("-x", archive, str(extract_dir)) |
| 143 | + else: |
| 144 | + raise InstallError(f"Unknown archive type: {archive}") |
| 145 | + src_root = join_path(extract_dir, "opt", "arm", "arm-toolchain-for-linux") |
| 146 | + |
| 147 | + if not Path(src_root).is_dir(): |
| 148 | + raise InstallError(f"Expected payload at {src_root}") |
| 149 | + |
| 150 | + # We must remove all of the libamath.* symlinks as they reach /opt |
| 151 | + for cand in Path(src_root).rglob("libamath.*"): |
| 152 | + if cand.is_symlink(): |
| 153 | + cand.unlink() |
| 154 | + |
| 155 | + install_tree(str(src_root), prefix) |
| 156 | + |
| 157 | + with open(join_path(prefix, "bin", "atfl-performance.cfg"), "a") as f: |
| 158 | + # Enable lld if requested. Some system builds (e.g. ncurses with |
| 159 | + # version scripts) are stricter under lld; make this opt-in to |
| 160 | + # maximize compatibility. |
| 161 | + if self.spec.satisfies("+lld"): |
| 162 | + print("-fuse-ld=lld", file=f) |
| 163 | + |
| 164 | + # ArmPL's libamath must be visible to the compiler. |
| 165 | + # ArmPL directory layout: <prefix>/armpl_<version>_gcc/lib |
| 166 | + armpl_dir = join_path( |
| 167 | + self["armpl-gcc"].prefix, "armpl_" + str(self["armpl-gcc"].version) + "_gcc", "lib" |
| 168 | + ) |
| 169 | + print(f"-L{armpl_dir} -Wl,-rpath={armpl_dir}", file=f) |
| 170 | + |
| 171 | + # Ensure ATfL's own Fortran runtime is available to dependents. |
| 172 | + # At first, Flang was using libFortranRuntime and libFortranDecimal; |
| 173 | + # later toolchains use libflang_rt.runtime. This avoids per-package |
| 174 | + # tweaks. |
| 175 | + fortran_runtime = "" |
| 176 | + fortran_runtime_paths = set() |
| 177 | + for cand in Path(prefix).rglob("libFortranRuntime.*"): |
| 178 | + fortran_runtime = "-lFortranRuntime -lFortranDecimal" |
| 179 | + fortran_runtime_paths.add(str(cand.parent)) |
| 180 | + for cand in Path(prefix).rglob("libflang_rt.runtime.*"): |
| 181 | + fortran_runtime = "-lflang_rt.runtime" |
| 182 | + fortran_runtime_paths.add(str(cand.parent)) |
| 183 | + for rt_path in fortran_runtime_paths: |
| 184 | + print(f"-L{rt_path} -Wl,-rpath,{rt_path}", file=f) |
| 185 | + print(f"-Wl,--push-state -Wl,--as-needed {fortran_runtime} -Wl,--pop-state", file=f) |
| 186 | + |
| 187 | + def _cc_path(self) -> str: |
| 188 | + return join_path(self.prefix, "bin", "armclang") |
| 189 | + |
| 190 | + def _cxx_path(self) -> str: |
| 191 | + return join_path(self.prefix, "bin", "armclang++") |
| 192 | + |
| 193 | + def _fortran_path(self) -> str: |
| 194 | + return join_path(self.prefix, "bin", "armflang") |
| 195 | + |
| 196 | + def _standard_flag(self, *, language: str, standard: str) -> str: |
| 197 | + flags = { |
| 198 | + "cxx": {"11": "-std=c++11", "14": "-std=c++14", "17": "-std=c++17"}, |
| 199 | + "c": {"99": "-std=c99", "11": "-std=c11"}, |
| 200 | + } |
| 201 | + return flags[language][standard] |
| 202 | + |
| 203 | + def setup_compiler_environment(self, env: EnvironmentModifications) -> None: |
| 204 | + """Set up the build environment for this compiler package.""" |
| 205 | + |
| 206 | + # Prefer LLVM binutils (needed by LTO). |
| 207 | + env.set("AR", join_path(self.prefix, "bin", "llvm-ar")) |
| 208 | + env.set("NM", join_path(self.prefix, "bin", "llvm-nm")) |
| 209 | + env.set("RANLIB", join_path(self.prefix, "bin", "llvm-ranlib")) |
| 210 | + |
| 211 | + def setup_run_environment(self, env: EnvironmentModifications) -> None: |
| 212 | + """Set up the run environment for this package.""" |
| 213 | + self.setup_compiler_environment(env) |
| 214 | + |
| 215 | + def setup_dependent_build_environment(self, env: EnvironmentModifications, _: Spec) -> None: |
| 216 | + """Set up the build environment for packages that depend on this one.""" |
| 217 | + self.setup_run_environment(env) |
0 commit comments