From b08c996135d7ff53a7b499fb2920e86d26ee2db7 Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Tue, 19 Nov 2024 10:04:38 -0700 Subject: [PATCH 1/9] add python bindings variant to chapel --- .../repos/builtin/packages/chapel/package.py | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index 3e8693c787bfc1..07316affcd1574 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -326,6 +326,12 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): values=("bundled", "none", "spack"), ) + variant( + "python-bindings", + description="Also build the Python bindings for Chapel frontend (requires LLVM)", + default=False, + ) + variant( "re2", description="Build with re2 support", @@ -492,6 +498,13 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): "https://chapel-lang.org/docs/usingchapel/chplenv.html#chpl-host-jemalloc", ) + conflicts( + "llvm=none", + when="+python-bindings", + msg="Python bindings require building with LLVM, see " + "https://chapel-lang.org/docs/tools/chapel-py/chapel-py.html#installation", + ) + with when("llvm=none"): conflicts("+cuda", msg="Cuda support requires building with LLVM") conflicts("+rocm", msg="ROCm support requires building with LLVM") @@ -536,6 +549,13 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): depends_on("gasnet conduits=none", when="gasnet=spack") depends_on("gasnet@2024.5.0: conduits=none", when="@2.1.0: gasnet=spack") + extends("python", when="+python-bindings") + requires( + "%clang", + "%apple-clang", + when="+python-bindings", + policy="one_of") + depends_on("python@3.7:") depends_on("cmake@3.16:") @@ -565,9 +585,15 @@ def unset_chpl_env_vars(self, env): env.unset(var) def build(self, spec, prefix): - make() - if spec.variants["chpldoc"].value: - make("chpldoc") + with set_env(CHPL_HOME=self.build_directory): + with set_env(CHPL_MAKE_THIRD_PARTY=join_path(self.build_directory, "third-party")): + if spec.satisfies("+chpldoc"): + make("chpldoc") + if spec.satisfies("+python-bindings"): + make("chapel-py-venv") + python("-m", "ensurepip", "--default-pip") + python("-m", "pip", "install", "tools/chapel-py") + make() def setup_chpl_platform(self, env): if self.spec.variants["host_platform"].value == "unset": @@ -729,6 +755,10 @@ def setup_run_environment(self, env): env.prepend_path( "PATH", join_path(self.prefix.share, "chapel", self._output_version_short, "util") ) + if self.spec.satisfies("+python-bindings"): + env.prepend_path( + "LD_LIBRARY_PATH", join_path(self.prefix.lib, "chapel", self._output_version_short, "compiler") + ) @property @llnl.util.lang.memoized From 6a99837f2914f724a606658c0ea039514d8dfff8 Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Tue, 19 Nov 2024 10:07:17 -0700 Subject: [PATCH 2/9] fix chpl_home, update chapel frontend rpath in venv --- .../repos/builtin/packages/chapel/package.py | 97 +++++++++++++++---- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index 07316affcd1574..fa76532948c104 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -3,8 +3,11 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import glob import os +import re import subprocess +import typing import llnl.util.lang @@ -63,6 +66,9 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): version("2.0.1", sha256="47e1f3789478ea870bd4ecdf52acbe469d171b89b663309325431f3da7c75008") version("2.0.0", sha256="a8cab99fd034c7b7229be8d4626ec95cf02072646fb148c74b4f48c460c6059c") + sanity_check_is_dir = ["bin", join_path("lib", "chapel"), join_path("share", "chapel")] + sanity_check_is_file = [join_path("bin", "chpl")] + depends_on("c", type="build") # generated depends_on("cxx", type="build") # generated @@ -413,6 +419,7 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): "CHPL_GPU", "CHPL_GPU_ARCH", "CHPL_GPU_MEM_STRATEGY", + "CHPL_HOME", "CHPL_HOST_ARCH", # "CHPL_HOST_CC", "CHPL_HOST_COMPILER", @@ -549,14 +556,12 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): depends_on("gasnet conduits=none", when="gasnet=spack") depends_on("gasnet@2024.5.0: conduits=none", when="@2.1.0: gasnet=spack") - extends("python", when="+python-bindings") - requires( - "%clang", - "%apple-clang", - when="+python-bindings", - policy="one_of") + with when("+python-bindings"): + extends("python") + requires("%clang", "%apple-clang", policy="one_of") depends_on("python@3.7:") + depends_on("chrpath", type=("build",)) depends_on("cmake@3.16:") # ensure we can map the spack compiler name to one of the ones we recognize @@ -584,16 +589,74 @@ def unset_chpl_env_vars(self, env): for var in self.chpl_env_vars: env.unset(var) + def get_path(self, s: str) -> typing.List[str]: + get_path_pat = re.compile(r"(?:RUNPATH|RPATH)=(.*)") + m = re.search(get_path_pat, s) + if m: + paths = m.group(1).split(":") + paths = [p.strip() for p in paths if p.strip() != ""] + return paths + return [] + + # Some chapel build scripts depend on CHPL_HOME, this can get encoded into + # the frontend library rpaths. this is problematic for the python + # bindings which get installed in virtualenv provided by spack. This script + # will fix the rpath of the chapel frontend library after installation + @run_after("install") + def fix_rpath(self): + files = [] + # find all .so in the old lib path + for f in glob.glob( + join_path(self.prefix.lib, "chapel", str(self._output_version_short), "**", "*.so"), + recursive=True, + ): + files.append(f) + + for f in glob.glob( + join_path(self.spec["python-venv"].prefix.lib, "**", "chapel", "*.so"), recursive=True + ): + files.append(f) + + for f in files: + cp = subprocess.run( + ["chrpath", "-l", f], + encoding="utf-8", + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + path = cp.stdout.strip() + path = self.get_path(path) + new_path = [] + # clean path + for p in path: + if p == self.prefix.lib64: + continue + if p.startswith(str(self.build_directory)): + new_path.append( + str( + join_path( + self.prefix.lib, "chapel", self._output_version_short, "compiler" + ) + ) + ) + else: + new_path.append(p) + # remove duplicates + new_path = list(set(new_path)) + path = ":".join(new_path) + if path: + subprocess.check_call(["chrpath", "-r", path, f]) + def build(self, spec, prefix): - with set_env(CHPL_HOME=self.build_directory): - with set_env(CHPL_MAKE_THIRD_PARTY=join_path(self.build_directory, "third-party")): + with set_env(CHPL_MAKE_THIRD_PARTY=join_path(self.build_directory, "third-party")): + make() + with set_env(CHPL_HOME=self.build_directory): if spec.satisfies("+chpldoc"): make("chpldoc") if spec.satisfies("+python-bindings"): make("chapel-py-venv") python("-m", "ensurepip", "--default-pip") python("-m", "pip", "install", "tools/chapel-py") - make() def setup_chpl_platform(self, env): if self.spec.variants["host_platform"].value == "unset": @@ -752,17 +815,17 @@ def setup_build_environment(self, env): def setup_run_environment(self, env): self.setup_env_vars(env) - env.prepend_path( - "PATH", join_path(self.prefix.share, "chapel", self._output_version_short, "util") + chpl_home = join_path(self.prefix.share, "chapel", self._output_version_short) + env.prepend_path("PATH", join_path(chpl_home, "util")) + env.set( + "CHPL_MAKE_THIRD_PARTY", + join_path(self.prefix.lib, "chapel", self._output_version_short), ) - if self.spec.satisfies("+python-bindings"): - env.prepend_path( - "LD_LIBRARY_PATH", join_path(self.prefix.lib, "chapel", self._output_version_short, "compiler") - ) + env.set("CHPL_HOME", chpl_home) @property @llnl.util.lang.memoized - def _output_version_long(self): + def _output_version_long(self) -> str: if str(self.spec.version).lower() == "main": return "2.3.0" spec_vers_str = str(self.spec.version.up_to(3)) @@ -770,7 +833,7 @@ def _output_version_long(self): @property @llnl.util.lang.memoized - def _output_version_short(self): + def _output_version_short(self) -> str: if str(self.spec.version).lower() == "main": return "2.3" spec_vers_str = str(self.spec.version.up_to(2)) From e389657e7fe3c2cd756adb9511d8585fb44077ad Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Wed, 20 Nov 2024 15:27:11 -0700 Subject: [PATCH 3/9] fix chpl frontend shared lib rpath hack --- .../chapel/fix_chpl_shared_lib_path.patch | 20 +++++ .../repos/builtin/packages/chapel/package.py | 75 ++----------------- 2 files changed, 28 insertions(+), 67 deletions(-) create mode 100644 var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch diff --git a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch new file mode 100644 index 00000000000000..d933564757ddc8 --- /dev/null +++ b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch @@ -0,0 +1,20 @@ +diff --git a/tools/chapel-py/setup.py b/tools/chapel-py/setup.py +index bee452790c..09c16fbda3 100644 +--- a/tools/chapel-py/setup.py ++++ b/tools/chapel-py/setup.py +@@ -25,6 +25,7 @@ import sys + import glob + + chpl_home = str(os.getenv("CHPL_HOME")) ++chpl_lib_install = str(os.getenv("CHPL_SPACK_LIB_INSTALL")) + chpl_printchplenv = os.path.join(chpl_home, "util", "printchplenv") + chpl_variables_lines = ( + subprocess.check_output( +@@ -67,6 +68,7 @@ LDFLAGS += [ + "-lChplFrontendShared", + "-Wl,-rpath", + chpl_lib_path, ++ "-Wl,-rpath,{}".format(chpl_lib_install), + ] + + if str(chpl_variables.get("CHPL_SANITIZE")) == "address": diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index fa76532948c104..116d4b06766534 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -73,6 +73,7 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): depends_on("cxx", type="build") # generated patch("fix_spack_cc_wrapper_in_cray_prgenv.patch", when="@2.0.0:") + patch("fix_chpl_shared_lib_path.patch") launcher_names = ( "amudprun", @@ -505,16 +506,14 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): "https://chapel-lang.org/docs/usingchapel/chplenv.html#chpl-host-jemalloc", ) - conflicts( - "llvm=none", - when="+python-bindings", - msg="Python bindings require building with LLVM, see " - "https://chapel-lang.org/docs/tools/chapel-py/chapel-py.html#installation", - ) - with when("llvm=none"): conflicts("+cuda", msg="Cuda support requires building with LLVM") conflicts("+rocm", msg="ROCm support requires building with LLVM") + conflicts( + "+python-bindings", + msg="Python bindings require building with LLVM, see " + "https://chapel-lang.org/docs/tools/chapel-py/chapel-py.html#installation", + ) # Add dependencies @@ -558,10 +557,8 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): with when("+python-bindings"): extends("python") - requires("%clang", "%apple-clang", policy="one_of") depends_on("python@3.7:") - depends_on("chrpath", type=("build",)) depends_on("cmake@3.16:") # ensure we can map the spack compiler name to one of the ones we recognize @@ -589,64 +586,6 @@ def unset_chpl_env_vars(self, env): for var in self.chpl_env_vars: env.unset(var) - def get_path(self, s: str) -> typing.List[str]: - get_path_pat = re.compile(r"(?:RUNPATH|RPATH)=(.*)") - m = re.search(get_path_pat, s) - if m: - paths = m.group(1).split(":") - paths = [p.strip() for p in paths if p.strip() != ""] - return paths - return [] - - # Some chapel build scripts depend on CHPL_HOME, this can get encoded into - # the frontend library rpaths. this is problematic for the python - # bindings which get installed in virtualenv provided by spack. This script - # will fix the rpath of the chapel frontend library after installation - @run_after("install") - def fix_rpath(self): - files = [] - # find all .so in the old lib path - for f in glob.glob( - join_path(self.prefix.lib, "chapel", str(self._output_version_short), "**", "*.so"), - recursive=True, - ): - files.append(f) - - for f in glob.glob( - join_path(self.spec["python-venv"].prefix.lib, "**", "chapel", "*.so"), recursive=True - ): - files.append(f) - - for f in files: - cp = subprocess.run( - ["chrpath", "-l", f], - encoding="utf-8", - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - path = cp.stdout.strip() - path = self.get_path(path) - new_path = [] - # clean path - for p in path: - if p == self.prefix.lib64: - continue - if p.startswith(str(self.build_directory)): - new_path.append( - str( - join_path( - self.prefix.lib, "chapel", self._output_version_short, "compiler" - ) - ) - ) - else: - new_path.append(p) - # remove duplicates - new_path = list(set(new_path)) - path = ":".join(new_path) - if path: - subprocess.check_call(["chrpath", "-r", path, f]) - def build(self, spec, prefix): with set_env(CHPL_MAKE_THIRD_PARTY=join_path(self.build_directory, "third-party")): make() @@ -812,6 +751,8 @@ def setup_env_vars(self, env): def setup_build_environment(self, env): self.unset_chpl_env_vars(env) self.setup_env_vars(env) + chpl_lib = join_path(self.prefix.lib, "chapel", self._output_version_short, "compiler") + env.set("CHPL_SPACK_LIB_INSTALL", chpl_lib) def setup_run_environment(self, env): self.setup_env_vars(env) From 7732be2c0f44ec2ddb5ecbebc3327728b2b924c1 Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Wed, 20 Nov 2024 15:34:53 -0700 Subject: [PATCH 4/9] spack style fixes --- var/spack/repos/builtin/packages/chapel/package.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index 116d4b06766534..a9819ff92a96d6 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -3,11 +3,8 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) -import glob import os -import re import subprocess -import typing import llnl.util.lang From 12d555c5491a4ed0dc287de10988c2753d68c73e Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Thu, 5 Dec 2024 10:59:48 -0700 Subject: [PATCH 5/9] patch chapel env var line length limit --- .../packages/chapel/fix_chpl_line_length.patch | 13 +++++++++++++ var/spack/repos/builtin/packages/chapel/package.py | 1 + 2 files changed, 14 insertions(+) create mode 100644 var/spack/repos/builtin/packages/chapel/fix_chpl_line_length.patch diff --git a/var/spack/repos/builtin/packages/chapel/fix_chpl_line_length.patch b/var/spack/repos/builtin/packages/chapel/fix_chpl_line_length.patch new file mode 100644 index 00000000000000..da9cf61c496dc2 --- /dev/null +++ b/var/spack/repos/builtin/packages/chapel/fix_chpl_line_length.patch @@ -0,0 +1,13 @@ +diff --git a/compiler/util/files.cpp b/compiler/util/files.cpp +index 4183614988..9746baf935 100644 +--- a/compiler/util/files.cpp ++++ b/compiler/util/files.cpp +@@ -211,7 +211,7 @@ void restoreDriverTmp(const char* tmpFilePath, + + fileinfo* tmpFile = openTmpFile(tmpFilePath, "r"); + +- char strBuf[4096]; ++ char strBuf[8192]; + while (fgets(strBuf, sizeof(strBuf), tmpFile->fptr)) { + // Note: Using strlen here (instead of strnlen) is safe because fgets + // guarantees null termination. diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index a9819ff92a96d6..981717ee832639 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -71,6 +71,7 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): patch("fix_spack_cc_wrapper_in_cray_prgenv.patch", when="@2.0.0:") patch("fix_chpl_shared_lib_path.patch") + patch("fix_chpl_line_length.patch") launcher_names = ( "amudprun", From 1c9e649f920948bf6a8b9343d84d70bddbe89334 Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Thu, 5 Dec 2024 11:00:57 -0700 Subject: [PATCH 6/9] patch chapel python shared lib location by chapel version --- .../chapel/fix_chpl_shared_lib_path.patch | 12 +++++++---- .../chapel/fix_chpl_shared_lib_path_2.3.patch | 20 +++++++++++++++++++ .../repos/builtin/packages/chapel/package.py | 3 ++- 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch diff --git a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch index d933564757ddc8..88ba06a9464c7f 100644 --- a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch +++ b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch @@ -1,5 +1,5 @@ diff --git a/tools/chapel-py/setup.py b/tools/chapel-py/setup.py -index bee452790c..09c16fbda3 100644 +index bee452790c..fd2fe54e12 100644 --- a/tools/chapel-py/setup.py +++ b/tools/chapel-py/setup.py @@ -25,6 +25,7 @@ import sys @@ -10,10 +10,14 @@ index bee452790c..09c16fbda3 100644 chpl_printchplenv = os.path.join(chpl_home, "util", "printchplenv") chpl_variables_lines = ( subprocess.check_output( -@@ -67,6 +68,7 @@ LDFLAGS += [ +@@ -64,9 +65,9 @@ CXXFLAGS += ["-std=c++17", "-I{}/frontend/include".format(chpl_home)] + LDFLAGS = [] + LDFLAGS += [ + "-L{}".format(chpl_lib_path), ++ "-Wl,-rpath,{}".format(chpl_lib_path), "-lChplFrontendShared", - "-Wl,-rpath", - chpl_lib_path, +- "-Wl,-rpath", +- chpl_lib_path, + "-Wl,-rpath,{}".format(chpl_lib_install), ] diff --git a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch new file mode 100644 index 00000000000000..6346a647b4685b --- /dev/null +++ b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch @@ -0,0 +1,20 @@ +diff --git a/tools/chapel-py/setup.py b/tools/chapel-py/setup.py +index 30c2708724..fd2fe54e12 100644 +--- a/tools/chapel-py/setup.py ++++ b/tools/chapel-py/setup.py +@@ -25,6 +25,7 @@ import sys + import glob + + chpl_home = str(os.getenv("CHPL_HOME")) ++chpl_lib_install = str(os.getenv("CHPL_SPACK_LIB_INSTALL")) + chpl_printchplenv = os.path.join(chpl_home, "util", "printchplenv") + chpl_variables_lines = ( + subprocess.check_output( +@@ -66,6 +67,7 @@ LDFLAGS += [ + "-L{}".format(chpl_lib_path), + "-Wl,-rpath,{}".format(chpl_lib_path), + "-lChplFrontendShared", ++ "-Wl,-rpath,{}".format(chpl_lib_install), + ] + + if str(chpl_variables.get("CHPL_SANITIZE")) == "address": diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index 981717ee832639..99ef98050f419f 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -70,7 +70,8 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): depends_on("cxx", type="build") # generated patch("fix_spack_cc_wrapper_in_cray_prgenv.patch", when="@2.0.0:") - patch("fix_chpl_shared_lib_path.patch") + patch("fix_chpl_shared_lib_path.patch", when="@:2.2") + patch("fix_chpl_shared_lib_path_2.3.patch", when="@2.3:") patch("fix_chpl_line_length.patch") launcher_names = ( From 77786d4c721a8e9a4896216d9d49e77bb6cb350e Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Thu, 5 Dec 2024 15:25:44 -0700 Subject: [PATCH 7/9] unhack chpl frontend lib rpath --- .../chapel/fix_chpl_shared_lib_path.patch | 55 ++++++++++++++---- .../chapel/fix_chpl_shared_lib_path_2.3.patch | 58 +++++++++++++++---- .../repos/builtin/packages/chapel/package.py | 35 +++++++++-- 3 files changed, 120 insertions(+), 28 deletions(-) diff --git a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch index 88ba06a9464c7f..047a657d6ef11f 100644 --- a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch +++ b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path.patch @@ -1,16 +1,46 @@ diff --git a/tools/chapel-py/setup.py b/tools/chapel-py/setup.py -index bee452790c..fd2fe54e12 100644 +index bee452790c..58ec46d7e6 100644 --- a/tools/chapel-py/setup.py +++ b/tools/chapel-py/setup.py -@@ -25,6 +25,7 @@ import sys - import glob +@@ -46,7 +46,37 @@ host_cc = str(chpl_variables.get("CHPL_HOST_CC")) + host_cxx = str(chpl_variables.get("CHPL_HOST_CXX")) - chpl_home = str(os.getenv("CHPL_HOME")) -+chpl_lib_install = str(os.getenv("CHPL_SPACK_LIB_INSTALL")) - chpl_printchplenv = os.path.join(chpl_home, "util", "printchplenv") - chpl_variables_lines = ( - subprocess.check_output( -@@ -64,9 +65,9 @@ CXXFLAGS += ["-std=c++17", "-I{}/frontend/include".format(chpl_home)] + host_bin_subdir = str(chpl_variables.get("CHPL_HOST_BIN_SUBDIR")) ++ ++# construct the chpl_lib_path from chpl_home, or use the configured-prefix if it exists ++ + chpl_lib_path = os.path.join(chpl_home, "lib", "compiler", host_bin_subdir) ++chpl_install_lib_path = None ++if os.path.exists(os.path.join(chpl_home, "configured-prefix")): ++ with open(os.path.join(chpl_home, "CMakeLists.txt"), "r") as f: ++ # read CMakeLists.txt to get the CHPL_MAJOR_VERSION and CHPL_MINOR_VERSION ++ # and then construct the path from that ++ chpl_major_version = None ++ chpl_minor_version = None ++ for line in f: ++ if "set(CHPL_MAJOR_VERSION" in line: ++ chpl_major_version = line.split()[1].strip(')') ++ if "set(CHPL_MINOR_VERSION" in line: ++ chpl_minor_version = line.split()[1].strip(')') ++ if chpl_major_version is not None and chpl_minor_version is not None: ++ break ++ assert(chpl_major_version is not None and chpl_minor_version is not None) ++ chpl_version_string = "{}.{}".format(chpl_major_version, chpl_minor_version) ++ chpl_prefix = None ++ with open(os.path.join(chpl_home, "configured-prefix"), "r") as f: ++ chpl_prefix = f.read().strip() ++ assert(chpl_prefix is not None) ++ chpl_install_lib_path = os.path.join( ++ chpl_prefix, ++ "lib", ++ "chapel", ++ chpl_version_string, ++ "compiler" ++ ) + + CXXFLAGS = [] + if have_llvm and have_llvm != "none": +@@ -64,10 +94,14 @@ CXXFLAGS += ["-std=c++17", "-I{}/frontend/include".format(chpl_home)] LDFLAGS = [] LDFLAGS += [ "-L{}".format(chpl_lib_path), @@ -18,7 +48,12 @@ index bee452790c..fd2fe54e12 100644 "-lChplFrontendShared", - "-Wl,-rpath", - chpl_lib_path, -+ "-Wl,-rpath,{}".format(chpl_lib_install), ] ++if chpl_install_lib_path is not None: ++ LDFLAGS += [ ++ "-L{}".format(chpl_install_lib_path), ++ "-Wl,-rpath,{}".format(chpl_install_lib_path), ++ ] if str(chpl_variables.get("CHPL_SANITIZE")) == "address": + if str(chpl_variables.get("CHPL_HOST_PLATFORM")) == "darwin": diff --git a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch index 6346a647b4685b..c566c7329f7f84 100644 --- a/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch +++ b/var/spack/repos/builtin/packages/chapel/fix_chpl_shared_lib_path_2.3.patch @@ -1,20 +1,54 @@ diff --git a/tools/chapel-py/setup.py b/tools/chapel-py/setup.py -index 30c2708724..fd2fe54e12 100644 +index 30c2708724..3921143def 100644 --- a/tools/chapel-py/setup.py +++ b/tools/chapel-py/setup.py -@@ -25,6 +25,7 @@ import sys - import glob +@@ -47,6 +47,36 @@ host_cxx = str(chpl_variables.get("CHPL_HOST_CXX")) - chpl_home = str(os.getenv("CHPL_HOME")) -+chpl_lib_install = str(os.getenv("CHPL_SPACK_LIB_INSTALL")) - chpl_printchplenv = os.path.join(chpl_home, "util", "printchplenv") - chpl_variables_lines = ( - subprocess.check_output( -@@ -66,6 +67,7 @@ LDFLAGS += [ - "-L{}".format(chpl_lib_path), - "-Wl,-rpath,{}".format(chpl_lib_path), + host_bin_subdir = str(chpl_variables.get("CHPL_HOST_BIN_SUBDIR")) + chpl_lib_path = os.path.join(chpl_home, "lib", "compiler", host_bin_subdir) ++# For installations using --prefix, the lib final lib path is going to be different ++# figure it out now and write it to the rpath ++chpl_install_lib_path = None ++if os.path.exists(os.path.join(chpl_home, "configured-prefix")): ++ with open(os.path.join(chpl_home, "CMakeLists.txt"), "r") as f: ++ # read CMakeLists.txt to get the CHPL_MAJOR_VERSION and CHPL_MINOR_VERSION ++ # and then construct the path from that ++ chpl_major_version = None ++ chpl_minor_version = None ++ for line in f: ++ if "set(CHPL_MAJOR_VERSION" in line: ++ chpl_major_version = line.split()[1].strip(')') ++ if "set(CHPL_MINOR_VERSION" in line: ++ chpl_minor_version = line.split()[1].strip(')') ++ if chpl_major_version is not None and chpl_minor_version is not None: ++ break ++ assert(chpl_major_version is not None and chpl_minor_version is not None) ++ chpl_version_string = "{}.{}".format(chpl_major_version, chpl_minor_version) ++ chpl_prefix = None ++ with open(os.path.join(chpl_home, "configured-prefix"), "r") as f: ++ chpl_prefix = f.read().strip() ++ assert(chpl_prefix is not None) ++ chpl_install_lib_path = os.path.join( ++ chpl_prefix, ++ "lib", ++ "chapel", ++ chpl_version_string, ++ "compiler" ++ ) ++ + + CXXFLAGS = [] + if have_llvm and have_llvm != "none": +@@ -68,6 +98,12 @@ LDFLAGS += [ "-lChplFrontendShared", -+ "-Wl,-rpath,{}".format(chpl_lib_install), ] ++if chpl_install_lib_path is not None: ++ LDFLAGS += [ ++ "-L{}".format(chpl_install_lib_path), ++ "-Wl,-rpath,{}".format(chpl_install_lib_path), ++ ] ++ if str(chpl_variables.get("CHPL_SANITIZE")) == "address": + if str(chpl_variables.get("CHPL_HOST_PLATFORM")) == "darwin": + sys.exit( diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index 99ef98050f419f..6908dd8b9ee890 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -70,8 +70,8 @@ class Chapel(AutotoolsPackage, CudaPackage, ROCmPackage): depends_on("cxx", type="build") # generated patch("fix_spack_cc_wrapper_in_cray_prgenv.patch", when="@2.0.0:") - patch("fix_chpl_shared_lib_path.patch", when="@:2.2") - patch("fix_chpl_shared_lib_path_2.3.patch", when="@2.3:") + patch("fix_chpl_shared_lib_path.patch", when="@2.1:2.2 +python-bindings") + patch("fix_chpl_shared_lib_path_2.3.patch", when="@2.2.1: +python-bindings") patch("fix_chpl_line_length.patch") launcher_names = ( @@ -596,6 +596,11 @@ def build(self, spec, prefix): python("-m", "ensurepip", "--default-pip") python("-m", "pip", "install", "tools/chapel-py") + def install(self, spec, prefix): + make("install") + if str(spec.version).lower() == "main": + install("CMakeLists.txt", join_path(prefix.share, "chapel")) + def setup_chpl_platform(self, env): if self.spec.variants["host_platform"].value == "unset": if is_CrayEX(): @@ -750,8 +755,6 @@ def setup_env_vars(self, env): def setup_build_environment(self, env): self.unset_chpl_env_vars(env) self.setup_env_vars(env) - chpl_lib = join_path(self.prefix.lib, "chapel", self._output_version_short, "compiler") - env.set("CHPL_SPACK_LIB_INSTALL", chpl_lib) def setup_run_environment(self, env): self.setup_env_vars(env) @@ -763,11 +766,31 @@ def setup_run_environment(self, env): ) env.set("CHPL_HOME", chpl_home) + def get_main_version_from_cmakelists(self) -> str: + with open(join_path(self.build_directory, "CMakeLists.txt"), "r") as f: + # read CMakeLists.txt to get the CHPL_MAJOR_VERSION and CHPL_MINOR_VERSION + # and then construct the path from that + chpl_major_version = None + chpl_minor_version = None + chpl_patch_version = None + for line in f: + if "set(CHPL_MAJOR_VERSION" in line: + chpl_major_version = line.split()[1].strip(')') + if "set(CHPL_MINOR_VERSION" in line: + chpl_minor_version = line.split()[1].strip(')') + if "set(CHPL_PATCH_VERSION" in line: + chpl_patch_version = line.split()[1].strip(')') + if chpl_major_version is not None and chpl_minor_version is not None and chpl_patch_version is not None: + break + assert(chpl_major_version is not None and chpl_minor_version is not None and chpl_patch_version is not None) + chpl_version_string = "{}.{}.{}".format(chpl_major_version, chpl_minor_version, chpl_patch_version) + return chpl_version_string + @property @llnl.util.lang.memoized def _output_version_long(self) -> str: if str(self.spec.version).lower() == "main": - return "2.3.0" + return self.get_main_version_from_cmakelists() spec_vers_str = str(self.spec.version.up_to(3)) return spec_vers_str @@ -775,7 +798,7 @@ def _output_version_long(self) -> str: @llnl.util.lang.memoized def _output_version_short(self) -> str: if str(self.spec.version).lower() == "main": - return "2.3" + return self.get_main_version_from_cmakelists()[-2] spec_vers_str = str(self.spec.version.up_to(2)) return spec_vers_str From 41a4658651bfe80f4739c110238f0fdb4113d948 Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Mon, 9 Dec 2024 12:29:03 -0700 Subject: [PATCH 8/9] spack style fixes --- .../repos/builtin/packages/chapel/package.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index 6908dd8b9ee890..87144df9f3eb3c 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -775,15 +775,25 @@ def get_main_version_from_cmakelists(self) -> str: chpl_patch_version = None for line in f: if "set(CHPL_MAJOR_VERSION" in line: - chpl_major_version = line.split()[1].strip(')') + chpl_major_version = line.split()[1].strip(")") if "set(CHPL_MINOR_VERSION" in line: - chpl_minor_version = line.split()[1].strip(')') + chpl_minor_version = line.split()[1].strip(")") if "set(CHPL_PATCH_VERSION" in line: - chpl_patch_version = line.split()[1].strip(')') - if chpl_major_version is not None and chpl_minor_version is not None and chpl_patch_version is not None: + chpl_patch_version = line.split()[1].strip(")") + if ( + chpl_major_version is not None + and chpl_minor_version is not None + and chpl_patch_version is not None + ): break - assert(chpl_major_version is not None and chpl_minor_version is not None and chpl_patch_version is not None) - chpl_version_string = "{}.{}.{}".format(chpl_major_version, chpl_minor_version, chpl_patch_version) + assert ( + chpl_major_version is not None + and chpl_minor_version is not None + and chpl_patch_version is not None + ) + chpl_version_string = "{}.{}.{}".format( + chpl_major_version, chpl_minor_version, chpl_patch_version + ) return chpl_version_string @property From e2f248eac421e7e285a6f4290576072c67f8d5e0 Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Mon, 9 Dec 2024 13:54:30 -0700 Subject: [PATCH 9/9] fix postinstall main version number file path --- .../repos/builtin/packages/chapel/package.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/var/spack/repos/builtin/packages/chapel/package.py b/var/spack/repos/builtin/packages/chapel/package.py index 87144df9f3eb3c..e55aade99d1972 100644 --- a/var/spack/repos/builtin/packages/chapel/package.py +++ b/var/spack/repos/builtin/packages/chapel/package.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os +import re import subprocess import llnl.util.lang @@ -767,7 +768,13 @@ def setup_run_environment(self, env): env.set("CHPL_HOME", chpl_home) def get_main_version_from_cmakelists(self) -> str: - with open(join_path(self.build_directory, "CMakeLists.txt"), "r") as f: + cmake_lists = None + if os.path.exists(join_path(self.prefix.share, "chapel", "CMakeLists.txt")): + cmake_lists = join_path(self.prefix.share, "chapel", "CMakeLists.txt") + else: + cmake_lists = join_path(self.build_directory, "CMakeLists.txt") + assert cmake_lists is not None and os.path.exists(cmake_lists) + with open(cmake_lists, "r") as f: # read CMakeLists.txt to get the CHPL_MAJOR_VERSION and CHPL_MINOR_VERSION # and then construct the path from that chpl_major_version = None @@ -796,10 +803,15 @@ def get_main_version_from_cmakelists(self) -> str: ) return chpl_version_string + def is_versioned_release(self) -> bool: + # detect main or possibly other branch names + matches = re.findall(r"[^0-9.]", str(self.spec.version)) + return len(matches) == 0 + @property @llnl.util.lang.memoized def _output_version_long(self) -> str: - if str(self.spec.version).lower() == "main": + if not self.is_versioned_release(): return self.get_main_version_from_cmakelists() spec_vers_str = str(self.spec.version.up_to(3)) return spec_vers_str @@ -807,7 +819,7 @@ def _output_version_long(self) -> str: @property @llnl.util.lang.memoized def _output_version_short(self) -> str: - if str(self.spec.version).lower() == "main": + if not self.is_versioned_release(): return self.get_main_version_from_cmakelists()[-2] spec_vers_str = str(self.spec.version.up_to(2)) return spec_vers_str