From aea50674847d15ef3419f67d0ff4c1f64239fb03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eric=20M=C3=BCller?= <mueller@kip.uni-heidelberg.de>
Date: Wed, 28 Feb 2024 13:28:20 +0100
Subject: [PATCH] feat(BSS-2): cleanup env handling during build

---
 packages/hxtorch/package.py          | 51 ++++++++++++++++++----------
 packages/pynn-brainscales/package.py | 51 ++++++++++++++++++----------
 2 files changed, 66 insertions(+), 36 deletions(-)

diff --git a/packages/hxtorch/package.py b/packages/hxtorch/package.py
index 95413009..e3eebd1a 100644
--- a/packages/hxtorch/package.py
+++ b/packages/hxtorch/package.py
@@ -5,6 +5,8 @@
 import os
 
 from spack import *
+from spack.util.environment import EnvironmentModifications
+import spack.build_environment
 
 
 class Hxtorch(WafPackage):
@@ -71,8 +73,37 @@ class Hxtorch(WafPackage):
             dep = self.spec[ppu_dep_name]
             dep_include_dirs = set(dep.headers.directories)
             ppu_include_dirs.extend(list(dep_include_dirs))
-        env.set('C_INCLUDE_PATH', ':'.join(ppu_include_dirs))
-        env.set('CPLUS_INCLUDE_PATH', ':'.join(ppu_include_dirs))
+        for dir in reversed(ppu_include_dirs):
+            env.prepend_path("C_INCLUDE_PATH", dir)
+            env.prepend_path("CPLUS_INCLUDE_PATH", dir)
+
+    def setup_build_environment(self, env):
+        my_envmod = EnvironmentModifications(env)
+        spack.build_environment.set_wrapper_variables(self, my_envmod)
+        my_env = {}
+        my_envmod.apply_modifications(my_env)
+
+        def get_path(env, name):
+            path = env.get(name, "").strip()
+            if path:
+                return path.split(os.pathsep)
+            return []
+
+        # spack tries to find headers and libraries by itself (i.e. it's not
+        # relying on the compiler to find it); we explicitly expose the
+        # spack-provided env vars that contain include and library paths
+        if 'SPACK_INCLUDE_DIRS' in my_env:
+            for dir in reversed(get_path(my_env, "SPACK_INCLUDE_DIRS")):
+                env.prepend_path("C_INCLUDE_PATH", dir)
+                env.prepend_path("CPLUS_INCLUDE_PATH", dir)
+        if 'SPACK_LINK_DIRS' in my_env:
+            for dir in reversed(get_path(my_env, "SPACK_LINK_DIRS")):
+                env.prepend_path("LIBRARY_PATH", dir)
+                env.prepend_path("LD_LIBRARY_PATH", dir)
+        for dir in reversed(self.compiler.implicit_rpaths()):
+            env.prepend_path("LIBRARY_PATH", dir)
+            # technically this is probably not needed for the non-configure steps
+            env.prepend_path("LD_LIBRARY_PATH", dir)
 
     def setup_dependent_build_environment(self, env, dependent_spec):
         self._setup_common_env(env)
@@ -87,20 +118,6 @@ class Hxtorch(WafPackage):
     def configure(self, spec, prefix):
         """Setup and configure the project."""
 
