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>
This commit is contained in:
parent
cdeecf2507
commit
a481087695
1 changed files with 51 additions and 62 deletions
|
@ -3,10 +3,9 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
import inspect
|
import inspect
|
||||||
|
import itertools
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import shutil
|
|
||||||
import stat
|
|
||||||
from subprocess import PIPE
|
from subprocess import PIPE
|
||||||
from subprocess import check_call
|
from subprocess import check_call
|
||||||
|
|
||||||
|
@ -103,8 +102,8 @@ def _do_patch_config_files(self):
|
||||||
"""Some packages ship with older config.guess/config.sub files and
|
"""Some packages ship with older config.guess/config.sub files and
|
||||||
need to have these updated when installed on a newer architecture.
|
need to have these updated when installed on a newer architecture.
|
||||||
In particular, config.guess fails for PPC64LE for version prior
|
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 (
|
if not self.patch_config_files or (
|
||||||
not self.spec.satisfies('target=ppc64le:') and
|
not self.spec.satisfies('target=ppc64le:') and
|
||||||
not self.spec.satisfies('target=aarch64:')
|
not self.spec.satisfies('target=aarch64:')
|
||||||
|
@ -121,70 +120,60 @@ def _do_patch_config_files(self):
|
||||||
else:
|
else:
|
||||||
config_arch = 'local'
|
config_arch = 'local'
|
||||||
|
|
||||||
my_config_files = {'guess': None, 'sub': None}
|
def runs_ok(script_abs_path):
|
||||||
config_files = {'guess': None, 'sub': None}
|
# Construct the list of arguments for the call
|
||||||
config_args = {'guess': [], 'sub': [config_arch]}
|
additional_args = {
|
||||||
|
'config.sub': [config_arch]
|
||||||
|
}
|
||||||
|
script_name = os.path.basename(script_abs_path)
|
||||||
|
args = [script_abs_path] + additional_args.get(script_name, [])
|
||||||
|
|
||||||
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:
|
try:
|
||||||
config_path = my_config_files[config_name]
|
check_call(args, stdout=PIPE, stderr=PIPE)
|
||||||
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:
|
except Exception as e:
|
||||||
tty.debug(e)
|
tty.debug(e)
|
||||||
else:
|
return False
|
||||||
continue
|
|
||||||
|
|
||||||
# Look for a spack-installed automake package
|
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:
|
if 'automake' in self.spec:
|
||||||
automake_dir = 'automake-' + str(self.spec['automake'].version)
|
good_file_dirs.insert(0, self.spec['automake'].prefix)
|
||||||
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],
|
# List of files to be found in the directories above
|
||||||
stdout=PIPE, stderr=PIPE)
|
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)
|
||||||
|
|
||||||
m = os.stat(my_config_path).st_mode & 0o777 | stat.S_IWUSR
|
# Check that we found everything we needed
|
||||||
os.chmod(my_config_path, m)
|
if to_be_found:
|
||||||
shutil.copyfile(config_path, my_config_path)
|
msg = 'Failed to find suitable substitutes for {0}'
|
||||||
continue
|
raise RuntimeError(msg.format(', '.join(to_be_found)))
|
||||||
except Exception as e:
|
|
||||||
tty.debug(e)
|
|
||||||
|
|
||||||
raise RuntimeError('Failed to find suitable ' + config_file)
|
# 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')
|
@run_before('configure')
|
||||||
def _set_autotools_environment_variables(self):
|
def _set_autotools_environment_variables(self):
|
||||||
|
|
Loading…
Reference in a new issue