From 3753424a87ebb86e9b6c972a8d136c8c2f2f604b Mon Sep 17 00:00:00 2001 From: Michael Kuhn Date: Mon, 24 Feb 2020 15:34:57 +0100 Subject: [PATCH] modules: store configure args during build (#11084) This change stores packages' configure arguments during build and makes use of them while refreshing module files. This fixes problems such as in #10716. --- lib/spack/spack/installer.py | 16 ++++++++++++++++ lib/spack/spack/modules/common.py | 13 +++---------- lib/spack/spack/package.py | 15 +++++++++++++++ lib/spack/spack/test/install.py | 8 +++++++- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index f4f39f2640..714dc0f31c 100755 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -463,6 +463,10 @@ def log(pkg): # Archive the environment used for the build install(pkg.env_path, pkg.install_env_path) + if os.path.exists(pkg.configure_args_path): + # Archive the args used for the build + install(pkg.configure_args_path, pkg.install_configure_args_path) + # Finally, archive files that are specific to each package with working_dir(pkg.stage.path): errors = six.StringIO() @@ -1013,6 +1017,18 @@ def build_process(): # Save the build environment in a file before building. dump_environment(pkg.env_path) + for attr in ('configure_args', 'cmake_args'): + try: + configure_args = getattr(pkg, attr)() + configure_args = ' '.join(configure_args) + + with open(pkg.configure_args_path, 'w') as args_file: + args_file.write(configure_args) + + break + except Exception: + pass + # cache debug settings debug_enabled = tty.is_debug() diff --git a/lib/spack/spack/modules/common.py b/lib/spack/spack/modules/common.py index d9407a1bf6..d6fb536e8f 100644 --- a/lib/spack/spack/modules/common.py +++ b/lib/spack/spack/modules/common.py @@ -623,16 +623,9 @@ def configure_options(self): msg = 'unknown, software installed outside of Spack' return msg - # This is quite simple right now, but contains information on how - # to call different build system classes. - for attr in ('configure_args', 'cmake_args'): - try: - configure_args = getattr(pkg, attr)() - return ' '.join(configure_args) - except (AttributeError, IOError, KeyError): - # The method doesn't exist in the current spec, - # or it's not usable - pass + if os.path.exists(pkg.install_configure_args_path): + with open(pkg.install_configure_args_path, 'r') as args_file: + return args_file.read() # Returning a false-like value makes the default templates skip # the configure option section diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index d123f58cdf..b7efc3989b 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -68,6 +68,9 @@ # Filename for the Spack build/install environment file. _spack_build_envfile = 'spack-build-env.txt' +# Filename for the Spack configure args file. +_spack_configure_argsfile = 'spack-configure-args.txt' + class InstallPhase(object): """Manages a single phase of the installation. @@ -896,6 +899,18 @@ def install_log_path(self): # Otherwise, return the current install log path name. return os.path.join(install_path, _spack_build_logfile) + @property + def configure_args_path(self): + """Return the configure args file path associated with staging.""" + return os.path.join(self.stage.path, _spack_configure_argsfile) + + @property + def install_configure_args_path(self): + """Return the configure args file path on successful installation.""" + install_path = spack.store.layout.metadata_path(self.spec) + + return os.path.join(install_path, _spack_configure_argsfile) + def _make_fetcher(self): # Construct a composite fetcher that always contains at least # one element (the root package). In case there are resources diff --git a/lib/spack/spack/test/install.py b/lib/spack/spack/test/install.py index f53a760f70..ff7f5a3355 100644 --- a/lib/spack/spack/test/install.py +++ b/lib/spack/spack/test/install.py @@ -15,7 +15,8 @@ import spack.repo import spack.store from spack.spec import Spec -from spack.package import _spack_build_envfile, _spack_build_logfile +from spack.package import (_spack_build_envfile, _spack_build_logfile, + _spack_configure_argsfile) def test_install_and_uninstall(install_mockery, mock_fetch, monkeypatch): @@ -410,6 +411,9 @@ def test_pkg_install_paths(install_mockery): env_path = os.path.join(spec.prefix, '.spack', _spack_build_envfile) assert spec.package.install_env_path == env_path + args_path = os.path.join(spec.prefix, '.spack', _spack_configure_argsfile) + assert spec.package.install_configure_args_path == args_path + # Backward compatibility checks log_dir = os.path.dirname(log_path) mkdirp(log_dir) @@ -448,6 +452,7 @@ def test_pkg_install_log(install_mockery): with working_dir(log_dir): touch(log_path) touch(spec.package.env_path) + touch(spec.package.configure_args_path) install_path = os.path.dirname(spec.package.install_log_path) mkdirp(install_path) @@ -456,6 +461,7 @@ def test_pkg_install_log(install_mockery): assert os.path.exists(spec.package.install_log_path) assert os.path.exists(spec.package.install_env_path) + assert os.path.exists(spec.package.install_configure_args_path) # Cleanup shutil.rmtree(log_dir)