-        # spack tries to find headers and libraries by itself (i.e. it's not
-        # relying on the compiler to find it); we explicitly expose the
-        # spack-provided env vars that contain include and library paths
-        env = os.environ
-        if 'SPACK_INCLUDE_DIRS' in env:
-            env['C_INCLUDE_PATH'] = env['SPACK_INCLUDE_DIRS']
-            env['CPLUS_INCLUDE_PATH'] = env['SPACK_INCLUDE_DIRS']
-        if 'SPACK_LINK_DIRS' in env:
-            env['LIBRARY_PATH'] = env['SPACK_LINK_DIRS']
-            env['LD_LIBRARY_PATH'] = env['SPACK_LINK_DIRS']
-        if 'SPACK_COMPILER_IMPLICIT_RPATHS' in env:
-            env['LIBRARY_PATH'] = env['SPACK_COMPILER_IMPLICIT_RPATHS'] + ':' + env['LIBRARY_PATH']
-            env['WAF_CONFIGURE_LD_LIBRARY_PATH'] = env['SPACK_COMPILER_IMPLICIT_RPATHS'] + ':' + env['LD_LIBRARY_PATH']
-
         self.waf('setup', '--repo-db-url=https://github.com/electronicvisions/projects',
             '--without-munge',
             '--without-hxcomm-hostarq',
@@ -111,8 +128,6 @@ class Hxtorch(WafPackage):
 
         args = ['--prefix={0}'.format(self.prefix)]
         args += self.configure_args()
-
-        env['LD_LIBRARY_PATH'] = env.get('WAF_CONFIGURE_LD_LIBRARY_PATH')
         self.waf('configure', '--build-profile=release', '--disable-doxygen', *args)
 
     def build_args(self):
diff --git a/packages/pynn-brainscales/package.py b/packages/pynn-brainscales/package.py
index fda6b150..93ed8f5d 100644
--- a/packages/pynn-brainscales/package.py
+++ b/packages/pynn-brainscales/package.py
@@ -5,6 +5,8 @@
 import os
 
 from spack import *
+from spack.util.environment import EnvironmentModifications
+import spack.build_environment
 
 
 class PynnBrainscales(WafPackage):
@@ -68,8 +70,37 @@ class PynnBrainscales(WafPackage):
             dep = self.spec[ppu_dep_name]
             dep_include_dirs = set(dep.headers.directories)
             ppu_include_dirs.extend(list(dep_include_dirs))
-        env.set('C_INCLUDE_PATH', ':'.join(ppu_include_dirs))
-        env.set('CPLUS_INCLUDE_PATH', ':'.join(ppu_include_dirs))
+        for dir in reversed(ppu_include_dirs):
+            env.prepend_path("C_INCLUDE_PATH", dir)
+            env.prepend_path("CPLUS_INCLUDE_PATH", dir)
+
+    def setup_build_environment(self, env):
+        my_envmod = EnvironmentModifications(env)
+        spack.build_environment.set_wrapper_variables(self, my_envmod)
+        my_env = {}
+        my_envmod.apply_modifications(my_env)
+
+        def get_path(env, name):
+            path = env.get(name, "").strip()
+            if path:
+                return path.split(os.pathsep)
+            return []
+
+        # spack tries to find headers and libraries by itself (i.e. it's not
+        # relying on the compiler to find it); we explicitly expose the
+        # spack-provided env vars that contain include and library paths
+        if 'SPACK_INCLUDE_DIRS' in my_env:
+            for dir in reversed(get_path(my_env, "SPACK_INCLUDE_DIRS")):
+                env.prepend_path("C_INCLUDE_PATH", dir)
+                env.prepend_path("CPLUS_INCLUDE_PATH", dir)
+        if 'SPACK_LINK_DIRS' in my_env:
+            for dir in reversed(get_path(my_env, "SPACK_LINK_DIRS")):
+                env.prepend_path("LIBRARY_PATH", dir)
+                env.prepend_path("LD_LIBRARY_PATH", dir)
+        for dir in reversed(self.compiler.implicit_rpaths()):
+            env.prepend_path("LIBRARY_PATH", dir)
+            # technically this is probably not needed for the non-configure steps
+            env.prepend_path("LD_LIBRARY_PATH", dir)
 
     def setup_dependent_build_environment(self, env, dependent_spec):
         self._setup_common_env(env)
@@ -84,20 +115,6 @@ class PynnBrainscales(WafPackage):
     def configure(self, spec, prefix):
         """Setup and configure the project."""
 
-        # spack tries to find headers and libraries by itself (i.e. it's not
-        # relying on the compiler to find it); we explicitly expose the
-        # spack-provided env vars that contain include and library paths
-        env = os.environ
-        if 'SPACK_INCLUDE_DIRS' in env:
-            env['C_INCLUDE_PATH'] = env['SPACK_INCLUDE_DIRS']
-            env['CPLUS_INCLUDE_PATH'] = env['SPACK_INCLUDE_DIRS']
-        if 'SPACK_LINK_DIRS' in env:
-            env['LIBRARY_PATH'] = env['SPACK_LINK_DIRS']
-            env['LD_LIBRARY_PATH'] = env['SPACK_LINK_DIRS']
-        if 'SPACK_COMPILER_IMPLICIT_RPATHS' in env:
-            env['LIBRARY_PATH'] = env['SPACK_COMPILER_IMPLICIT_RPATHS'] + ':' + env['LIBRARY_PATH']
-            env['WAF_CONFIGURE_LD_LIBRARY_PATH'] = env['SPACK_COMPILER_IMPLICIT_RPATHS'] + ':' + env['LD_LIBRARY_PATH']
-
         self.waf('setup', '--repo-db-url=https://github.com/electronicvisions/projects',
             '--without-munge',
             '--without-hxcomm-hostarq',
@@ -108,8 +125,6 @@ class PynnBrainscales(WafPackage):
 
         args = ['--prefix={0}'.format(self.prefix)]
         args += self.configure_args()
-
-        env['LD_LIBRARY_PATH'] = env.get('WAF_CONFIGURE_LD_LIBRARY_PATH')
         self.waf('configure', '--build-profile=release', '--disable-doxygen', *args)
 
     def build_args(self):
-- 
GitLab