From df4129d3951b2dd7fed2193f853270fd2d62df0d Mon Sep 17 00:00:00 2001 From: John Parent Date: Tue, 15 Mar 2022 15:11:56 -0400 Subject: [PATCH] Expand external find for Windows (#27588) * Incorporate new search location * Add external user option * proper doc string * Explicit commands in getting started * raise during chgrp on Win recover installer changes Notate admin privleges Windows phase install hooks Find external python and install ninja (#23496) Allow external find python to find windows python and spack install ninja Co-authored-by: Adam J. Stewart Co-authored-by: Betsy McPhail --- etc/spack/defaults/windows/config.yaml | 2 +- lib/spack/docs/getting_started.rst | 91 ++++++++----- lib/spack/llnl/util/filesystem.py | 3 + lib/spack/llnl/util/tty/log.py | 67 +++++++-- lib/spack/spack/build_systems/cmake.py | 23 +++- lib/spack/spack/cmd/make_installer.py | 68 ++++++---- lib/spack/spack/compilers/__init__.py | 1 + lib/spack/spack/compilers/msvc.py | 5 + lib/spack/spack/detection/common.py | 48 +++++++ lib/spack/spack/detection/path.py | 50 +++++-- lib/spack/spack/installer.py | 128 +++++++++--------- .../spack/operating_systems/windows_os.py | 4 + lib/spack/spack/schema/config.py | 4 + lib/spack/spack/stage.py | 32 +---- lib/spack/spack/test/bindist.py | 3 + lib/spack/spack/test/bootstrap.py | 3 + lib/spack/spack/test/build_distribution.py | 5 +- lib/spack/spack/test/build_systems.py | 23 +--- lib/spack/spack/test/cmd/analyze.py | 6 + lib/spack/spack/test/cmd/ci.py | 5 +- lib/spack/spack/test/cmd/clean.py | 4 +- lib/spack/spack/test/cmd/debug.py | 5 +- lib/spack/spack/test/cmd/dependencies.py | 8 +- lib/spack/spack/test/cmd/dependents.py | 7 +- lib/spack/spack/test/cmd/find.py | 22 +-- lib/spack/spack/test/cmd/gc.py | 6 +- lib/spack/spack/test/cmd/gpg.py | 7 +- lib/spack/spack/test/cmd/graph.py | 9 +- lib/spack/spack/test/cmd/install.py | 53 +------- lib/spack/spack/test/cmd/license.py | 6 +- lib/spack/spack/test/cmd/location.py | 19 +-- lib/spack/spack/test/cmd/mark.py | 10 +- lib/spack/spack/test/cmd/mirror.py | 13 +- lib/spack/spack/test/cmd/module.py | 12 +- lib/spack/spack/test/cmd/undevelop.py | 7 +- lib/spack/spack/test/cmd/uninstall.py | 10 +- lib/spack/spack/test/cmd/verify.py | 5 +- lib/spack/spack/test/cmd/versions.py | 12 +- lib/spack/spack/test/cmd/view.py | 17 +-- lib/spack/spack/test/concretize.py | 5 +- .../spack/test/concretize_preferences.py | 5 +- lib/spack/spack/test/database.py | 4 + lib/spack/spack/test/llnl/util/lock.py | 23 +++- lib/spack/spack/test/llnl/util/tty/log.py | 14 +- lib/spack/spack/test/make_executable.py | 5 +- lib/spack/spack/test/mirror.py | 16 +-- lib/spack/spack/test/sbang.py | 5 + lib/spack/spack/test/spec_dag.py | 3 + lib/spack/spack/test/svn_fetch.py | 12 +- lib/spack/spack/test/util/unparse/unparse.py | 3 + lib/spack/spack/util/path.py | 31 +++++ .../repos/builtin/packages/nasm/package.py | 6 +- .../repos/builtin/packages/ninja/package.py | 8 +- .../repos/builtin/packages/perl/package.py | 2 +- .../repos/builtin/packages/python/package.py | 23 +--- .../repos/builtin/packages/ruby/package.py | 24 ++-- 56 files changed, 535 insertions(+), 457 deletions(-) diff --git a/etc/spack/defaults/windows/config.yaml b/etc/spack/defaults/windows/config.yaml index 5d35246acb..956bc97c20 100644 --- a/etc/spack/defaults/windows/config.yaml +++ b/etc/spack/defaults/windows/config.yaml @@ -2,4 +2,4 @@ config: locks: false concretizer: original build_stage:: - - '~/.spack' + - '$spack/.staging' diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst index 8ba0a799a9..2d44af9a5d 100644 --- a/lib/spack/docs/getting_started.rst +++ b/lib/spack/docs/getting_started.rst @@ -1523,7 +1523,7 @@ linux distro. Spack On Windows ---------------- -Windows support for Spack is currently under development. While this work is still in an early stage, +Windows support for Spack is currently under development. While this work is still in an early stage, it is currently possible to set up Spack and perform a few operations on Windows. This section will guide you through the steps needed to install Spack and start running it on a fresh Windows machine. @@ -1533,13 +1533,16 @@ Step 1: Install prerequisites To use Spack on Windows, you will need the following packages: +Required: * Microsoft Visual Studio -* Intel Fortran (needed for some packages) * Python * Git -* Perl (needed for some packages) -* NASM (needed for some packages) -* CMake + +Optional: +* Intel Fortran (needed for some packages) + +Note: +Currently MSVC is the only compiler tested for C/C++ projects. Intel OneAPI provides Fortran support. """"""""""""""""""""""" Microsoft Visual Studio @@ -1587,21 +1590,6 @@ When given the option of adjusting your ``PATH``, choose the ``Git from the command line and also from 3rd-party software`` option. This will automatically update your ``PATH`` variable to include the ``git`` command. -"""" -NASM -"""" - -The Netwide Assembler (NASM) is a x86-64 assembler that some Windows packages -will use to create binaries and can be found at https://www.nasm.us. - -""""" -CMake -""""" - -While the CMake provided by your Microsoft Visual Studio installation should -suffice for most packages, we still recommend downloading and installing the -most recent version of the software at https://cmake.org/download/ in case -of version restrictions. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Step 2: Install and setup Spack @@ -1611,23 +1599,40 @@ We are now ready to get the Spack environment set up on our machine. We begin by using Git to clone the Spack repo, hosted at https://github.com/spack/spack.git into a desired directory, for our purposes today, called ``spack_install``. -The files and scripts used for Windows installation are on the -``features/windows-support`` branch; ``cd`` into the repo and use -``git checkout`` to switch to it. +Presently, Windows operations are supported by Spack soley through the +features/windows-support branch on the upstream Spack repository, +located at the above url. +In order to install Spack with Windows support, run the following one liner +in a Windows CMD prompt. +.. code-block:: console + + git clone https://github.com/spack/spack.git -b features/windows-support win_spack + +or if working from a previous clone of Spack, simply checkout the Windows support feature branch +with + +.. code-block:: console + + git checkout -b features/windows-support --track /features/windows-support + +Note: +If you chose to install spack into a directory on Windows that is set up to require Administrative +Privleges (either by default like `C:\Program Files`, or by administrative settings), or have administrative +restrictions on a directory spack install files to such as `C:\Users\`, Spack will require elevated privleges +to run. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Step 3: Run and configure Spack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To use Spack, run ``bin\spack_cmd.bat`` (you may need to Run as Administrator) -from the spack source tree root. This will provide a Windows command prompt -with an environment properly set up with Spack and its prerequisites. -If you receive a warning message that Python is not in your ``PATH`` -(which may happen if you installed Python from the website and not -the Windows Store), add the location of the Python executable to your -``PATH`` now. +To use Spack, run ``bin\spack_cmd.bat`` (you may need to Run as Administrator) from the top-level spack +directory. This will provide a Windows command prompt with an environment properly set up with Spack +and its prerequisites. If you receive a warning message that Python is not in your ``PATH`` +(which may happen if you installed Python from the website and not the Windows Store) add the location +of the Python executable to your ``PATH`` now. You can permanently add Python to your ``PATH`` variable +by using the ``Edit the system environment variables`` utility in Windows Control Panel. To configure Spack, first run the following command inside the Spack console: @@ -1635,7 +1640,7 @@ To configure Spack, first run the following command inside the Spack console: spack compiler find -This creates a ``.spack`` directory in our home directory, along with a ``windows`` subdirectory +This creates a ``.staging`` directory in our Spack prefix, along with a ``windows`` subdirectory containing a ``compilers.yaml`` file. On a fresh Windows install with the above packages installed, this command should only detect Microsoft Visual Studio and the Intel Fortran compiler will be integrated within the first version of MSVC present in the ``compilers.yaml`` @@ -1649,8 +1654,11 @@ as this specifies the directory that will temporarily hold the source code for t be installed. This path name must be sufficiently short for compliance with cmd, otherwise you will see build errors during installation (particularly with CMake) tied to long path names. -For the ``packages.yaml`` file, there are two options. The first -and easiest choice is to use Spack to find installation on your system. In +To allow Spack use of external tools and dependencies already on your system, the +external pieces of software must be described in the ``packages.yaml`` file. +There are two methods to populate this file: + +The first and easiest choice is to use Spack to find installation on your system. In the Spack terminal, run the following commands: .. code-block:: console @@ -1660,10 +1668,10 @@ the Spack terminal, run the following commands: The ``spack external find `` will find executables on your system with the same name given. The command will store the items found in -``packages.yaml`` in the ``.spack\`` directory. +``packages.yaml`` in the ``.staging\`` directory. Assuming that the command found CMake and Ninja executables in the previous -step, continue to Step 4. If no executables were found, we need to manually direct spack towards the CMake +step, continue to Step 4. If no executables were found, we may need to manually direct spack towards the CMake and Ninja installations we set up with Visual Studio. Therefore, your ``packages.yaml`` file will look something like this, with possibly slight variants in the paths to CMake and Ninja: @@ -1698,6 +1706,8 @@ Spack console via: spack install cpuinfo +If in the previous step, you did not have CMake or Ninja installed, running the command above should boostrap both packages + """"""""""""""""""""""""""" Windows Compatible Packages """"""""""""""""""""""""""" @@ -1712,6 +1722,15 @@ packages known to work on Windows: * netlib-lapack (requires Intel Fortran) * openssl * zlib +* perl +* ruby +* python +* cmake +* ninja +* nasm +* clingo + +Note: this is not a comprehensive list ^^^^^^^^^^^^^^ For developers @@ -1721,3 +1740,5 @@ The intent is to provide a Windows installer that will automatically set up Python, Git, and Spack, instead of requiring the user to do so manually. Instructions for creating the installer are at https://github.com/spack/spack/blob/features/windows-support/lib/spack/spack/cmd/installer/README.md. + +Alternatively a pre-built copy of the Windows installer is available as an artifact of Spack's Windows CI diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py index d18a06461f..2a67ca698a 100644 --- a/lib/spack/llnl/util/filesystem.py +++ b/lib/spack/llnl/util/filesystem.py @@ -321,6 +321,9 @@ def group_ids(uid=None): def chgrp(path, group): """Implement the bash chgrp function on a single path""" + if is_windows: + raise OSError("Function 'chgrp' is not supported on Windows") + if isinstance(group, six.string_types): gid = grp.getgrnam(group).gr_gid else: diff --git a/lib/spack/llnl/util/tty/log.py b/lib/spack/llnl/util/tty/log.py index 2551a751f4..c16982241e 100644 --- a/lib/spack/llnl/util/tty/log.py +++ b/lib/spack/llnl/util/tty/log.py @@ -403,7 +403,52 @@ def replace_environment(env): os.environ[name] = val -class log_output(object): +def log_output(*args, **kwargs): + """Context manager that logs its output to a file. + + In the simplest case, the usage looks like this:: + + with log_output('logfile.txt'): + # do things ... output will be logged + + Any output from the with block will be redirected to ``logfile.txt``. + If you also want the output to be echoed to ``stdout``, use the + ``echo`` parameter:: + + with log_output('logfile.txt', echo=True): + # do things ... output will be logged and printed out + + And, if you just want to echo *some* stuff from the parent, use + ``force_echo``:: + + with log_output('logfile.txt', echo=False) as logger: + # do things ... output will be logged + + with logger.force_echo(): + # things here will be echoed *and* logged + + Under the hood, we spawn a daemon and set up a pipe between this + process and the daemon. The daemon writes our output to both the + file and to stdout (if echoing). The parent process can communicate + with the daemon to tell it when and when not to echo; this is what + force_echo does. You can also enable/disable echoing by typing 'v'. + + We try to use OS-level file descriptors to do the redirection, but if + stdout or stderr has been set to some Python-level file object, we + use Python-level redirection instead. This allows the redirection to + work within test frameworks like nose and pytest. + + + This method is actually a factory serving a per platform + (nix vs windows) log_output class + """ + if sys.platform == 'win32': + return winlog(*args, **kwargs) + else: + return nixlog(*args, **kwargs) + + +class nixlog(object): """Context manager that logs its output to a file. In the simplest case, the usage looks like this:: @@ -747,12 +792,13 @@ def close(self): os.close(self.saved_stream) -class winlog: - def __init__(self, logfile, echo=False, debug=0, env=None): +class winlog(object): + def __init__(self, file_like=None, echo=False, debug=0, buffer=False, + env=None, filter_fn=None): self.env = env self.debug = debug self.echo = echo - self.logfile = logfile + self.logfile = file_like self.stdout = StreamWrapper('stdout') self.stderr = StreamWrapper('stderr') self._active = False @@ -807,6 +853,7 @@ def background_reader(reader, echo_writer, _kill): self._thread = Thread(target=background_reader, args=(self.reader, self.echo_writer, self._kill)) self._thread.start() + return self def __exit__(self, exc_type, exc_val, exc_tb): if self._ioflag: @@ -831,18 +878,10 @@ def force_echo(self): if not self._active: raise RuntimeError( "Can't call force_echo() outside log_output region!") - - # This uses the xon/xoff to highlight regions to be echoed in the - # output. We use these control characters rather than, say, a - # separate pipe, because they're in-band and assured to appear - # exactly before and after the text we want to echo. - sys.stdout.write(xon) - sys.stdout.flush() try: - yield + yield self finally: - sys.stdout.write(xoff) - sys.stdout.flush() + pass def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo, diff --git a/lib/spack/spack/build_systems/cmake.py b/lib/spack/spack/build_systems/cmake.py index 591d73a5c4..7a53adc250 100644 --- a/lib/spack/spack/build_systems/cmake.py +++ b/lib/spack/spack/build_systems/cmake.py @@ -9,7 +9,7 @@ import platform import re import sys -from typing import List # novm +from typing import List import six @@ -18,7 +18,7 @@ import spack.build_environment from spack.directives import conflicts, depends_on, variant -from spack.package import PackageBase, run_after +from spack.package import InstallError, PackageBase, run_after # Regex to extract the primary generator from the CMake generator # string. @@ -146,10 +146,19 @@ def _std_args(pkg): """Computes the standard cmake arguments for a generic package""" try: - if not pkg.generator: - raise AttributeError + generator = pkg.generator except AttributeError: - pkg.generator = CMakePackage.generator + generator = CMakePackage.generator + + # Make sure a valid generator was chosen + valid_primary_generators = ['Unix Makefiles', 'Ninja'] + primary_generator = _extract_primary_generator(generator) + if primary_generator not in valid_primary_generators: + msg = "Invalid CMake generator: '{0}'\n".format(generator) + msg += "CMakePackage currently supports the following " + msg += "primary generators: '{0}'".\ + format("', '".join(valid_primary_generators)) + raise InstallError(msg) try: build_type = pkg.spec.variants['build_type'].value @@ -163,7 +172,7 @@ def _std_args(pkg): define = CMakePackage.define args = [ - '-G', pkg.generator, + '-G', generator, define('CMAKE_INSTALL_PREFIX', pkg.prefix.replace('\\', '/')), define('CMAKE_BUILD_TYPE', build_type), ] @@ -172,7 +181,7 @@ def _std_args(pkg): if pkg.spec.satisfies('^cmake@3.9:'): args.append(define('CMAKE_INTERPROCEDURAL_OPTIMIZATION', ipo)) - if pkg.generator == 'Unix Makefiles': + if generator == 'Unix Makefiles': args.append(define('CMAKE_VERBOSE_MAKEFILE', True)) if platform.mac_ver()[0]: diff --git a/lib/spack/spack/cmd/make_installer.py b/lib/spack/spack/cmd/make_installer.py index 6ddb049b8d..71d0aa3ada 100644 --- a/lib/spack/spack/cmd/make_installer.py +++ b/lib/spack/spack/cmd/make_installer.py @@ -4,7 +4,6 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os import posixpath -import subprocess import sys import spack.paths @@ -38,10 +37,10 @@ def line_to_rtf(str): def setup_parser(subparser): spack_source_group = subparser.add_mutually_exclusive_group(required=True) spack_source_group.add_argument( - '-v', '--spack_version', default="", + '-v', '--spack-version', default="", help='download given spack version e.g. 0.16.0') spack_source_group.add_argument( - '-s', '--spack_source', default="", + '-s', '--spack-source', default="", help='full path to spack source') subparser.add_argument( @@ -97,41 +96,50 @@ def make_installer(parser, args): "share/spack/logo/favicon.ico") try: - subprocess.check_call( - ('"%s" -S "%s" -B "%s" -DSPACK_VERSION=%s ' - '-DSPACK_SOURCE="%s" -DSPACK_LICENSE="%s" ' - '-DSPACK_LOGO="%s" -DSPACK_GIT_VERBOSITY="%s"') - % (cmake_path, source_dir, output_dir, spack_version, spack_source, - spack_license, spack_logo, git_verbosity), - shell=True) - except subprocess.CalledProcessError: + spack.util.executable.Executable(cmake_path)( + '-S', source_dir, '-B', output_dir, + '-DSPACK_VERSION=%s' % spack_version, + '-DSPACK_SOURCE=%s' % spack_source, + '-DSPACK_LICENSE=%s' % spack_license, + '-DSPACK_LOGO=%s' % spack_logo, + '-DSPACK_GIT_VERBOSITY=%s' % git_verbosity + ) + except spack.util.executable.ProcessError: print("Failed to generate installer") - return subprocess.CalledProcessError.returncode + return spack.util.executable.ProcessError.returncode try: - subprocess.check_call( - '"%s" --config "%s/CPackConfig.cmake" -B "%s/"' - % (cpack_path, output_dir, output_dir), - shell=True) - except subprocess.CalledProcessError: + spack.util.executable.Executable(cpack_path)( + "--config", + "%s/CPackConfig.cmake" % output_dir, + "-B", + "%s/" % output_dir) + except spack.util.executable.ProcessError: print("Failed to generate installer") - return subprocess.CalledProcessError.returncode + return spack.util.executable.ProcessError.returncode try: - subprocess.check_call( - '"%s/bin/candle.exe" -ext WixBalExtension "%s/bundle.wxs"' - ' -out "%s/bundle.wixobj"' - % (os.environ.get('WIX'), output_dir, output_dir), shell=True) - except subprocess.CalledProcessError: + spack.util.executable.Executable(os.environ.get('WIX') + '/bin/candle.exe')( + '-ext', + 'WixBalExtension', + '%s/bundle.wxs' % output_dir, + '-out', + '%s/bundle.wixobj' % output_dir + ) + except spack.util.executable.ProcessError: print("Failed to generate installer chain") - return subprocess.CalledProcessError.returncode + return spack.util.executable.ProcessError.returncode try: - subprocess.check_call( - '"%s/bin/light.exe" -sw1134 -ext WixBalExtension "%s/bundle.wixobj"' - ' -out "%s/Spack.exe"' - % (os.environ.get('WIX'), output_dir, output_dir), shell=True) - except subprocess.CalledProcessError: + spack.util.executable.Executable(os.environ.get('WIX') + "/bin/light.exe")( + "-sw1134", + "-ext", + "WixBalExtension", + "%s/bundle.wixobj" % output_dir, + '-out', + '%s/Spack.exe' % output_dir + ) + except spack.util.executable.ProcessError: print("Failed to generate installer chain") - return subprocess.CalledProcessError.returncode + return spack.util.executable.ProcessError.returncode print("Successfully generated Spack.exe in %s" % (output_dir)) else: print('The make-installer command is currently only supported on Windows.') diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py index 8e9917488c..5aad6b2b98 100644 --- a/lib/spack/spack/compilers/__init__.py +++ b/lib/spack/spack/compilers/__init__.py @@ -211,6 +211,7 @@ def find_compilers(path_hints=None): for o in all_os_classes(): search_paths = getattr(o, 'compiler_search_paths', default_paths) arguments.extend(arguments_to_detect_version_fn(o, search_paths)) + # Here we map the function arguments to the corresponding calls tp = multiprocessing.pool.ThreadPool() try: diff --git a/lib/spack/spack/compilers/msvc.py b/lib/spack/spack/compilers/msvc.py index f51583caf4..32a9620c3d 100644 --- a/lib/spack/spack/compilers/msvc.py +++ b/lib/spack/spack/compilers/msvc.py @@ -51,6 +51,11 @@ class Msvc(Compiler): fc_names = ['ifx.exe'] # type: List[str] # Named wrapper links within build_env_path + # Due to the challenges of supporting compiler wrappers + # in Windows, we leave these blank, and dynamically compute + # based on proper versions of MSVC from there + # pending acceptance of #28117 for full support using + # compiler wrappers link_paths = {'cc': '', 'cxx': '', 'f77': '', diff --git a/lib/spack/spack/detection/common.py b/lib/spack/spack/detection/common.py index f3ebd7aa11..e24a0561da 100644 --- a/lib/spack/spack/detection/common.py +++ b/lib/spack/spack/detection/common.py @@ -14,8 +14,10 @@ detection mechanisms. """ import collections +import itertools import os import os.path +import re import six @@ -175,3 +177,49 @@ def update_configuration(detected_packages, scope=None, buildable=True): spack.config.set('packages', pkgs_cfg, scope=scope) return all_new_specs + + +def find_win32_additional_install_paths(): + """Not all programs on Windows live on the PATH + Return a list of other potential install locations. + """ + windows_search_ext = [] + cuda_re = r'CUDA_PATH[a-zA-Z1-9_]*' + # The list below should be expanded with other + # common Windows install locations as neccesary + path_ext_keys = ['I_MPI_ONEAPI_ROOT', + 'MSMPI_BIN', + 'MLAB_ROOT', + 'NUGET_PACKAGES'] + user = os.environ["USERPROFILE"] + add_path = lambda key: re.search(cuda_re, key) or key in path_ext_keys + windows_search_ext.extend([os.environ[key] for key + in os.environ.keys() if + add_path(key)]) + # note windows paths are fine here as this method should only ever be invoked + # to interact with Windows + # Add search path for default Chocolatey (https://github.com/chocolatey/choco) + # install directory + windows_search_ext.append("C:\\ProgramData\\chocolatey\\bin") + # Add search path for NuGet package manager default install location + windows_search_ext.append(os.path.join(user, ".nuget", "packages")) + windows_search_ext.extend( + spack.config.get("config:additional_external_search_paths", default=[]) + ) + + return windows_search_ext + + +def compute_windows_program_path_for_package(pkg): + """Given a package, attempt to compute its Windows + program files location, return list of best guesses + + Args: + pkg (spack.package.Package): package for which + Program Files location is to be computed + """ + program_files = 'C:\\Program Files {}\\{}' + + return[program_files.format(arch, name) for + arch, name in itertools.product(("", "(x86)"), + (pkg.name, pkg.name.capitalize()))] diff --git a/lib/spack/spack/detection/path.py b/lib/spack/spack/detection/path.py index ee98e23841..835a8a0c5a 100644 --- a/lib/spack/spack/detection/path.py +++ b/lib/spack/spack/detection/path.py @@ -6,6 +6,7 @@ and running executables. """ import collections +from distutils.spawn import find_executable import os import os.path import re @@ -21,11 +22,40 @@ from .common import ( DetectedPackage, _convert_to_iterable, + compute_windows_program_path_for_package, executable_prefix, + find_win32_additional_install_paths, is_executable, ) +def find_executables(path_hints): + """Get the paths of all executables available from provided hints + + For convenience, this is constructed as a dictionary where the keys are + the executable paths and the values are the names of the executables + (i.e. the basename of the executable path). + + There may be multiple paths with the same basename. In this case it is + assumed there are two different instances of the executable. + + Args: + path_hints (list): list of paths to be searched. If None the list will be + constructed based on the PATH environment variable. + """ + search_paths = llnl.util.filesystem.search_paths_for_executables(*path_hints) + + path_to_exe = {} + # Reverse order of search directories so that an exe in the first PATH + # entry overrides later entries + for search_path in reversed(search_paths): + for exe in os.listdir(search_path): + exe_path = os.path.join(search_path, exe) + if is_executable(exe_path): + path_to_exe[exe_path] = exe + return path_to_exe + + def executables_in_path(path_hints=None): """Get the paths of all executables available from the current PATH. @@ -56,18 +86,8 @@ def executables_in_path(path_hints=None): "CMake", "Ninja") for path in msvc_paths] path_hints = msvc_ninja_paths + path_hints - - search_paths = llnl.util.filesystem.search_paths_for_executables(*path_hints) - - path_to_exe = {} - # Reverse order of search directories so that an exe in the first PATH - # entry overrides later entries - for search_path in reversed(search_paths): - for exe in os.listdir(search_path): - exe_path = os.path.join(search_path, exe) - if is_executable(exe_path): - path_to_exe[exe_path] = exe - return path_to_exe + path_hints.extend(find_win32_additional_install_paths()) + return find_executables(path_hints) def _group_by_prefix(paths): @@ -95,6 +115,12 @@ def by_executable(packages_to_check, path_hints=None): exe = exe.replace('$', r'\.exe$') exe_pattern_to_pkgs[exe].append(pkg) + path_to_exe_name.update( + find_executables( + compute_windows_program_path_for_package(pkg) + ) + ) + pkg_to_found_exes = collections.defaultdict(set) for exe_pattern, pkgs in exe_pattern_to_pkgs.items(): compiled_re = re.compile(exe_pattern) diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index 35403a6cc1..c6da212340 100644 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -165,12 +165,13 @@ def _do_fake_install(pkg): library = 'lib' + library dso_suffix = '.dylib' if sys.platform == 'darwin' else '.so' - chmod = which('chmod') # Install fake command fs.mkdirp(pkg.prefix.bin) fs.touch(os.path.join(pkg.prefix.bin, command)) - chmod('+x', os.path.join(pkg.prefix.bin, command)) + if sys.platform != 'win32': + chmod = which('chmod') + chmod('+x', os.path.join(pkg.prefix.bin, command)) # Install fake header file fs.mkdirp(pkg.prefix.include) @@ -1936,75 +1937,74 @@ def _real_install(self): # Spawn a daemon that reads from a pipe and redirects # everything to log_path, and provide the phase for logging - if sys.platform != 'win32': - for i, (phase_name, phase_attr) in enumerate(zip( - pkg.phases, pkg._InstallPhase_phases)): + # if sys.platform != 'win32': + for i, (phase_name, phase_attr) in enumerate(zip( + pkg.phases, pkg._InstallPhase_phases)): - # Keep a log file for each phase - log_dir = os.path.dirname(pkg.log_path) - log_file = "spack-build-%02d-%s-out.txt" % ( - i + 1, phase_name.lower() + # Keep a log file for each phase + log_dir = os.path.dirname(pkg.log_path) + log_file = "spack-build-%02d-%s-out.txt" % ( + i + 1, phase_name.lower() + ) + log_file = os.path.join(log_dir, log_file) + + try: + # DEBUGGING TIP - to debug this section, insert an IPython + # embed here, and run the sections below without log capture + log_contextmanager = log_output( + log_file, + self.echo, + True, + env=self.unmodified_env, + filter_fn=self.filter_fn ) - log_file = os.path.join(log_dir, log_file) - - try: - # DEBUGGING TIP - to debug this section, insert an IPython - # embed here, and run the sections below without log capture - log_contextmanager = log_output( - log_file, - self.echo, - True, - env=self.unmodified_env, - filter_fn=self.filter_fn - ) - - with log_contextmanager as logger: - with logger.force_echo(): - inner_debug_level = tty.debug_level() - tty.set_debug(debug_level) - tty.msg( - "{0} Executing phase: '{1}'" .format( - self.pre, - phase_name - ) + with log_contextmanager as logger: + with logger.force_echo(): + inner_debug_level = tty.debug_level() + tty.set_debug(debug_level) + tty.msg( + "{0} Executing phase: '{1}'" .format( + self.pre, + phase_name ) - tty.set_debug(inner_debug_level) - - # Redirect stdout and stderr to daemon pipe - phase = getattr(pkg, phase_attr) - self.timer.phase(phase_name) - - # Catch any errors to report to logging - phase(pkg.spec, pkg.prefix) - spack.hooks.on_phase_success(pkg, phase_name, log_file) - - except BaseException: - combine_phase_logs(pkg.phase_log_files, pkg.log_path) - spack.hooks.on_phase_error(pkg, phase_name, log_file) - - # phase error indicates install error - spack.hooks.on_install_failure(pkg.spec) - raise - - # We assume loggers share echo True/False - self.echo = logger.echo - else: - with winlog(pkg.log_path, True, True, - env=self.unmodified_env) as logger: - - for phase_name, phase_attr in zip( - pkg.phases, pkg._InstallPhase_phases): - - # with logger.force_echo(): - # inner_debug_level = tty.debug_level() - # tty.set_debug(debug_level) - # tty.msg("{0} Executing phase: '{1}'" - # .format(pre, phase_name)) - # tty.set_debug(inner_debug_level) + ) + tty.set_debug(inner_debug_level) # Redirect stdout and stderr to daemon pipe phase = getattr(pkg, phase_attr) + self.timer.phase(phase_name) + + # Catch any errors to report to logging phase(pkg.spec, pkg.prefix) + spack.hooks.on_phase_success(pkg, phase_name, log_file) + + except BaseException: + combine_phase_logs(pkg.phase_log_files, pkg.log_path) + spack.hooks.on_phase_error(pkg, phase_name, log_file) + + # phase error indicates install error + spack.hooks.on_install_failure(pkg.spec) + raise + + # We assume loggers share echo True/False + self.echo = logger.echo + # if True: + # with winlog(pkg.log_path, True, True, + # env=self.unmodified_env) as logger: + + # for phase_name, phase_attr in zip( + # pkg.phases, pkg._InstallPhase_phases): + + # # with logger.force_echo(): + # # inner_debug_level = tty.debug_level() + # # tty.set_debug(debug_level) + # # tty.msg("{0} Executing phase: '{1}'" + # # .format(pre, phase_name)) + # # tty.set_debug(inner_debug_level) + + # # Redirect stdout and stderr to daemon pipe + # phase = getattr(pkg, phase_attr) + # phase(pkg.spec, pkg.prefix) if sys.platform != 'win32': # After log, we can get all output/error files from the package stage diff --git a/lib/spack/spack/operating_systems/windows_os.py b/lib/spack/spack/operating_systems/windows_os.py index 06113a4434..b32768f709 100755 --- a/lib/spack/spack/operating_systems/windows_os.py +++ b/lib/spack/spack/operating_systems/windows_os.py @@ -5,9 +5,11 @@ import glob import os +import platform import subprocess import sys +from spack.error import SpackError from spack.version import Version from ._operating_system import OperatingSystem @@ -65,6 +67,8 @@ class WindowsOs(OperatingSystem): compiler_search_paths = comp_search_paths def __init__(self): + if Version(platform.release()) < Version('10'): + raise SpackError("Spack is not supported on Windows versions older than 10") super(WindowsOs, self).__init__('Windows10', '10') def __str__(self): diff --git a/lib/spack/spack/schema/config.py b/lib/spack/spack/schema/config.py index 99eecd67e6..06dadc802c 100644 --- a/lib/spack/spack/schema/config.py +++ b/lib/spack/spack/schema/config.py @@ -103,6 +103,10 @@ 'type': 'string', 'enum': ['urllib', 'curl'] }, + 'additional_external_search_paths': { + 'type': 'array', + 'items': {'type': 'string'} + } }, }, } diff --git a/lib/spack/spack/stage.py b/lib/spack/spack/stage.py index 83066abe9f..5a587ccee7 100644 --- a/lib/spack/spack/stage.py +++ b/lib/spack/spack/stage.py @@ -14,7 +14,6 @@ import stat import sys import tempfile -from sys import platform as _platform from typing import Dict # novm from six import iteritems, string_types @@ -23,6 +22,7 @@ import llnl.util.tty as tty from llnl.util.filesystem import ( can_access, + getuid, install, install_tree, mkdirp, @@ -42,10 +42,6 @@ import spack.util.url as url_util from spack.util.crypto import bit_length, prefix_bits -if _platform == "win32": - import win32api - import win32security - # The well-known stage source subdirectory name. _source_path_subdir = 'spack-src' @@ -61,10 +57,7 @@ def create_stage_root(path): err_msg = 'Cannot create stage root {0}: Access to {1} is denied' - if _platform != "win32": - user_uid = os.getuid() # type: ignore[attr-defined] - else: - user_uid = win32api.GetUserName() + user_uid = getuid() # Obtain lists of ancestor and descendant paths of the $user node, if any. group_paths, user_node, user_paths = partition_path(path, @@ -97,26 +90,7 @@ def create_stage_root(path): for p in user_paths: # Ensure access controls of subdirs from `$user` on down are # restricted to the user. - if not os.path.exists(p): - mkdirp(p, mode=stat.S_IRWXU) - - p_stat = os.stat(p) - if p_stat.st_mode & stat.S_IRWXU != stat.S_IRWXU: - tty.error("Expected {0} to support mode {1}, but it is {2}" - .format(p, stat.S_IRWXU, p_stat.st_mode)) - - raise OSError(errno.EACCES, err_msg.format(path, p)) - else: - p_stat = os.stat(p) - - if _platform != "win32": - owner_uid = p_stat.st_uid - else: - sid = win32security.GetFileSecurity( - p, win32security.OWNER_SECURITY_INFORMATION) \ - .GetSecurityDescriptorOwner() - owner_uid = win32security.LookupAccountSid(None, sid)[0] - + owner_uid = sup.get_owner_uid(p) if user_uid != owner_uid: tty.warn("Expected user {0} to own {1}, but it is owned by {2}" .format(user_uid, p, owner_uid)) diff --git a/lib/spack/spack/test/bindist.py b/lib/spack/spack/test/bindist.py index 858871d495..c3c7e0e7b2 100644 --- a/lib/spack/spack/test/bindist.py +++ b/lib/spack/spack/test/bindist.py @@ -27,6 +27,9 @@ from spack.paths import test_path from spack.spec import Spec +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + mirror_cmd = spack.main.SpackCommand('mirror') install_cmd = spack.main.SpackCommand('install') uninstall_cmd = spack.main.SpackCommand('uninstall') diff --git a/lib/spack/spack/test/bootstrap.py b/lib/spack/spack/test/bootstrap.py index f5f6026a5c..b0825a521c 100644 --- a/lib/spack/spack/test/bootstrap.py +++ b/lib/spack/spack/test/bootstrap.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os +import sys import pytest @@ -150,6 +151,8 @@ def test_nested_use_of_context_manager(mutable_config): assert spack.config.config == user_config +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") @pytest.mark.parametrize('expected_missing', [False, True]) def test_status_function_find_files( mutable_config, mock_executable, tmpdir, monkeypatch, expected_missing diff --git a/lib/spack/spack/test/build_distribution.py b/lib/spack/spack/test/build_distribution.py index aeb1a9a878..c2008ffa63 100644 --- a/lib/spack/spack/test/build_distribution.py +++ b/lib/spack/spack/test/build_distribution.py @@ -14,9 +14,10 @@ install = spack.main.SpackCommand('install') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") def test_build_tarball_overwrite( install_mockery, mock_fetch, monkeypatch, tmpdir): diff --git a/lib/spack/spack/test/build_systems.py b/lib/spack/spack/test/build_systems.py index 0ec2854337..337b7c21a1 100644 --- a/lib/spack/spack/test/build_systems.py +++ b/lib/spack/spack/test/build_systems.py @@ -21,9 +21,10 @@ DATA_PATH = os.path.join(spack.paths.test_path, 'data') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.parametrize( 'directory', glob.iglob(os.path.join(DATA_PATH, 'make', 'affirmative', '*')) @@ -43,8 +44,6 @@ def test_affirmative_make_check(directory, config, mock_packages, working_env): pkg._if_make_target_execute('check') -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.parametrize( 'directory', glob.iglob(os.path.join(DATA_PATH, 'make', 'negative', '*')) @@ -111,8 +110,6 @@ def test_negative_ninja_check(directory, config, mock_packages, working_env): pkg._if_ninja_target_execute('check') -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") def test_cmake_std_args(config, mock_packages): # Call the function on a CMakePackage instance s = Spec('cmake-client') @@ -127,16 +124,12 @@ def test_cmake_std_args(config, mock_packages): assert get_std_cmake_args(pkg) -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") def test_cmake_bad_generator(config, mock_packages): with pytest.raises(serr.SpackError): s = Spec('cmake-client generator="Yellow Sticky Note"') s.concretize() -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") def test_cmake_secondary_generator(config, mock_packages): s = Spec('cmake-client') s.concretize() @@ -327,8 +320,6 @@ def test_broken_external_gnuconfig(self, mutable_database, tmpdir): e.install_all() -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.usefixtures('config', 'mock_packages') class TestCMakePackage(object): @@ -370,8 +361,6 @@ def test_define_from_variant(self): pkg.define_from_variant('NONEXISTENT') -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.usefixtures('config', 'mock_packages') class TestGNUMirrorPackage(object): @@ -395,8 +384,6 @@ def test_define(self): 'make/make-4.2.1.tar.gz' -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.usefixtures('config', 'mock_packages') class TestSourceforgePackage(object): @@ -420,8 +407,6 @@ def test_define(self): 'tcl/tcl8.6.5-src.tar.gz' -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.usefixtures('config', 'mock_packages') class TestSourcewarePackage(object): @@ -445,8 +430,6 @@ def test_define(self): 'bzip2/bzip2-1.0.8.tar.gz' -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.usefixtures('config', 'mock_packages') class TestXorgPackage(object): diff --git a/lib/spack/spack/test/cmd/analyze.py b/lib/spack/spack/test/cmd/analyze.py index f662a48948..5084113b3c 100644 --- a/lib/spack/spack/test/cmd/analyze.py +++ b/lib/spack/spack/test/cmd/analyze.py @@ -60,6 +60,8 @@ class MyAnalyzer(AnalyzerBase): MyAnalyzer(spec) +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_analyze_output(tmpdir, mock_fetch, install_mockery_mutable_config): """ Test that an analyzer errors if requested name does not exist. @@ -152,6 +154,8 @@ def test_environment_analyzer(tmpdir, mock_fetch, install_mockery_mutable_config assert not result['environment_variables'] +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_list_analyzers(): """ test that listing analyzers shows all the possible analyzers. @@ -167,6 +171,8 @@ def test_list_analyzers(): assert analyzer_type in out +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_configargs_analyzer(tmpdir, mock_fetch, install_mockery_mutable_config): """ test the config args analyzer. diff --git a/lib/spack/spack/test/cmd/ci.py b/lib/spack/spack/test/cmd/ci.py index 7fc032db64..a668e69528 100644 --- a/lib/spack/spack/test/cmd/ci.py +++ b/lib/spack/spack/test/cmd/ci.py @@ -40,8 +40,9 @@ uninstall_cmd = spack.main.SpackCommand('uninstall') buildcache_cmd = spack.main.SpackCommand('buildcache') - -pytestmark = pytest.mark.maybeslow +pytestmark = [pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows"), + pytest.mark.maybeslow] @pytest.fixture() diff --git a/lib/spack/spack/test/cmd/clean.py b/lib/spack/spack/test/cmd/clean.py index 0dfca81c66..fb0bb87ed0 100644 --- a/lib/spack/spack/test/cmd/clean.py +++ b/lib/spack/spack/test/cmd/clean.py @@ -14,6 +14,9 @@ clean = spack.main.SpackCommand('clean') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + @pytest.fixture() def mock_calls_for_clean(monkeypatch): @@ -57,7 +60,6 @@ def __call__(self, *args, **kwargs): ('-a', all_effects), ('', []), ]) -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_function_calls(command_line, effects, mock_calls_for_clean): # Call the command with the supplied command line diff --git a/lib/spack/spack/test/cmd/debug.py b/lib/spack/spack/test/cmd/debug.py index 1666a8b277..ef00e28f48 100644 --- a/lib/spack/spack/test/cmd/debug.py +++ b/lib/spack/spack/test/cmd/debug.py @@ -17,8 +17,10 @@ debug = SpackCommand('debug') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_create_db_tarball(tmpdir, database): with tmpdir.as_cwd(): @@ -48,7 +50,6 @@ def test_create_db_tarball(tmpdir, database): assert spec_suffix in contents -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_report(): out = debug('report') host_platform = spack.platforms.host() diff --git a/lib/spack/spack/test/cmd/dependencies.py b/lib/spack/spack/test/cmd/dependencies.py index 7c76f031d2..50ce7b8dde 100644 --- a/lib/spack/spack/test/cmd/dependencies.py +++ b/lib/spack/spack/test/cmd/dependencies.py @@ -20,8 +20,10 @@ ] mpi_deps = ['fake'] +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_direct_dependencies(mock_packages): out = dependencies('mpileaks') actual = set(re.split(r'\s+', out.strip())) @@ -29,7 +31,6 @@ def test_direct_dependencies(mock_packages): assert expected == actual -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_transitive_dependencies(mock_packages): out = dependencies('--transitive', 'mpileaks') actual = set(re.split(r'\s+', out.strip())) @@ -38,7 +39,6 @@ def test_transitive_dependencies(mock_packages): assert expected == actual -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_transitive_dependencies_with_deptypes(mock_packages): out = dependencies('--transitive', '--deptype=link,run', 'dtbuild1') deps = set(re.split(r'\s+', out.strip())) @@ -53,7 +53,6 @@ def test_transitive_dependencies_with_deptypes(mock_packages): assert set(['dtlink2']) == deps -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_direct_installed_dependencies(mock_packages, database): with color_when(False): @@ -71,7 +70,6 @@ def test_direct_installed_dependencies(mock_packages, database): assert expected == hashes -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_transitive_installed_dependencies(mock_packages, database): with color_when(False): diff --git a/lib/spack/spack/test/cmd/dependents.py b/lib/spack/spack/test/cmd/dependents.py index 6cee5a22a5..d9b6d8a2f6 100644 --- a/lib/spack/spack/test/cmd/dependents.py +++ b/lib/spack/spack/test/cmd/dependents.py @@ -15,8 +15,10 @@ dependents = SpackCommand('dependents') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_immediate_dependents(mock_packages): out = dependents('libelf') actual = set(re.split(r'\s+', out.strip())) @@ -30,7 +32,6 @@ def test_immediate_dependents(mock_packages): ]) -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_transitive_dependents(mock_packages): out = dependents('--transitive', 'libelf') actual = set(re.split(r'\s+', out.strip())) @@ -47,7 +48,6 @@ def test_transitive_dependents(mock_packages): ]) -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_immediate_installed_dependents(mock_packages, database): with color_when(False): @@ -65,7 +65,6 @@ def test_immediate_installed_dependents(mock_packages, database): assert expected == hashes -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_transitive_installed_dependents(mock_packages, database): with color_when(False): diff --git a/lib/spack/spack/test/cmd/find.py b/lib/spack/spack/test/cmd/find.py index cc2b51590d..7760ef49a4 100644 --- a/lib/spack/spack/test/cmd/find.py +++ b/lib/spack/spack/test/cmd/find.py @@ -24,6 +24,9 @@ base32_alphabet = 'abcdefghijklmnopqrstuvwxyz234567' +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + @pytest.fixture(scope='module') def parser(): @@ -49,7 +52,6 @@ def display(x, *args, **kwargs): monkeypatch.setattr(spack.cmd, 'display_specs', display) -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_query_arguments(): query_arguments = spack.cmd.find.query_arguments @@ -87,7 +89,6 @@ def test_query_arguments(): assert q_args['explicit'] is False -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db @pytest.mark.usefixtures('database', 'mock_display') def test_tag1(parser, specs): @@ -100,7 +101,6 @@ def test_tag1(parser, specs): assert 'mpich2' in [x.name for x in specs] -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db @pytest.mark.usefixtures('database', 'mock_display') def test_tag2(parser, specs): @@ -111,7 +111,6 @@ def test_tag2(parser, specs): assert 'mpich' in [x.name for x in specs] -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db @pytest.mark.usefixtures('database', 'mock_display') def test_tag2_tag3(parser, specs): @@ -121,7 +120,6 @@ def test_tag2_tag3(parser, specs): assert len(specs) == 0 -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_namespaces_shown_correctly(database): out = find() @@ -157,7 +155,6 @@ def _check_json_output_deps(spec_list): assert names.count("libelf") == 1 -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_json(database): output = find('--json', 'mpileaks') @@ -165,7 +162,6 @@ def test_find_json(database): _check_json_output(spec_list) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_json_deps(database): output = find('-d', '--json', 'mpileaks') @@ -173,7 +169,6 @@ def test_find_json_deps(database): _check_json_output_deps(spec_list) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_display_json(database, capsys): specs = [Spec(s).concretized() for s in [ @@ -191,7 +186,6 @@ def test_display_json(database, capsys): _check_json_output(spec_list) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_display_json_deps(database, capsys): specs = [Spec(s).concretized() for s in [ @@ -209,7 +203,6 @@ def test_display_json_deps(database, capsys): _check_json_output_deps(spec_list) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_format(database, config): output = find('--format', '{name}-{^mpi.name}', 'mpileaks') @@ -243,7 +236,6 @@ def test_find_format(database, config): assert c in base32_alphabet -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_format_deps(database, config): output = find('-d', '--format', '{name}-{version}', 'mpileaks', '^zmpi') @@ -259,7 +251,6 @@ def test_find_format_deps(database, config): """ -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_format_deps_paths(database, config): output = find('-dp', '--format', '{name}-{version}', 'mpileaks', '^zmpi') @@ -279,7 +270,6 @@ def test_find_format_deps_paths(database, config): """.format(*prefixes) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_very_long(database, config): output = find('-L', '--no-groups', "mpileaks") @@ -295,14 +285,12 @@ def test_find_very_long(database, config): ]) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_show_compiler(database, config): output = find('--no-groups', '--show-full-compiler', "mpileaks") assert "mpileaks@2.3%gcc@4.5.0" in output -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_not_found(database, config, capsys): with capsys.disabled(): @@ -311,7 +299,6 @@ def test_find_not_found(database, config, capsys): assert find.returncode == 1 -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_no_sections(database, config): output = find() @@ -322,14 +309,12 @@ def test_find_no_sections(database, config): assert "==>" not in output -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.db def test_find_command_basic_usage(database): output = find() assert 'mpileaks' in output -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.regression('9875') def test_find_prefix_in_env(mutable_mock_env_path, install_mockery, mock_fetch, mock_packages, mock_archive, config): @@ -343,7 +328,6 @@ def test_find_prefix_in_env(mutable_mock_env_path, install_mockery, mock_fetch, # Would throw error on regression -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") def test_find_loaded(database, working_env): output = find('--loaded', '--group') assert output == '' diff --git a/lib/spack/spack/test/cmd/gc.py b/lib/spack/spack/test/cmd/gc.py index 1f3d776658..822564f0a4 100644 --- a/lib/spack/spack/test/cmd/gc.py +++ b/lib/spack/spack/test/cmd/gc.py @@ -13,8 +13,10 @@ gc = spack.main.SpackCommand('gc') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_no_packages_to_remove(config, mutable_database, capsys): with capsys.disabled(): @@ -22,7 +24,6 @@ def test_no_packages_to_remove(config, mutable_database, capsys): assert 'There are no unused specs.' in output -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_packages_are_removed(config, mutable_database, capsys): s = spack.spec.Spec('simple-inheritance') @@ -33,7 +34,6 @@ def test_packages_are_removed(config, mutable_database, capsys): assert 'Successfully uninstalled cmake' in output -@pytest.mark.skipif(sys.platform == "win32", reason="Test unsupported on Windows") @pytest.mark.db def test_gc_with_environment( config, mutable_database, mutable_mock_env_path, capsys diff --git a/lib/spack/spack/test/cmd/gpg.py b/lib/spack/spack/test/cmd/gpg.py index 694e5df353..96f7948b6d 100644 --- a/lib/spack/spack/test/cmd/gpg.py +++ b/lib/spack/spack/test/cmd/gpg.py @@ -21,8 +21,10 @@ gpg = SpackCommand('gpg') bootstrap = SpackCommand('bootstrap') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") # test gpg command detection @pytest.mark.parametrize('cmd_name,version', [ ('gpg', 'undetectable'), # undetectable version @@ -50,6 +52,8 @@ def test_find_gpg(cmd_name, version, tmpdir, mock_gnupghome, monkeypatch): assert spack.util.gpg.GPGCONF is not None +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_no_gpg_in_path(tmpdir, mock_gnupghome, monkeypatch, mutable_config): monkeypatch.setitem(os.environ, "PATH", str(tmpdir)) bootstrap('disable') @@ -57,7 +61,6 @@ def test_no_gpg_in_path(tmpdir, mock_gnupghome, monkeypatch, mutable_config): spack.util.gpg.init(force=True) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.maybeslow def test_gpg(tmpdir, mock_gnupghome): # Verify a file with an empty keyring. diff --git a/lib/spack/spack/test/cmd/graph.py b/lib/spack/spack/test/cmd/graph.py index 608b8573c1..06900cb0ac 100644 --- a/lib/spack/spack/test/cmd/graph.py +++ b/lib/spack/spack/test/cmd/graph.py @@ -11,8 +11,10 @@ graph = SpackCommand('graph') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('mock_packages', 'database') def test_graph_ascii(): @@ -20,7 +22,6 @@ def test_graph_ascii(): graph('--ascii', 'dt-diamond') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('mock_packages', 'database') def test_graph_dot(): @@ -28,7 +29,6 @@ def test_graph_dot(): graph('--dot', 'dt-diamond') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('mock_packages', 'database') def test_graph_static(): @@ -36,7 +36,6 @@ def test_graph_static(): graph('--static', 'dt-diamond') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('mock_packages', 'database') def test_graph_installed(): @@ -48,7 +47,6 @@ def test_graph_installed(): graph('--installed', 'dt-diamond') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('mock_packages', 'database') def test_graph_deptype(): @@ -56,7 +54,6 @@ def test_graph_deptype(): graph('--deptype', 'all', 'dt-diamond') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_graph_no_specs(): """Tests spack graph with no arguments""" diff --git a/lib/spack/spack/test/cmd/install.py b/lib/spack/spack/test/cmd/install.py index e85ed3d967..cc99c7d6a3 100644 --- a/lib/spack/spack/test/cmd/install.py +++ b/lib/spack/spack/test/cmd/install.py @@ -35,6 +35,9 @@ buildcache = SpackCommand('buildcache') find = SpackCommand('find') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + @pytest.fixture() def noop_install(monkeypatch): @@ -43,7 +46,6 @@ def noop(*args, **kwargs): monkeypatch.setattr(spack.installer.PackageInstaller, 'install', noop) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_install_package_and_dependency( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -61,7 +63,6 @@ def test_install_package_and_dependency( assert 'errors="0"' in content -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.disable_clean_stage_check def test_install_runtests_notests(monkeypatch, mock_packages, install_mockery): def check(pkg): @@ -70,7 +71,6 @@ def check(pkg): install('-v', 'dttop') -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.disable_clean_stage_check def test_install_runtests_root(monkeypatch, mock_packages, install_mockery): def check(pkg): @@ -80,7 +80,6 @@ def check(pkg): install('--test=root', 'dttop') -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.disable_clean_stage_check def test_install_runtests_all(monkeypatch, mock_packages, install_mockery): def check(pkg): @@ -91,7 +90,6 @@ def check(pkg): install('--run-tests', 'a') -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_install_package_already_installed( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -113,7 +111,6 @@ def test_install_package_already_installed( assert len(skipped) == 2 -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") @pytest.mark.parametrize('arguments,expected', [ ([], spack.config.get('config:dirty')), # default from config file (['--clean'], False), @@ -126,7 +123,6 @@ def test_install_dirty_flag(arguments, expected): assert args.dirty == expected -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_package_output(tmpdir, capsys, install_mockery, mock_fetch): """ Ensure output printed from pkgs is captured by output redirection. @@ -148,7 +144,6 @@ def test_package_output(tmpdir, capsys, install_mockery, mock_fetch): assert "AFTER INSTALL" in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_install_output_on_build_error(mock_packages, mock_archive, mock_fetch, config, install_mockery, capfd): @@ -163,7 +158,6 @@ def test_install_output_on_build_error(mock_packages, mock_archive, mock_fetch, assert 'Installing build-error' in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_install_output_on_python_error( mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -173,7 +167,6 @@ def test_install_output_on_python_error( assert 'raise InstallError("Expected failure.")' in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_install_with_source( mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -186,7 +179,6 @@ def test_install_with_source( os.path.join(src, 'configure')) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_env_variables( mock_packages, mock_archive, mock_fetch, config, install_mockery ): @@ -196,7 +188,6 @@ def test_install_env_variables( assert os.path.isfile(spec.package.install_env_path) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_show_log_on_error(mock_packages, mock_archive, mock_fetch, config, install_mockery, capfd): @@ -213,7 +204,6 @@ def test_show_log_on_error(mock_packages, mock_archive, mock_fetch, assert 'See build log for details:' in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_overwrite( mock_packages, mock_archive, mock_fetch, config, install_mockery ): @@ -247,7 +237,6 @@ def test_install_overwrite( assert fs.hash_directory(spec.prefix, ignore=ignores) != bad_md5 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_overwrite_not_installed( mock_packages, mock_archive, mock_fetch, config, install_mockery, ): @@ -261,7 +250,6 @@ def test_install_overwrite_not_installed( assert os.path.exists(spec.prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Not yet implemented on windows") def test_install_commit( mock_git_version_info, install_mockery, mock_packages, monkeypatch): """Test installing a git package from a commit. @@ -289,7 +277,6 @@ def test_install_commit( assert content == '[]' # contents are weird for another test -@pytest.mark.skipif(sys.platform == 'win32', reason="Not yet implemented on windows") def test_install_overwrite_multiple( mock_packages, mock_archive, mock_fetch, config, install_mockery ): @@ -347,7 +334,6 @@ def test_install_overwrite_multiple( assert cm_hash != bad_cmake_md5 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.usefixtures( 'mock_packages', 'mock_archive', 'mock_fetch', 'config', 'install_mockery', ) @@ -357,7 +343,6 @@ def test_install_conflicts(conflict_spec): install(conflict_spec) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.usefixtures( 'mock_packages', 'mock_archive', 'mock_fetch', 'config', 'install_mockery', ) @@ -367,7 +352,6 @@ def test_install_invalid_spec(invalid_spec): install(invalid_spec) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.usefixtures('noop_install', 'mock_packages', 'config') @pytest.mark.parametrize('spec,concretize,error_code', [ (Spec('mpi'), False, 1), @@ -400,7 +384,6 @@ def test_install_from_file(spec, concretize, error_code, tmpdir): assert err_msg in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check @pytest.mark.usefixtures( 'mock_packages', 'mock_archive', 'mock_fetch', 'config', 'install_mockery' @@ -443,7 +426,6 @@ def test_junit_output_with_failures(tmpdir, exc_typename, msg): assert msg in content -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check @pytest.mark.parametrize('exc_typename,expected_exc,msg', [ ('RuntimeError', spack.installer.InstallError, 'something weird happened'), @@ -487,7 +469,6 @@ def just_throw(*args, **kwargs): assert 'error message="{0}"'.format(msg) in content -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.usefixtures('noop_install', 'mock_packages', 'config') @pytest.mark.parametrize('clispecs,filespecs', [ [[], ['mpi']], @@ -512,7 +493,6 @@ def test_install_mix_cli_and_files(clispecs, filespecs, tmpdir): assert install.returncode == 0 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_extra_files_are_archived(mock_packages, mock_archive, mock_fetch, config, install_mockery): s = Spec('archive-files') @@ -532,7 +512,6 @@ def test_extra_files_are_archived(mock_packages, mock_archive, mock_fetch, assert os.path.exists(errors_txt) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_report_concretization_error(tmpdir, mock_fetch, install_mockery, capfd, conflict_spec): @@ -559,7 +538,6 @@ def test_cdash_report_concretization_error(tmpdir, mock_fetch, install_mockery, assert any(x in content for x in expected_messages) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_upload_build_error(tmpdir, mock_fetch, install_mockery, capfd): @@ -580,7 +558,6 @@ def test_cdash_upload_build_error(tmpdir, mock_fetch, install_mockery, assert 'configure: error: in /path/to/some/file:' in content -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_upload_clean_build(tmpdir, mock_fetch, install_mockery, capfd): # capfd interferes with Spack's capturing of e.g., Build.xml output @@ -599,7 +576,6 @@ def test_cdash_upload_clean_build(tmpdir, mock_fetch, install_mockery, capfd): assert '' not in content -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_upload_extra_params(tmpdir, mock_fetch, install_mockery, capfd): # capfd interferes with Spack's capture of e.g., Build.xml output @@ -622,7 +598,6 @@ def test_cdash_upload_extra_params(tmpdir, mock_fetch, install_mockery, capfd): assert '-my_custom_track' in content -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_buildstamp_param(tmpdir, mock_fetch, install_mockery, capfd): # capfd interferes with Spack's capture of e.g., Build.xml output @@ -645,7 +620,6 @@ def test_cdash_buildstamp_param(tmpdir, mock_fetch, install_mockery, capfd): assert buildstamp in content -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_install_from_spec_yaml(tmpdir, mock_fetch, install_mockery, capfd, mock_packages, mock_archive, @@ -684,7 +658,6 @@ def test_cdash_install_from_spec_yaml(tmpdir, mock_fetch, install_mockery, assert 'a@' in install_command -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_build_error_output(tmpdir, mock_fetch, install_mockery, capfd): with capfd.disabled(): @@ -699,7 +672,6 @@ def test_build_error_output(tmpdir, mock_fetch, install_mockery, capfd): assert 'configure: error: cannot run C compiled programs.' in msg -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_build_warning_output(tmpdir, mock_fetch, install_mockery, capfd): with capfd.disabled(): @@ -714,7 +686,6 @@ def test_build_warning_output(tmpdir, mock_fetch, install_mockery, capfd): assert 'foo.c:89: warning: some weird warning!' in msg -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_cache_only_fails(tmpdir, mock_fetch, install_mockery, capfd): # libelf from cache fails to install, which automatically removes the # the libdwarf build task @@ -731,7 +702,6 @@ def test_cache_only_fails(tmpdir, mock_fetch, install_mockery, capfd): assert 'libdwarf' in failure_lock_prefixes -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_only_dependencies(tmpdir, mock_fetch, install_mockery): dep = Spec('dependency-install').concretized() root = Spec('dependent-install').concretized() @@ -742,7 +712,6 @@ def test_install_only_dependencies(tmpdir, mock_fetch, install_mockery): assert not os.path.exists(root.prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_only_package(tmpdir, mock_fetch, install_mockery, capfd): msg = '' with capfd.disabled(): @@ -755,7 +724,6 @@ def test_install_only_package(tmpdir, mock_fetch, install_mockery, capfd): assert '1 uninstalled dependency' in msg -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_deps_then_package(tmpdir, mock_fetch, install_mockery): dep = Spec('dependency-install').concretized() root = Spec('dependent-install').concretized() @@ -768,7 +736,6 @@ def test_install_deps_then_package(tmpdir, mock_fetch, install_mockery): assert os.path.exists(root.prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.regression('12002') def test_install_only_dependencies_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock_env_path): @@ -784,7 +751,6 @@ def test_install_only_dependencies_in_env(tmpdir, mock_fetch, install_mockery, assert not os.path.exists(root.prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.regression('12002') def test_install_only_dependencies_of_all_in_env( tmpdir, mock_fetch, install_mockery, mutable_mock_env_path @@ -805,7 +771,6 @@ def test_install_only_dependencies_of_all_in_env( assert os.path.exists(dep.prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock_env_path): # To test behavior of --no-add option, we create the following environment: @@ -912,7 +877,6 @@ def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, assert(not any([s.name == 'bowtie' for s in e.uninstalled_specs()])) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_help_does_not_show_cdash_options(capsys): """ Make sure `spack install --help` does not describe CDash arguments @@ -923,7 +887,6 @@ def test_install_help_does_not_show_cdash_options(capsys): assert 'CDash URL' not in captured.out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_help_cdash(capsys): """Make sure `spack install --help-cdash` describes CDash arguments""" install_cmd = SpackCommand('install') @@ -931,7 +894,6 @@ def test_install_help_cdash(capsys): assert 'CDash URL' in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_auth_token(tmpdir, mock_fetch, install_mockery, capfd): # capfd interferes with Spack's capturing @@ -946,7 +908,6 @@ def test_cdash_auth_token(tmpdir, mock_fetch, install_mockery, capfd): assert 'Using CDash auth token from environment' in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.disable_clean_stage_check def test_cdash_configure_warning(tmpdir, mock_fetch, install_mockery, capfd): # capfd interferes with Spack's capturing of e.g., Build.xml output @@ -966,7 +927,6 @@ def test_cdash_configure_warning(tmpdir, mock_fetch, install_mockery, capfd): assert 'foo: No such file or directory' in content -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_compiler_bootstrap( install_mockery_mutable_config, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch): @@ -979,7 +939,6 @@ def test_compiler_bootstrap( install('a%gcc@2.0') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_compiler_bootstrap_from_binary_mirror( install_mockery_mutable_config, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch, tmpdir): @@ -1018,7 +977,6 @@ def test_compiler_bootstrap_from_binary_mirror( install('--no-cache', '--only', 'package', 'b%gcc@10.2.0') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.regression('16221') def test_compiler_bootstrap_already_installed( install_mockery_mutable_config, mock_packages, mock_fetch, @@ -1034,7 +992,6 @@ def test_compiler_bootstrap_already_installed( install('a%gcc@2.0') -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_install_fails_no_args(tmpdir): # ensure no spack.yaml in directory with tmpdir.as_cwd(): @@ -1046,7 +1003,6 @@ def test_install_fails_no_args(tmpdir): assert 'using the `spack.yaml` in this directory' not in output -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_install_fails_no_args_suggests_env_activation(tmpdir): # ensure spack.yaml in directory tmpdir.ensure('spack.yaml') @@ -1072,7 +1028,6 @@ def fake_full_hash(spec): return default_full_hash(spec) -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_cache_install_full_hash_match( install_mockery_mutable_config, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch, tmpdir): @@ -1131,7 +1086,6 @@ def test_cache_install_full_hash_match( shutil.rmtree(mirror_dir.strpath) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_env_with_tests_all(tmpdir, mock_packages, mock_fetch, install_mockery, mutable_mock_env_path): env('create', 'test') @@ -1142,7 +1096,6 @@ def test_install_env_with_tests_all(tmpdir, mock_packages, mock_fetch, assert os.path.exists(test_dep.prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_install_env_with_tests_root(tmpdir, mock_packages, mock_fetch, install_mockery, mutable_mock_env_path): env('create', 'test') diff --git a/lib/spack/spack/test/cmd/license.py b/lib/spack/spack/test/cmd/license.py index bd9636c088..8501434659 100644 --- a/lib/spack/spack/test/cmd/license.py +++ b/lib/spack/spack/test/cmd/license.py @@ -17,8 +17,10 @@ license = SpackCommand('license') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_list_files(): files = license('list-files').strip().split('\n') assert all(f.startswith(spack.paths.prefix) for f in files) @@ -26,7 +28,6 @@ def test_list_files(): assert os.path.abspath(__file__) in files -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_verify(tmpdir): source_dir = tmpdir.join('lib', 'spack', 'spack') mkdirp(str(source_dir)) @@ -74,7 +75,6 @@ def test_verify(tmpdir): assert license.returncode == 1 -@pytest.mark.skipif(sys.platform == 'win32', reason="All Fetchers Failed") def test_update_copyright_year(tmpdir): source_dir = tmpdir.join('lib', 'spack', 'spack') mkdirp(str(source_dir)) diff --git a/lib/spack/spack/test/cmd/location.py b/lib/spack/spack/test/cmd/location.py index 8d8d4fc5bf..fe73607a18 100644 --- a/lib/spack/spack/test/cmd/location.py +++ b/lib/spack/spack/test/cmd/location.py @@ -17,8 +17,9 @@ from spack.main import SpackCommand, SpackCommandError # Everything here uses (or can use) the mock config and database. -pytestmark = pytest.mark.usefixtures('config', 'database') - +pytestmark = [pytest.mark.usefixtures('config', 'database'), + pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows")] # location prints out "locations of packages and spack directories" location = SpackCommand('location') env = SpackCommand('env') @@ -38,14 +39,12 @@ def mock_spec(): shutil.rmtree(pkg.stage.path) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_location_build_dir(mock_spec): """Tests spack location --build-dir.""" spec, pkg = mock_spec assert location('--build-dir', spec.name).strip() == pkg.stage.source_path -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.regression('22738') def test_location_source_dir(mock_spec): """Tests spack location --source-dir.""" @@ -54,7 +53,6 @@ def test_location_source_dir(mock_spec): assert location(spec.name).strip() == pkg.stage.source_path -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_location_source_dir_missing(): """Tests spack location --source-dir with a missing source directory.""" spec = 'mpileaks' @@ -65,7 +63,6 @@ def test_location_source_dir_missing(): assert out == expected -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.parametrize('options', [([]), (['--source-dir', 'mpileaks']), (['--env', 'missing-env']), @@ -76,7 +73,6 @@ def test_location_cmd_error(options): location(*options) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_location_env_exists(mutable_mock_env_path): """Tests spack location --env for an existing environment.""" e = ev.create("example") @@ -84,7 +80,6 @@ def test_location_env_exists(mutable_mock_env_path): assert location('--env', "example").strip() == e.path -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_location_with_active_env(mutable_mock_env_path): """Tests spack location --env with active env""" e = ev.create("example") @@ -93,7 +88,6 @@ def test_location_with_active_env(mutable_mock_env_path): assert location('--env').strip() == e.path -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_location_env_flag_interference(mutable_mock_env_path, tmpdir): """ Tests that specifying an active environment using `spack -e x location ...` @@ -115,7 +109,6 @@ def test_location_env_flag_interference(mutable_mock_env_path, tmpdir): assert 'first_env' not in location('--packages', global_args=global_args) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_location_env_missing(): """Tests spack location --env.""" missing_env_name = 'missing-env' @@ -124,7 +117,6 @@ def test_location_env_missing(): assert out == error -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_location_install_dir(mock_spec): """Tests spack location --install-dir.""" @@ -132,7 +124,6 @@ def test_location_install_dir(mock_spec): assert location('--install-dir', spec.name).strip() == spec.prefix -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_location_package_dir(mock_spec): """Tests spack location --package-dir.""" @@ -140,7 +131,6 @@ def test_location_package_dir(mock_spec): assert location('--package-dir', spec.name).strip() == pkg.package_dir -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.parametrize('option,expected', [ ('--module-dir', spack.paths.module_path), @@ -151,7 +141,6 @@ def test_location_paths_options(option, expected): assert location(option).strip() == expected -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.parametrize('specs,expected', [ ([], "You must supply a spec."), (['spec1', 'spec2'], "Too many specs. Supply only one.")]) @@ -161,7 +150,6 @@ def test_location_spec_errors(specs, expected): assert location(*specs, fail_on_error=False).strip() == error -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_location_stage_dir(mock_spec): """Tests spack location --stage-dir.""" @@ -169,7 +157,6 @@ def test_location_stage_dir(mock_spec): assert location('--stage-dir', spec.name).strip() == pkg.stage.path -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_location_stages(mock_spec): """Tests spack location --stages.""" diff --git a/lib/spack/spack/test/cmd/mark.py b/lib/spack/spack/test/cmd/mark.py index a2e902ef96..d74c5df783 100644 --- a/lib/spack/spack/test/cmd/mark.py +++ b/lib/spack/spack/test/cmd/mark.py @@ -15,22 +15,22 @@ install = SpackCommand('install') uninstall = SpackCommand('uninstall') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_mark_mode_required(mutable_database): with pytest.raises(SystemExit): mark('-a') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_mark_spec_required(mutable_database): with pytest.raises(SpackCommandError): mark('-i') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_mark_all_explicit(mutable_database): mark('-e', '-a') @@ -39,7 +39,6 @@ def test_mark_all_explicit(mutable_database): assert len(all_specs) == 15 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_mark_all_implicit(mutable_database): mark('-i', '-a') @@ -48,7 +47,6 @@ def test_mark_all_implicit(mutable_database): assert len(all_specs) == 0 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_mark_one_explicit(mutable_database): mark('-e', 'libelf') @@ -58,7 +56,6 @@ def test_mark_one_explicit(mutable_database): assert len(all_specs) == 3 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_mark_one_implicit(mutable_database): mark('-i', 'externaltest') @@ -67,7 +64,6 @@ def test_mark_one_implicit(mutable_database): assert len(all_specs) == 14 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_mark_all_implicit_then_explicit(mutable_database): mark('-i', '-a') diff --git a/lib/spack/spack/test/cmd/mirror.py b/lib/spack/spack/test/cmd/mirror.py index c455aad514..ba7177cb41 100644 --- a/lib/spack/spack/test/cmd/mirror.py +++ b/lib/spack/spack/test/cmd/mirror.py @@ -20,6 +20,9 @@ buildcache = SpackCommand('buildcache') uninstall = SpackCommand('uninstall') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + @pytest.fixture def tmp_scope(): @@ -42,8 +45,6 @@ def tmp_scope(): @pytest.mark.disable_clean_stage_check @pytest.mark.regression('8083') -@pytest.mark.skipif(sys.platform == 'win32', - reason="MirrorCaches only work with file:// URLs") def test_regression_8083(tmpdir, capfd, mock_packages, mock_fetch, config): with capfd.disabled(): output = mirror('create', '-d', str(tmpdir), 'externaltool') @@ -51,8 +52,6 @@ def test_regression_8083(tmpdir, capfd, mock_packages, mock_fetch, config): assert 'as it is an external spec' in output -@pytest.mark.skipif(sys.platform == 'win32', - reason="MirrorCaches only work with file:// URLs") @pytest.mark.regression('12345') def test_mirror_from_env(tmpdir, mock_packages, mock_fetch, config, mutable_mock_env_path): @@ -86,8 +85,6 @@ def source_for_pkg_with_hash(mock_packages, tmpdir): pkg.versions[spack.version.Version('1.0')]['url'] = local_url -@pytest.mark.skipif(sys.platform == 'win32', - reason="MirrorCaches only work with file:// URLs") def test_mirror_skip_unstable(tmpdir_factory, mock_packages, config, source_for_pkg_with_hash): mirror_dir = str(tmpdir_factory.mktemp('mirror-dir')) @@ -152,7 +149,6 @@ def test_exclude_file(mock_packages, tmpdir, config): assert (not expected_exclude & set(mirror_specs)) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_mirror_crud(tmp_scope, capsys): with capsys.disabled(): mirror('add', '--scope', tmp_scope, 'mirror', 'http://spack.io') @@ -208,7 +204,6 @@ def test_mirror_crud(tmp_scope, capsys): assert 'No mirrors configured' in output -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_mirror_nonexisting(tmp_scope): with pytest.raises(SpackCommandError): mirror('remove', '--scope', tmp_scope, 'not-a-mirror') @@ -218,7 +213,6 @@ def test_mirror_nonexisting(tmp_scope): 'not-a-mirror', 'http://spack.io') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_mirror_name_collision(tmp_scope): mirror('add', '--scope', tmp_scope, 'first', '1') @@ -226,7 +220,6 @@ def test_mirror_name_collision(tmp_scope): mirror('add', '--scope', tmp_scope, 'first', '1') -@pytest.mark.skipif(sys.platform == 'win32', reason="hangs on windows") def test_mirror_destroy(install_mockery_mutable_config, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch, tmpdir): diff --git a/lib/spack/spack/test/cmd/module.py b/lib/spack/spack/test/cmd/module.py index cf5a0dbc8c..ec11ed2d65 100644 --- a/lib/spack/spack/test/cmd/module.py +++ b/lib/spack/spack/test/cmd/module.py @@ -16,6 +16,9 @@ module = spack.main.SpackCommand('module') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + #: make sure module files are generated for all the tests here @pytest.fixture(scope='module', autouse=True) @@ -60,14 +63,12 @@ def module_type(request): # TODO : this requires having a separate directory for test modules # TODO : add tests for loads and find to check the prompt format -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_exit_with_failure(database, module_type, failure_args): with pytest.raises(spack.main.SpackCommandError): module(module_type, *failure_args) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_remove_and_add(database, module_type): """Tests adding and removing a tcl module file.""" @@ -91,7 +92,6 @@ def test_remove_and_add(database, module_type): assert os.path.exists(item) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.parametrize('cli_args', [ ['libelf'], @@ -106,7 +106,6 @@ def test_find(database, cli_args, module_type): module(module_type, *(['find'] + cli_args)) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('database') @pytest.mark.regression('2215') @@ -126,7 +125,6 @@ def test_find_fails_on_multiple_matches(): assert 'matches multiple packages' in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('database') @pytest.mark.regression('2570') @@ -137,7 +135,6 @@ def test_find_fails_on_non_existing_packages(): assert 'matches no package' in out -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.usefixtures('database') def test_find_recursive(): @@ -151,7 +148,6 @@ def test_find_recursive(): assert len(out.split()) > 1 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_find_recursive_blacklisted(database, module_configuration): module_configuration('blacklist') @@ -160,7 +156,6 @@ def test_find_recursive_blacklisted(database, module_configuration): module('lmod', 'find', '-r', 'mpileaks ^mpich') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_loads_recursive_blacklisted(database, module_configuration): module_configuration('blacklist') @@ -185,7 +180,6 @@ def test_loads_recursive_blacklisted(database, module_configuration): writer_cls = spack.modules.lmod.LmodModulefileWriter -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_setdefault_command( mutable_database, mutable_config diff --git a/lib/spack/spack/test/cmd/undevelop.py b/lib/spack/spack/test/cmd/undevelop.py index 9182a1e45b..43a7f45ac3 100644 --- a/lib/spack/spack/test/cmd/undevelop.py +++ b/lib/spack/spack/test/cmd/undevelop.py @@ -15,9 +15,10 @@ env = SpackCommand('env') concretize = SpackCommand('concretize') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == "win32", - reason='Not supported on Windows (yet)') def test_undevelop(tmpdir, config, mock_packages, mutable_mock_env_path): # setup environment envdir = tmpdir.mkdir('env') @@ -45,8 +46,6 @@ def test_undevelop(tmpdir, config, mock_packages, mutable_mock_env_path): assert not after.satisfies('dev_path=*') -@pytest.mark.skipif(sys.platform == "win32", - reason='Not supported on Windows (yet)') def test_undevelop_nonexistent(tmpdir, config, mock_packages, mutable_mock_env_path): # setup environment envdir = tmpdir.mkdir('env') diff --git a/lib/spack/spack/test/cmd/uninstall.py b/lib/spack/spack/test/cmd/uninstall.py index fe813aaba4..4f0c0d9c91 100644 --- a/lib/spack/spack/test/cmd/uninstall.py +++ b/lib/spack/spack/test/cmd/uninstall.py @@ -15,6 +15,9 @@ uninstall = SpackCommand('uninstall') install = SpackCommand('install') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + class MockArgs(object): @@ -26,7 +29,6 @@ def __init__(self, packages, all=False, force=False, dependents=False): self.yes_to_all = True -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_multiple_matches(mutable_database): """Test unable to uninstall when multiple matches.""" @@ -34,7 +36,6 @@ def test_multiple_matches(mutable_database): uninstall('-y', 'mpileaks') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_installed_dependents(mutable_database): """Test can't uninstall when there are installed dependents.""" @@ -42,7 +43,6 @@ def test_installed_dependents(mutable_database): uninstall('-y', 'libelf') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_recursive_uninstall(mutable_database): """Test recursive uninstall.""" @@ -60,7 +60,6 @@ def test_recursive_uninstall(mutable_database): assert len(mpi_specs) == 3 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.regression('3690') @pytest.mark.parametrize('constraint,expected_number_of_specs', [ @@ -75,7 +74,6 @@ def test_uninstall_spec_with_multiple_roots( assert len(all_specs) == expected_number_of_specs -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.parametrize('constraint,expected_number_of_specs', [ ('dyninst', 14), ('libelf', 14) @@ -89,7 +87,6 @@ def test_force_uninstall_spec_with_ref_count_not_zero( assert len(all_specs) == expected_number_of_specs -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db def test_force_uninstall_and_reinstall_by_hash(mutable_database): """Test forced uninstall and reinstall of old specs.""" @@ -169,7 +166,6 @@ def db_specs(): assert len(mpi_specs) == 3 -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.db @pytest.mark.regression('15773') def test_in_memory_consistency_when_uninstalling( diff --git a/lib/spack/spack/test/cmd/verify.py b/lib/spack/spack/test/cmd/verify.py index 84dece61a7..357f3751c0 100644 --- a/lib/spack/spack/test/cmd/verify.py +++ b/lib/spack/spack/test/cmd/verify.py @@ -20,8 +20,10 @@ verify = SpackCommand('verify') install = SpackCommand('install') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_single_file_verify_cmd(tmpdir): # Test the verify command interface to verifying a single file. filedir = os.path.join(str(tmpdir), 'a', 'b', 'c', 'd') @@ -68,7 +70,6 @@ def test_single_file_verify_cmd(tmpdir): assert sorted(errors) == sorted(expected) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_single_spec_verify_cmd(tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): # Test the verify command interface to verify a single spec diff --git a/lib/spack/spack/test/cmd/versions.py b/lib/spack/spack/test/cmd/versions.py index 7d66f16b14..f3be1ed3fe 100644 --- a/lib/spack/spack/test/cmd/versions.py +++ b/lib/spack/spack/test/cmd/versions.py @@ -12,8 +12,10 @@ versions = SpackCommand('versions') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_safe_only_versions(): """Only test the safe versions of a package. (Using the deprecated command line argument) @@ -21,14 +23,12 @@ def test_safe_only_versions(): versions('--safe-only', 'zlib') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_safe_versions(): """Only test the safe versions of a package.""" versions('--safe', 'zlib') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.maybeslow def test_remote_versions(): """Test a package for which remote versions should be available.""" @@ -36,7 +36,6 @@ def test_remote_versions(): versions('zlib') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.maybeslow def test_remote_versions_only(): """Test a package for which remote versions should be available.""" @@ -44,7 +43,6 @@ def test_remote_versions_only(): versions('--remote', 'zlib') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.usefixtures('mock_packages') def test_new_versions_only(monkeypatch): """Test a package for which new versions should be available.""" @@ -73,7 +71,6 @@ def mock_fetch_remote_versions(*args, **kwargs): assert(v.strip(' \n\t') == "99.99.99\n 3.2.1") -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.maybeslow def test_no_versions(): """Test a package for which no remote versions are available.""" @@ -81,7 +78,6 @@ def test_no_versions(): versions('converge') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.maybeslow def test_no_unchecksummed_versions(): """Test a package for which no unchecksummed versions are available.""" @@ -89,7 +85,6 @@ def test_no_unchecksummed_versions(): versions('bzip2') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.maybeslow def test_versions_no_url(): """Test a package with versions but without a ``url`` attribute.""" @@ -97,7 +92,6 @@ def test_versions_no_url(): versions('graphviz') -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.maybeslow def test_no_versions_no_url(): """Test a package without versions or a ``url`` attribute.""" diff --git a/lib/spack/spack/test/cmd/view.py b/lib/spack/spack/test/cmd/view.py index a3d40493fe..d1d265bade 100644 --- a/lib/spack/spack/test/cmd/view.py +++ b/lib/spack/spack/test/cmd/view.py @@ -16,6 +16,9 @@ install = SpackCommand('install') view = SpackCommand('view') +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + def create_projection_file(tmpdir, projection): if 'projections' not in projection: @@ -26,7 +29,6 @@ def create_projection_file(tmpdir, projection): return projection_file -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.parametrize('cmd', ['hardlink', 'symlink', 'hard', 'add', 'copy', 'relocate']) def test_view_link_type( @@ -43,7 +45,6 @@ def test_view_link_type( assert os.path.islink(package_prefix) == is_link_cmd -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.parametrize('add_cmd', ['hardlink', 'symlink', 'hard', 'add', 'copy', 'relocate']) def test_view_link_type_remove( @@ -59,7 +60,6 @@ def test_view_link_type_remove( assert not os.path.exists(bindir) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") @pytest.mark.parametrize('cmd', ['hardlink', 'symlink', 'hard', 'add', 'copy', 'relocate']) def test_view_projections( @@ -85,7 +85,6 @@ def test_view_projections( assert os.path.islink(package_prefix) == is_symlink_cmd -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_multiple_projections( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -108,7 +107,6 @@ def test_view_multiple_projections( assert os.path.exists(extendee_prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_multiple_projections_all_first( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -131,7 +129,6 @@ def test_view_multiple_projections_all_first( assert os.path.exists(extendee_prefix) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_external( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -141,7 +138,6 @@ def test_view_external( assert 'Skipping external package: externaltool' in output -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_extension( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -168,7 +164,6 @@ def test_view_extension( assert os.path.exists(os.path.join(viewpath, 'bin', 'extension1')) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_extension_projection( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -202,7 +197,6 @@ def test_view_extension_projection( 'bin', 'extension1')) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_extension_remove( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -222,7 +216,6 @@ def test_view_extension_remove( assert not os.path.exists(os.path.join(viewpath, 'bin', 'extension1')) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_extension_conflict( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -235,7 +228,6 @@ def test_view_extension_conflict( assert 'Package conflict detected' in output -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_extension_conflict_ignored( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -249,7 +241,6 @@ def test_view_extension_conflict_ignored( assert fin.read() == '1.0' -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_extension_global_activation( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -279,7 +270,6 @@ def test_view_extension_global_activation( assert not os.path.exists(os.path.join(viewpath, 'bin', 'extension2')) -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_extendee_with_global_activations( tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery): @@ -293,7 +283,6 @@ def test_view_extendee_with_global_activations( assert 'Error: Globally activated extensions cannot be used' in output -@pytest.mark.skipif(sys.platform == 'win32', reason="Error on Win") def test_view_fails_with_missing_projections_file(tmpdir): viewpath = str(tmpdir.mkdir('view')) projection_file = os.path.join(str(tmpdir), 'nonexistent') diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index fd28f77a6a..61ecbfc4fd 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -22,6 +22,9 @@ from spack.util.mock_package import MockPackageMultiRepo from spack.version import ver +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + def check_spec(abstract, concrete): if abstract.versions.concrete: @@ -166,8 +169,6 @@ def change(self, context): return _changing_pkg -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") # This must use the mutable_config fixture because the test # adjusting_default_target_based_on_compiler uses the current_host fixture, # which changes the config. diff --git a/lib/spack/spack/test/concretize_preferences.py b/lib/spack/spack/test/concretize_preferences.py index 4f31e18d66..dccaee80a5 100644 --- a/lib/spack/spack/test/concretize_preferences.py +++ b/lib/spack/spack/test/concretize_preferences.py @@ -17,6 +17,9 @@ from spack.spec import Spec from spack.version import Version +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + @pytest.fixture() def concretize_scope(mutable_config, tmpdir): @@ -72,8 +75,6 @@ def assert_variant_values(spec, **variants): assert concrete.variants[variant].value == value -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.usefixtures('concretize_scope', 'mock_packages') class TestConcretizePreferences(object): @pytest.mark.parametrize('package_name,variant_value,expected_results', [ diff --git a/lib/spack/spack/test/database.py b/lib/spack/spack/test/database.py index 0f471c6a8b..af57fb8c5d 100644 --- a/lib/spack/spack/test/database.py +++ b/lib/spack/spack/test/database.py @@ -989,6 +989,8 @@ def test_database_works_with_empty_dir(tmpdir): assert not os.path.exists(db._index_path) +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") @pytest.mark.parametrize('query_arg,exc_type,msg_str', [ (['callpath'], spack.store.MatchError, 'matches multiple packages'), (['tensorflow'], spack.store.MatchError, 'does not match any') @@ -999,6 +1001,8 @@ def test_store_find_failures(database, query_arg, exc_type, msg_str): assert msg_str in str(exc_info.value) +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_store_find_accept_string(database): result = spack.store.find('callpath', multiple=True) assert len(result) == 3 diff --git a/lib/spack/spack/test/llnl/util/lock.py b/lib/spack/spack/test/llnl/util/lock.py index b2e3695454..e7788fa5a1 100644 --- a/lib/spack/spack/test/llnl/util/lock.py +++ b/lib/spack/spack/test/llnl/util/lock.py @@ -50,11 +50,11 @@ import shutil import socket import stat +import sys import tempfile import traceback from contextlib import contextmanager from multiprocessing import Process, Queue -from sys import platform as _platform import pytest @@ -62,6 +62,7 @@ import llnl.util.multiproc as mp from llnl.util.filesystem import getuid, touch +_platform = sys.platform if _platform == "win32": import pywintypes import win32con @@ -373,6 +374,8 @@ def __call__(self, barrier): # Test that exclusive locks on other processes time out when an # exclusive lock is held. # +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_write_lock_timeout_on_write(lock_path): multiproc_test( AcquireWrite(lock_path), @@ -617,6 +620,8 @@ def test_write_lock_timeout_with_multiple_readers_3_2_ranges(lock_path): TimeoutWrite(lock_path, 5, 1)) +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") @pytest.mark.skipif(getuid() == 0, reason='user is root') def test_read_lock_on_read_only_lockfile(lock_dir, lock_path): """read-only directory, read-only lockfile.""" @@ -632,6 +637,8 @@ def test_read_lock_on_read_only_lockfile(lock_dir, lock_path): pass +@pytest.mark.skipif(_platform == 'win32', + reason="Not supported on Windows (yet)") def test_read_lock_read_only_dir_writable_lockfile(lock_dir, lock_path): """read-only directory, writable lockfile.""" touch(lock_path) @@ -699,6 +706,8 @@ def test_upgrade_read_to_write(private_lock_path): assert lock._file is None +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_upgrade_read_to_write_fails_with_readonly_file(private_lock_path): """Test that read-only file can be read-locked but not write-locked.""" # ensure lock file exists the first time @@ -853,6 +862,8 @@ def p3(self, barrier): # Longer test case that ensures locks are reusable. Ordering is # enforced by barriers throughout -- steps are shown with numbers. # +@pytest.mark.skipif(sys.platform == 'win32', + reason="Not supported on Windows (yet)") def test_complex_acquire_and_release_chain(lock_path): test_chain = ComplexAcquireAndRelease(lock_path) multiproc_test(test_chain.p1, @@ -897,6 +908,8 @@ def release_write(self, release_fn=None): return result +@pytest.mark.skipif(_platform == 'win32', + reason="Not supported on Windows (yet)") @pytest.mark.parametrize( "transaction,type", [(lk.ReadTransaction, "read"), (lk.WriteTransaction, "write")] @@ -944,6 +957,8 @@ def exit_fn(t, v, tb): assert not vals['exception'] +@pytest.mark.skipif(_platform == 'win32', + reason="Not supported on Windows (yet)") @pytest.mark.parametrize( "transaction,type", [(lk.ReadTransaction, "read"), (lk.WriteTransaction, "write")] @@ -1001,6 +1016,8 @@ def exit_fn(t, v, tb): assert vals['exception'] +@pytest.mark.skipif(_platform == 'win32', + reason="Not supported on Windows (yet)") @pytest.mark.parametrize( "transaction,type", [(lk.ReadTransaction, "read"), (lk.WriteTransaction, "write")] @@ -1119,6 +1136,8 @@ def assert_only_ctx_exception(raises=True): assert_only_ctx_exception(raises=False) +@pytest.mark.skipif(_platform == 'win32', + reason="Not supported on Windows (yet)") def test_nested_write_transaction(lock_path): """Ensure that the outermost write transaction writes.""" @@ -1170,6 +1189,8 @@ def write(t, v, tb): assert vals['wrote'] +@pytest.mark.skipif(_platform == 'win32', + reason="Not supported on Windows (yet)") def test_nested_reads(lock_path): """Ensure that write transactions won't re-read data.""" diff --git a/lib/spack/spack/test/llnl/util/tty/log.py b/lib/spack/spack/test/llnl/util/tty/log.py index bd6c0ebcfe..fd8c7d30da 100644 --- a/lib/spack/spack/test/llnl/util/tty/log.py +++ b/lib/spack/spack/test/llnl/util/tty/log.py @@ -32,12 +32,15 @@ pass +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + + @contextlib.contextmanager def nullcontext(): yield -@pytest.mark.skipif(sys.platform == 'win32', reason="echo not implemented on windows") def test_log_python_output_with_echo(capfd, tmpdir): with tmpdir.as_cwd(): with log.log_output('foo.txt', echo=True): @@ -51,7 +54,6 @@ def test_log_python_output_with_echo(capfd, tmpdir): assert capfd.readouterr()[0] == 'logged\n' -@pytest.mark.skipif(sys.platform == 'win32', reason="echo not implemented on windows") def test_log_python_output_without_echo(capfd, tmpdir): with tmpdir.as_cwd(): with log.log_output('foo.txt'): @@ -65,7 +67,6 @@ def test_log_python_output_without_echo(capfd, tmpdir): assert capfd.readouterr()[0] == '' -@pytest.mark.skipif(sys.platform == 'win32', reason="echo not implemented on windows") def test_log_python_output_with_invalid_utf8(capfd, tmpdir): with tmpdir.as_cwd(): with log.log_output('foo.txt'): @@ -84,7 +85,6 @@ def test_log_python_output_with_invalid_utf8(capfd, tmpdir): assert capfd.readouterr()[0] == '' -@pytest.mark.skipif(sys.platform == 'win32', reason="echo not implemented on windows") def test_log_python_output_and_echo_output(capfd, tmpdir): with tmpdir.as_cwd(): # echo two lines @@ -105,8 +105,6 @@ def _log_filter_fn(string): return string.replace("foo", "bar") -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") def test_log_output_with_filter(capfd, tmpdir): with tmpdir.as_cwd(): with log.log_output('foo.txt', filter_fn=_log_filter_fn): @@ -136,7 +134,7 @@ def test_log_output_with_filter(capfd, tmpdir): assert capfd.readouterr()[0] == 'bar blah\nblah bar\nbar bar\n' -@pytest.mark.skipif(not which('echo') or os.name == 'nt', reason="needs echo command") +@pytest.mark.skipif(not which('echo'), reason="needs echo command") def test_log_subproc_and_echo_output_no_capfd(capfd, tmpdir): echo = which('echo') @@ -154,7 +152,7 @@ def test_log_subproc_and_echo_output_no_capfd(capfd, tmpdir): assert f.read() == 'echo\nlogged\n' -@pytest.mark.skipif(not which('echo') or os.name == 'nt', reason="needs echo command") +@pytest.mark.skipif(not which('echo'), reason="needs echo command") def test_log_subproc_and_echo_output_capfd(capfd, tmpdir): echo = which('echo') diff --git a/lib/spack/spack/test/make_executable.py b/lib/spack/spack/test/make_executable.py index 84f0374bcc..a814601176 100644 --- a/lib/spack/spack/test/make_executable.py +++ b/lib/spack/spack/test/make_executable.py @@ -19,9 +19,10 @@ from spack.build_environment import MakeExecutable from spack.util.environment import path_put_first +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") class MakeExecutableTest(unittest.TestCase): def setUp(self): diff --git a/lib/spack/spack/test/mirror.py b/lib/spack/spack/test/mirror.py index 7d03161c02..0aeb4f46f9 100644 --- a/lib/spack/spack/test/mirror.py +++ b/lib/spack/spack/test/mirror.py @@ -20,7 +20,9 @@ from spack.util.executable import which from spack.util.spack_yaml import SpackYAMLError -pytestmark = pytest.mark.usefixtures('mutable_config', 'mutable_mock_repo') +pytestmark = [pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows"), + pytest.mark.usefixtures('mutable_config', 'mutable_mock_repo')] # paths in repos that shouldn't be in the mirror tarballs. exclude = ['.hg', '.git', '.svn'] @@ -104,16 +106,12 @@ def check_mirror(): assert all(left in exclude for left in dcmp.left_only) -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") def test_url_mirror(mock_archive): set_up_package('trivial-install-test-package', mock_archive, 'url') check_mirror() repos.clear() -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.skipif( not which('git'), reason='requires git to be installed') def test_git_mirror(mock_git_repository): @@ -122,8 +120,6 @@ def test_git_mirror(mock_git_repository): repos.clear() -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.skipif( not which('svn') or not which('svnadmin'), reason='requires subversion to be installed') @@ -133,8 +129,6 @@ def test_svn_mirror(mock_svn_repository): repos.clear() -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.skipif( not which('hg'), reason='requires mercurial to be installed') def test_hg_mirror(mock_hg_repository): @@ -143,8 +137,6 @@ def test_hg_mirror(mock_hg_repository): repos.clear() -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.skipif( not all([which('svn'), which('hg'), which('git')]), reason='requires subversion, git, and mercurial to be installed') @@ -330,8 +322,6 @@ def archive(dst): pass -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.regression('14067') def test_mirror_cache_symlinks(tmpdir): """Confirm that the cosmetic symlink created in the mirror cache (which may diff --git a/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py index 9218c80d3d..6e0c647a6b 100644 --- a/lib/spack/spack/test/sbang.py +++ b/lib/spack/spack/test/sbang.py @@ -26,6 +26,11 @@ if sys.platform != 'win32': import grp + +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + + too_long = sbang.system_shebang_limit + 1 diff --git a/lib/spack/spack/test/spec_dag.py b/lib/spack/spack/test/spec_dag.py index a14855069d..929d2c36bb 100644 --- a/lib/spack/spack/test/spec_dag.py +++ b/lib/spack/spack/test/spec_dag.py @@ -16,6 +16,9 @@ from spack.spec import Spec from spack.util.mock_package import MockPackageMultiRepo +pytestmark = pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows") + def check_links(spec_to_check): for spec in spec_to_check.traverse(): diff --git a/lib/spack/spack/test/svn_fetch.py b/lib/spack/spack/test/svn_fetch.py index b15d2e2ca3..5051df5fc8 100644 --- a/lib/spack/spack/test/svn_fetch.py +++ b/lib/spack/spack/test/svn_fetch.py @@ -18,13 +18,13 @@ from spack.util.executable import which from spack.version import ver -pytestmark = pytest.mark.skipif( - not which('svn') or not which('svnadmin'), - reason='requires subversion to be installed') +pytestmark = [pytest.mark.skipif( + not which('svn') or not which('svnadmin'), + reason='requires subversion to be installed'), + pytest.mark.skipif(sys.platform == "win32", + reason="does not run on windows")] -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") @pytest.mark.parametrize("type_of_test", ['default', 'rev0']) @pytest.mark.parametrize("secure", [True, False]) def test_fetch( @@ -81,8 +81,6 @@ def test_fetch( assert h() == t.revision -@pytest.mark.skipif(sys.platform == 'win32', - reason="Not supported on Windows (yet)") def test_svn_extra_fetch(tmpdir): """Ensure a fetch after downloading is effectively a no-op.""" testpath = str(tmpdir) diff --git a/lib/spack/spack/test/util/unparse/unparse.py b/lib/spack/spack/test/util/unparse/unparse.py index 85ab5c6b1b..f3a74aa9b7 100644 --- a/lib/spack/spack/test/util/unparse/unparse.py +++ b/lib/spack/spack/test/util/unparse/unparse.py @@ -17,6 +17,9 @@ import spack.util.unparse +pytestmark = pytest.mark.skipif(sys.platform == 'win32', + reason="Test module unsupported on Windows") + def read_pyfile(filename): """Read and return the contents of a Python source file (as a diff --git a/lib/spack/spack/util/path.py b/lib/spack/spack/util/path.py index 1a44e1946f..e83e3cb734 100644 --- a/lib/spack/spack/util/path.py +++ b/lib/spack/spack/util/path.py @@ -8,18 +8,25 @@ TODO: this is really part of spack.config. Consolidate it. """ import contextlib +import errno import getpass import os import re +import stat import subprocess import tempfile +from sys import platform as _platform import llnl.util.tty as tty +from llnl.util.filesystem import mkdirp from llnl.util.lang import memoized import spack.paths import spack.util.spack_yaml as syaml +if _platform == "win32": + import win32security + __all__ = [ 'substitute_config_variables', 'substitute_path_variables', @@ -70,6 +77,30 @@ def get_system_path_max(): return sys_max_path_length +def get_owner_uid(path, err_msg=None): + if not os.path.exists(path): + mkdirp(path, mode=stat.S_IRWXU) + + p_stat = os.stat(path) + if p_stat.st_mode & stat.S_IRWXU != stat.S_IRWXU: + tty.error("Expected {0} to support mode {1}, but it is {2}" + .format(path, stat.S_IRWXU, p_stat.st_mode)) + + raise OSError(errno.EACCES, + err_msg.format(path, path) if err_msg else "") + else: + p_stat = os.stat(path) + + if _platform != "win32": + owner_uid = p_stat.st_uid + else: + sid = win32security.GetFileSecurity( + path, win32security.OWNER_SECURITY_INFORMATION) \ + .GetSecurityDescriptorOwner() + owner_uid = win32security.LookupAccountSid(None, sid)[0] + return owner_uid + + def substitute_config_variables(path): """Substitute placeholders into paths. diff --git a/var/spack/repos/builtin/packages/nasm/package.py b/var/spack/repos/builtin/packages/nasm/package.py index 6bfa36a660..b4794eecfb 100644 --- a/var/spack/repos/builtin/packages/nasm/package.py +++ b/var/spack/repos/builtin/packages/nasm/package.py @@ -45,7 +45,7 @@ def patch(self): def configure(self, spec, prefix): with working_dir(self.stage.source_path, create=True): if not is_windows: - configure(['--prefix={0}'.format(self.prefix)]) + configure(*['--prefix={0}'.format(self.prefix)]) def build(self, spec, prefix): with working_dir(self.stage.source_path): @@ -53,11 +53,11 @@ def build(self, spec, prefix): touch('asm\\warnings.time') nmake('/f', 'Mkfiles\\msvc.mak') else: - make(['V=1']) + make(*['V=1']) def install(self, spec, prefix): with working_dir(self.stage.source_path): if is_windows: pass else: - make(['install']) + make(*['install']) diff --git a/var/spack/repos/builtin/packages/ninja/package.py b/var/spack/repos/builtin/packages/ninja/package.py index d6cc0d59d1..b242d2eeea 100644 --- a/var/spack/repos/builtin/packages/ninja/package.py +++ b/var/spack/repos/builtin/packages/ninja/package.py @@ -2,6 +2,7 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import sys class Ninja(Package): @@ -53,9 +54,14 @@ def setup_run_environment(self, env): def install(self, spec, prefix): mkdir(prefix.bin) - install('ninja', prefix.bin) + name = 'ninja' + if sys.platform == 'win32': + name = name + '.exe' + install(name, prefix.bin) install_tree('misc', prefix.misc) + if sys.platform == "win32": + return # Some distros like Fedora install a 'ninja-build' executable # instead of 'ninja'. Install both for uniformity. with working_dir(prefix.bin): diff --git a/var/spack/repos/builtin/packages/perl/package.py b/var/spack/repos/builtin/packages/perl/package.py index 714c7e3a7b..a16bfc95de 100644 --- a/var/spack/repos/builtin/packages/perl/package.py +++ b/var/spack/repos/builtin/packages/perl/package.py @@ -194,7 +194,7 @@ def nmake_arguments(self): args.append('CCTYPE=%s' % self.compiler.msvc_version) else: raise RuntimeError("Perl unsupported for non MSVC compilers on Windows") - args.append('INST_TOP="%s"' % self.prefix.replace('/', '\\')) + args.append('INST_TOP=%s' % self.prefix.replace('/', '\\')) args.append("INST_ARCH=\\$(ARCHNAME)") if self.spec.satisfies('~shared'): args.append("ALL_STATIC=%s" % "define") diff --git a/var/spack/repos/builtin/packages/python/package.py b/var/spack/repos/builtin/packages/python/package.py index cd67ac4dc3..0e38a56325 100644 --- a/var/spack/repos/builtin/packages/python/package.py +++ b/var/spack/repos/builtin/packages/python/package.py @@ -846,9 +846,13 @@ def command(self): # in that order if using python@3.6.5, for example. version = self.spec.version for ver in [version.up_to(2), version.up_to(1), '']: - path = os.path.join(self.prefix.bin, 'python{0}'.format(ver)) + if sys.platform != "win32": + path = os.path.join(self.prefix.bin, 'python{0}'.format(ver)) + else: + path = os.path.join(self.prefix, 'python{0}.exe'.format(ver)) if os.path.exists(path): return Executable(path) + else: msg = 'Unable to locate {0} command in {1}' raise RuntimeError(msg.format(self.name, self.prefix.bin)) @@ -892,21 +896,6 @@ def config_vars(self): Returns: dict: variable definitions """ - # Some values set by sysconfig may not always exist on Windows, so - # compute Windows alternatives - def repair_win_sysconf(conf): - if is_windows: - conf["LIBDIR"] = os.path.join(conf["LIBDEST"], "..", "libs") - conf["LIBPL"] = conf["LIBDIR"] - conf["PYTHONFRAMEWORKPREFIX"] = "" - conf["LDLIBRARY"] = "python" + conf["VERSION"] + ".dll" - conf["LIBRARY"] = "python" + conf["VERSION"] + ".lib" - conf["CC"] = "" - conf["CXX"] = "" - conf["LDSHARED"] = "" - conf["LDCXXSHARED"] = "" - - return conf # TODO: distutils is deprecated in Python 3.10 and will be removed in # Python 3.12, find a different way to access this information. @@ -976,7 +965,7 @@ def repair_win_sysconf(conf): config.update(json.loads(self.command('-c', cmd, output=str))) except (ProcessError, RuntimeError): pass - self._config_vars[dag_hash] = repair_win_sysconf(config) + self._config_vars[dag_hash] = config return self._config_vars[dag_hash] def get_sysconfigdata_name(self): diff --git a/var/spack/repos/builtin/packages/ruby/package.py b/var/spack/repos/builtin/packages/ruby/package.py index b4ca1afaff..9d83c7b66b 100644 --- a/var/spack/repos/builtin/packages/ruby/package.py +++ b/var/spack/repos/builtin/packages/ruby/package.py @@ -46,7 +46,9 @@ class Ruby(Package): depends_on('openssl@:1.0', when='@:2.3') extendable = True - phases = ['autoreconf', 'configure', 'build', 'install'] + phases = ['configure', 'build', 'install'] + build_targets = [] + install_targets = ['install'] # Known build issues when Avira antivirus software is running: # https://github.com/rvm/rvm/issues/4313#issuecomment-374020379 # TODO: add check for this and warn user @@ -120,17 +122,17 @@ def setup_dependent_package(self, module, dependent_spec): module.rake = Executable(self.prefix.bin.rake) def configure(self, spec, prefix): - with working_dir(self.build_directory, create=True): - if is_windows: - Executable("win32\\configure.bat", "--prefix=%s" % self.prefix) - else: - options = getattr(self, 'configure_flag_args', []) - options += ['--prefix={0}'.format(prefix)] - options += self.configure_args() - configure(*options) + with working_dir(self.stage.source_path, create=True): + # if is_windows: + Executable("win32\\configure.bat")("--prefix=%s" % self.prefix) + # else: + # options = getattr(self, 'configure_flag_args', []) + # options += ['--prefix={0}'.format(prefix)] + # options += self.configure_args() + # configure(*options) def build(self, spec, prefix): - with working_dir(self.build_directory): + with working_dir(self.stage.source_path): if is_windows: nmake() else: @@ -139,7 +141,7 @@ def build(self, spec, prefix): make(*params) def install(self, spec, prefix): - with working_dir(self.build_directory): + with working_dir(self.stage.source_path): if is_windows: nmake('install') else: