From 81bc00d61fd9872514e5e25b4af405e6d3c9202e Mon Sep 17 00:00:00 2001 From: Ben Cowan Date: Mon, 1 Feb 2021 07:26:47 -0700 Subject: Adding basic Windows features (#21259) * Snapshot of some MSVC infrastructure added during experiments a while ago. Rebasing from spack/develop. * Added platform and OS definitions for Windows. * Updated Windows platform file to conform to new archspec use. * Added Windows as a platform; introduced some debugging code. * Added type annotations. * Fixed copyright. * Removed print statements. * Ensure `spack arch` returns correctly on Windows (#21428) * Correctly identify windows as 'windows-Windows10-AMD64' --- lib/spack/env/cc | 2 +- lib/spack/llnl/util/tty/log.py | 5 ++-- lib/spack/spack/compilers/msvc.py | 35 ++++++++++++++++++++++ lib/spack/spack/operating_systems/windows_os.py | 29 ++++++++++++++++++ lib/spack/spack/platforms/windows.py | 40 +++++++++++++++++++++++++ lib/spack/spack/util/debug.py | 30 +++++++++++++++++++ 6 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 lib/spack/spack/compilers/msvc.py create mode 100755 lib/spack/spack/operating_systems/windows_os.py create mode 100755 lib/spack/spack/platforms/windows.py (limited to 'lib') diff --git a/lib/spack/env/cc b/lib/spack/env/cc index 1a52f2c612..9fd0e4dfbc 100755 --- a/lib/spack/env/cc +++ b/lib/spack/env/cc @@ -241,7 +241,7 @@ case "$command" in mode=cpp debug_flags="-g" ;; - cc|c89|c99|gcc|clang|armclang|icc|icx|pgcc|nvc|xlc|xlc_r|fcc|amdclang) + cc|c89|c99|gcc|clang|armclang|icc|icx|pgcc|nvc|xlc|xlc_r|fcc|amdclang|cl.exe) command="$SPACK_CC" language="C" comp="CC" diff --git a/lib/spack/llnl/util/tty/log.py b/lib/spack/llnl/util/tty/log.py index 1a93b570a5..566d180645 100644 --- a/lib/spack/llnl/util/tty/log.py +++ b/lib/spack/llnl/util/tty/log.py @@ -564,7 +564,7 @@ class log_output(object): sys.stdout.flush() sys.stderr.flush() - # Now do the actual output rediction. + # Now do the actual output redirection. self.use_fds = _file_descriptors_work(sys.stdout, sys.stderr) if self.use_fds: # We try first to use OS-level file descriptors, as this @@ -725,7 +725,8 @@ def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo, # write_fd to terminate the reading loop, so we close the file descriptor # here. Forking is the process spawning method everywhere except Mac OS # for Python >= 3.8 and on Windows - if sys.version_info < (3, 8) or sys.platform != 'darwin': + if sys.version_info < (3, 8) \ + or sys.platform not in ['darwin', 'cygwin']: os.close(write_fd) # Use line buffering (3rd param = 1) since Python 3 has a bug diff --git a/lib/spack/spack/compilers/msvc.py b/lib/spack/spack/compilers/msvc.py new file mode 100644 index 0000000000..ac5da84705 --- /dev/null +++ b/lib/spack/spack/compilers/msvc.py @@ -0,0 +1,35 @@ +# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +from typing import List # novm +from spack.compiler import Compiler + + +class Msvc(Compiler): + # Subclasses use possible names of C compiler + cc_names = ['cl.exe'] + + # Subclasses use possible names of C++ compiler + cxx_names = ['cl.exe'] + + # Subclasses use possible names of Fortran 77 compiler + f77_names = [] # type: List[str] + + # Subclasses use possible names of Fortran 90 compiler + fc_names = [] # type: List[str] + + # Named wrapper links within build_env_path + link_paths = {'cc': 'msvc/cl.exe', + 'cxx': 'msvc/cl.exe', + 'f77': '', + 'fc': ''} + + @property + def verbose_flag(self): + return "" + + @property + def pic_flag(self): + return "" diff --git a/lib/spack/spack/operating_systems/windows_os.py b/lib/spack/spack/operating_systems/windows_os.py new file mode 100755 index 0000000000..c4f8fa7f84 --- /dev/null +++ b/lib/spack/spack/operating_systems/windows_os.py @@ -0,0 +1,29 @@ +# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +from spack.architecture import OperatingSystem +from spack.version import Version + + +# FIXME: To get the actual Windows version, we need a python that runs +# natively on Windows, not Cygwin. +def windows_version(): + """temporary workaround to return a Windows version as a Version object + """ + return Version('10') + + +class WindowsOs(OperatingSystem): + """This class represents the Windows operating system. This will be + auto detected using the python platform.win32_ver() once we have a + python setup that runs natively. The Windows platform will be represented + using the major version operating system number, e.g. 10. + """ + + def __init__(self): + super(WindowsOs, self).__init__('Windows10', '10') + + def __str__(self): + return self.name diff --git a/lib/spack/spack/platforms/windows.py b/lib/spack/spack/platforms/windows.py new file mode 100755 index 0000000000..7c9ed1443d --- /dev/null +++ b/lib/spack/spack/platforms/windows.py @@ -0,0 +1,40 @@ +# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +import platform + +import archspec.cpu + +from spack.architecture import Platform, Target +from spack.operating_systems.windows_os import WindowsOs + + +class Windows(Platform): + priority = 101 + + # binary_formats = ['macho'] + + def __init__(self): + super(Windows, self).__init__('windows') + + for name in archspec.cpu.TARGETS: + self.add_target(name, Target(name)) + + self.default = archspec.cpu.host().name + self.front_end = self.default + self.back_end = self.default + + windows_os = WindowsOs() + + self.default_os = str(windows_os) + self.front_os = str(windows_os) + self.back_os = str(windows_os) + + self.add_operating_system(str(windows_os), windows_os) + + @classmethod + def detect(cls): + plat = platform.system().lower() + return 'cygwin' in plat or 'win32' in plat or 'windows' in plat diff --git a/lib/spack/spack/util/debug.py b/lib/spack/spack/util/debug.py index 0cae1ef58a..8a15b76f16 100644 --- a/lib/spack/spack/util/debug.py +++ b/lib/spack/spack/util/debug.py @@ -13,6 +13,8 @@ import code import os import signal import traceback +import sys +import pdb def debug_handler(sig, frame): @@ -32,3 +34,31 @@ def debug_handler(sig, frame): def register_interrupt_handler(): """Print traceback and enter an interpreter on Ctrl-C""" signal.signal(signal.SIGINT, debug_handler) + + +# Subclass of the debugger to keep readline working. See +# https://stackoverflow.com/questions/4716533/how-to-attach-debugger-to-a-python-subproccess/23654936 +class ForkablePdb(pdb.Pdb): + + _original_stdin_fd = sys.stdin.fileno() + _original_stdin = None + + def __init__(self, stdout_fd=None, stderr_fd=None): + pdb.Pdb.__init__(self, nosigint=True) + self._stdout_fd = stdout_fd + self._stderr_fd = stderr_fd + + def _cmdloop(self): + current_stdin = sys.stdin + try: + if not self._original_stdin: + self._original_stdin = os.fdopen(self._original_stdin_fd) + sys.stdin = self._original_stdin + if self._stdout_fd is not None: + os.dup2(self._stdout_fd, sys.stdout.fileno()) + os.dup2(self._stdout_fd, self.stdout.fileno()) + if self._stderr_fd is not None: + os.dup2(self._stderr_fd, sys.stderr.fileno()) + self.cmdloop() + finally: + sys.stdin = current_stdin -- cgit v1.2.3-60-g2f50