@@ -118,6 +118,41 @@ def clone_spack(self):
118
118
if self .args .debug :
119
119
sexe (f"git -C { spack_dir } clean -df" )
120
120
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
+
121
156
def custom_spack_env (self , env_dir , env_name ):
122
157
"Use/create a custom Spack environment"
123
158
from spack import environment
@@ -137,67 +172,56 @@ def custom_spack_env(self, env_dir, env_name):
137
172
dev_cmd = SpackCommand ("develop" )
138
173
comp_cmd = SpackCommand ("compiler" )
139
174
ext_cmd = SpackCommand ("external" )
175
+ cur_repos = repo_cmd ("list" ) # spack repo list
140
176
141
177
# Add the repos and develop paths to the spack environment
142
- cur_repos = repo_cmd ("list" ) # spack repo list
143
178
for package , path in package_dirs .items ():
144
179
if (package + " " not in cur_repos ):
145
180
repo_path = os .path .abspath (get_config_dir (path ))
146
181
repo_cmd ("add" , f"{ repo_path } " ) # spack repo add <repo_path>
147
182
dev_path = os .path .abspath (path )
148
183
dev_cmd ("-p" , dev_path , f"{ package } @=develop" ) # spack develop <package>@=develop
149
184
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" )
155
185
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 )
165
203
# Always add the spec for a custom environment
166
204
self .args .add_spec = True
167
205
168
206
def remove_upstream (self , env_dir ):
169
207
"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" )
173
208
# TODO: Currently, Spack has no other way to
174
209
# to remove an include: line from an environment
175
210
# 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
185
211
# 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
194
220
195
221
# Copy spack.yaml to origspack.yaml and overwrite spack.yaml
196
222
# 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 )
201
225
202
226
def activate_spack_env (self ):
203
227
"Activates a Spack environment or creates and activates one when necessary"
0 commit comments