summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorToyohisa Kameyama <kameyama@riken.jp>2020-10-16 18:30:06 +0900
committerGitHub <noreply@github.com>2020-10-16 11:30:06 +0200
commita481087695346828db4d5f9e7f489e15a54630cc (patch)
tree4fe37c636347f096c6bbc2f4958147e38b9eaf84 /lib
parentcdeecf2507d92c41625c9d7d3ee21b973c404f5b (diff)
downloadspack-a481087695346828db4d5f9e7f489e15a54630cc.tar.gz
spack-a481087695346828db4d5f9e7f489e15a54630cc.tar.bz2
spack-a481087695346828db4d5f9e7f489e15a54630cc.tar.xz
spack-a481087695346828db4d5f9e7f489e15a54630cc.zip
autotools: recursively patch config.guess and config.sub (#18347)
Previously config.guess and config.sub were patched only in the root of the source path. This modification extend the previous behavior to patch every config.guess or config.sub file even in subfolders, if need be. Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Diffstat (limited to 'lib')
-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):