Skip to content

Commit 2995685

Browse files
committed
Improve modifying spack.yaml file, improve package finding methods for external builds
1 parent a9267f6 commit 2995685

File tree

2 files changed

+64
-40
lines changed

2 files changed

+64
-40
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ ARG HOST_CONFIG=docker-$SPEC
3131
ENV DEBIAN_FRONTEND=noninteractive
3232
RUN apt-get update -y
3333
RUN apt-get upgrade -y
34-
RUN apt-get install -y build-essential git gfortran mpich autotools-dev autoconf sqlite pkg-config uuid gettext libncurses-dev libgdbm-dev libffi-dev libssl-dev libexpat-dev libreadline-dev libbz2-dev locales python python3 unzip libtool wget curl tk-dev
34+
RUN apt-get install -y build-essential git gfortran mpich autotools-dev autoconf sqlite pkg-config uuid gettext cmake libncurses-dev libgdbm-dev libffi-dev libssl-dev libexpat-dev libreadline-dev libbz2-dev locales python python3 unzip libtool wget curl tk-dev
3535
RUN apt-get install -y python3-dev python3-venv python3-pip
3636
RUN apt-get install -y iputils-ping
3737

scripts/devtools/tpl-manager.py

+63-39
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,41 @@ def clone_spack(self):
118118
if self.args.debug:
119119
sexe(f"git -C {spack_dir} clean -df")
120120

121+
def find_spack_package(self, package_names):
122+
"""
123+
Find if the package name/s is already in the environment.
124+
If any one of them are found, return the name of that package
125+
If not, run spack external find and raise an error if none are found
126+
"""
127+
cur_packages = spack.config.get("packages")
128+
if (type(package_names) is not list):
129+
package_names = [package_names]
130+
for i in package_names:
131+
if (i in cur_packages):
132+
return i
133+
ext_cmd = SpackCommand("external")
134+
find_out = ext_cmd("find", "--not-buildable", *package_names)
135+
for i in package_names:
136+
if (i in find_out):
137+
return i
138+
raise Exception(f"System install of {package_names} not found. "+\
139+
"If software is installed, add location to $PATH "+\
140+
"environment variable. Otherwise, install package.")
141+
142+
def modify_env_file(self, env_dir, mod_func):
143+
"Modify the spack.yaml file"
144+
from spack.util import spack_yaml
145+
env_file = os.path.join(env_dir, "spack.yaml")
146+
# Load the spack.yaml file
147+
with open(env_file) as ff:
148+
try:
149+
loader = spack_yaml.load(ff)
150+
except SpackYAMLError as exception:
151+
print(exception)
152+
loader = mod_func(loader)
153+
with open(env_file, 'w') as ff:
154+
spack_yaml.dump(loader, ff)
155+
121156
def custom_spack_env(self, env_dir, env_name):
122157
"Use/create a custom Spack environment"
123158
from spack import environment
@@ -137,67 +172,56 @@ def custom_spack_env(self, env_dir, env_name):
137172
dev_cmd = SpackCommand("develop")
138173
comp_cmd = SpackCommand("compiler")
139174
ext_cmd = SpackCommand("external")
175+
cur_repos = repo_cmd("list") # spack repo list
140176

141177
# Add the repos and develop paths to the spack environment
142-
cur_repos = repo_cmd("list") # spack repo list
143178
for package, path in package_dirs.items():
144179
if (package+" " not in cur_repos):
145180
repo_path = os.path.abspath(get_config_dir(path))
146181
repo_cmd("add", f"{repo_path}") # spack repo add <repo_path>
147182
dev_path = os.path.abspath(path)
148183
dev_cmd("-p", dev_path, f"{package}@=develop") # spack develop <package>@=develop
149184

150-
# Find external packages and compilers
151-
# List of packages to find externally
152-
ext_packages = ["git", "pkg-config", "autoconf", "automake"]
153-
if (not spack.spec.Spec(self.args.spec).satisfies("~mpi")):
154-
ext_packages.append("mpich")
155185
comp_cmd("find") # spack compiler find
156-
# Ignore any packages that are already found
157-
cur_packages = spack.config.get("packages")
158-
for i in ext_packages:
159-
if (i in cur_packages):
160-
ext_packages.remove(i)
161-
ext_cmd("find", *ext_packages)
162-
cur_packages = spack.config.get("packages")
163-
# TODO: Add logic to inform user when packages arent found
164-
# to encourage them to potentially add their own paths
186+
ext_cmd("find")
187+
# req_packages are packages we refuse to let spack build
188+
# If they aren't found, an error will be thrown telling the user
189+
# to install the package or ensure an install is in $PATH
190+
req_packages = ["python", "perl"]
191+
for i in req_packages:
192+
self.find_spack_package(i)
193+
# Look for MPI installs
194+
if (not spack.spec.Spec(self.args.spec).satisfies("~mpi")):
195+
mpi_packages = ["mpich", "openmpi"]
196+
mpi_pack = self.find_spack_package(mpi_packages)
197+
# Modify the providers to ensure the MPI package is being used
198+
def set_provider(loader):
199+
new_data = {"all": {"providers": {"mpi": [mpi_pack]}}}
200+
loader["spack"]["packages"].update(new_data)
201+
return loader
202+
self.modify_env_file(env_dir, set_provider)
165203
# Always add the spec for a custom environment
166204
self.args.add_spec = True
167205

168206
def remove_upstream(self, env_dir):
169207
"Modify the spack.yaml to remove the upstream"
170-
# Copy original file
171-
from spack.util import spack_yaml
172-
env_file = os.path.join(env_dir, "spack.yaml")
173208
# TODO: Currently, Spack has no other way to
174209
# to remove an include: line from an environment
175210
# than to directly change the spack.yaml file
176-
177-
# Load the spack.yaml file
178-
with open(env_file) as ff:
179-
try:
180-
loader = spack_yaml.load(ff)
181-
except SpackYAMLError as exception:
182-
print(exception)
183-
184-
modded_file = False
185211
# Remove upstream.yaml or upstream entry
186-
if ("upstreams" in loader["spack"]):
187-
del loader["spack"]["upstreams"]
188-
modded_file = True
189-
if ("include" in loader["spack"]):
190-
for i, x in enumerate(loader["spack"]["include"]):
191-
if ("upstreams.yaml" in x):
192-
del loader["spack"]["include"][i]
193-
modded_file = True
212+
def do_remove(loader):
213+
if ("upstreams" in loader["spack"]):
214+
del loader["spack"]["upstreams"]
215+
if ("include" in loader["spack"]):
216+
for i, x in enumerate(loader["spack"]["include"]):
217+
if ("upstreams.yaml" in x):
218+
del loader["spack"]["include"][i]
219+
return loader
194220

195221
# Copy spack.yaml to origspack.yaml and overwrite spack.yaml
196222
# with upstreams removed
197-
if (modded_file):
198-
shutil.copyfile(env_file, os.path.join(env_dir, "origspack.yaml"))
199-
with open(env_file, 'w') as ff:
200-
spack_yaml.dump(loader, ff)
223+
shutil.copyfile(env_file, os.path.join(env_dir, "origspack.yaml"))
224+
self.modify_env_file(env_dir, do_remove)
201225

202226
def activate_spack_env(self):
203227
"Activates a Spack environment or creates and activates one when necessary"

0 commit comments

Comments
 (0)