summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/build_systems/autotools.py125
1 files changed, 57 insertions, 68 deletions
diff --git a/lib/spack/spack/build_systems/autotools.py b/lib/spack/spack/build_systems/autotools.py
index d73416be21..ee9fb6884e 100644
--- a/lib/spack/spack/build_systems/autotools.py
+++ b/lib/spack/spack/build_systems/autotools.py
@@ -3,10 +3,9 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import inspect
+import itertools
import os
import os.path
-import shutil
-import stat
from subprocess import PIPE
from subprocess import check_call
@@ -103,8 +102,8 @@ class AutotoolsPackage(PackageBase):
"""Some packages ship with older config.guess/config.sub files and
need to have these updated when installed on a newer architecture.
In particular, config.guess fails for PPC64LE for version prior
- to a 2013-06-10 build date (automake 1.13.4) and for ARM (aarch64)."""
-
+ to a 2013-06-10 build date (automake 1.13.4) and for ARM (aarch64).
+ """
if not self.patch_config_files or (
not self.spec.satisfies('target=ppc64le:') and
not self.spec.satisfies('target=aarch64:')
@@ -121,70 +120,60 @@ class AutotoolsPackage(PackageBase):
else:
config_arch = 'local'
- my_config_files = {'guess': None, 'sub': None}
- config_files = {'guess': None, 'sub': None}
- config_args = {'guess': [], 'sub': [config_arch]}
-
- for config_name in config_files.keys():
- config_file = 'config.{0}'.format(config_name)
- if os.path.exists(config_file):
- # First search the top-level source directory
- my_config_files[config_name] = os.path.abspath(config_file)
- else:
- # Then search in all sub directories recursively.
- # We would like to use AC_CONFIG_AUX_DIR, but not all packages
- # ship with their configure.in or configure.ac.
- config_path = next((os.path.abspath(os.path.join(r, f))
- for r, ds, fs in os.walk('.') for f in fs
- if f == config_file), None)
- my_config_files[config_name] = config_path
-
- if my_config_files[config_name] is not None:
- try:
- config_path = my_config_files[config_name]
- check_call([config_path] + config_args[config_name],
- stdout=PIPE, stderr=PIPE)
- # The package's config file already runs OK, so just use it
- continue
- except Exception as e:
- tty.debug(e)
- else:
- continue
-
- # Look for a spack-installed automake package
- if 'automake' in self.spec:
- automake_dir = 'automake-' + str(self.spec['automake'].version)
- automake_path = os.path.join(self.spec['automake'].prefix,
- 'share', automake_dir)
- path = os.path.join(automake_path, config_file)
- if os.path.exists(path):
- config_files[config_name] = path
- # Look for the system's config.guess
- if (config_files[config_name] is None and
- os.path.exists('/usr/share')):
- automake_dir = [s for s in os.listdir('/usr/share') if
- "automake" in s]
- if automake_dir:
- automake_path = os.path.join('/usr/share', automake_dir[0])
- path = os.path.join(automake_path, config_file)
- if os.path.exists(path):
- config_files[config_name] = path
- if config_files[config_name] is not None:
- try:
- config_path = config_files[config_name]
- my_config_path = my_config_files[config_name]
-
- check_call([config_path] + config_args[config_name],
- stdout=PIPE, stderr=PIPE)
-
- m = os.stat(my_config_path).st_mode & 0o777 | stat.S_IWUSR
- os.chmod(my_config_path, m)
- shutil.copyfile(config_path, my_config_path)
- continue
- except Exception as e:
- tty.debug(e)
-
- raise RuntimeError('Failed to find suitable ' + config_file)
+ def runs_ok(script_abs_path):
+ # Construct the list of arguments for the call
+ additional_args = {
+ 'config.sub': [config_arch]
+ }
+ script_name = os.path.basename(script_abs_path)
+ args = [script_abs_path] + additional_args.get(script_name, [])
+
+ try:
+ check_call(args, stdout=PIPE, stderr=PIPE)
+ except Exception as e:
+ tty.debug(e)
+ return False
+
+ return True
+
+ # Compute the list of files that needs to be patched
+ search_dir = self.stage.path
+ to_be_patched = fs.find(
+ search_dir, files=['config.sub', 'config.guess'], recursive=True
+ )
+ to_be_patched = [f for f in to_be_patched if not runs_ok(f)]
+
+ # If there are no files to be patched, return early
+ if not to_be_patched:
+ return
+
+ # Directories where to search for files to be copied
+ # over the failing ones
+ good_file_dirs = ['/usr/share']
+ if 'automake' in self.spec:
+ good_file_dirs.insert(0, self.spec['automake'].prefix)
+
+ # List of files to be found in the directories above
+ to_be_found = list(set(os.path.basename(f) for f in to_be_patched))
+ substitutes = {}
+ for directory in good_file_dirs:
+ candidates = fs.find(directory, files=to_be_found, recursive=True)
+ candidates = [f for f in candidates if runs_ok(f)]
+ for name, good_files in itertools.groupby(
+ candidates, key=os.path.basename
+ ):
+ substitutes[name] = next(good_files)
+ to_be_found.remove(name)
+
+ # Check that we found everything we needed
+ if to_be_found:
+ msg = 'Failed to find suitable substitutes for {0}'
+ raise RuntimeError(msg.format(', '.join(to_be_found)))
+
+ # Copy the good files over the bad ones
+ for abs_path in to_be_patched:
+ name = os.path.basename(abs_path)
+ fs.copy(substitutes[name], abs_path)
@run_before('configure')
def _set_autotools_environment_variables(self):