From a0164793cbf763ae9691b957fa90bce1c9102871 Mon Sep 17 00:00:00 2001 From: Ben Cowan Date: Fri, 22 Oct 2021 14:29:44 -0400 Subject: Features/windows install (#22204) * Fixed path and uid issues. * Added needed import statement; kluged .exe extension. * Got package to build. Some manual intervention necessary, including sourcing the MSVC setup script and having certain configuration parameters. * Removed CMake executable suffix hack. --- lib/spack/spack/build_environment.py | 5 ++++- lib/spack/spack/build_systems/cmake.py | 38 +++++++++++++++++++--------------- lib/spack/spack/directory_layout.py | 7 ++++--- lib/spack/spack/stage.py | 25 ++++++++++++++++++---- 4 files changed, 50 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index 542c0a504d..7888dee139 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -524,6 +524,7 @@ def _set_variables_for_single_module(pkg, module): m.configure = Executable('./configure') m.meson = Executable('meson') + # m.cmake = Executable('cmake') m.cmake = Executable('cmake') m.ctest = MakeExecutable('ctest', jobs) @@ -1136,7 +1137,8 @@ def start_build_process(pkg, function, kwargs): try: # Forward sys.stdin when appropriate, to allow toggling verbosity - if sys.platform != "win32" and sys.stdin.isatty() and hasattr(sys.stdin, 'fileno'): + if sys.platform != "win32" and sys.stdin.isatty() and hasattr(sys.stdin, + 'fileno'): input_fd = os.dup(sys.stdin.fileno()) input_multiprocess_fd = MultiProcessFd(input_fd) @@ -1144,6 +1146,7 @@ def start_build_process(pkg, function, kwargs): target=_setup_pkg_and_run, args=(serialized_pkg, function, kwargs, child_pipe, input_multiprocess_fd)) + p.start() except InstallError as e: diff --git a/lib/spack/spack/build_systems/cmake.py b/lib/spack/spack/build_systems/cmake.py index 4ef798fd51..02f32766bd 100644 --- a/lib/spack/spack/build_systems/cmake.py +++ b/lib/spack/spack/build_systems/cmake.py @@ -8,6 +8,7 @@ import inspect import os import platform import re +import sys from typing import List # novm import six @@ -17,7 +18,7 @@ from llnl.util.filesystem import working_dir import spack.build_environment from spack.directives import conflicts, depends_on, variant -from spack.package import InstallError, PackageBase, run_after +from spack.package import PackageBase, run_after # Regex to extract the primary generator from the CMake generator # string. @@ -91,7 +92,16 @@ class CMakePackage(PackageBase): #: #: See https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html #: for more information. - generator = 'Unix Makefiles' + + variant('generator', + default='Make' if sys.platform != 'win32' else 'Ninja', + description='Build system to generate', + values=('Make', 'Ninja')) + + depends_on('ninja', when='generator=Ninja') + + generatorMap = {'Make': 'Unix Makefiles', + 'Ninja': 'Ninja'} # https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html variant('build_type', default='RelWithDebInfo', @@ -138,20 +148,12 @@ class CMakePackage(PackageBase): @staticmethod def _std_args(pkg): """Computes the standard cmake arguments for a generic package""" + try: - generator = pkg.generator - except AttributeError: - generator = 'Unix Makefiles' - - # 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) + pkg.generator = pkg.spec.variants['generator'].value + except KeyError: + pkg.generator = 'Make' if sys.platform != 'win32' else 'Ninja' + primary_generator = CMakePackage.generatorMap[pkg.generator] try: build_type = pkg.spec.variants['build_type'].value @@ -165,9 +167,11 @@ class CMakePackage(PackageBase): define = CMakePackage.define args = [ - '-G', generator, - define('CMAKE_INSTALL_PREFIX', pkg.prefix), + '-G', primary_generator, + define('CMAKE_INSTALL_PREFIX', pkg.prefix.replace('\\', '/')), define('CMAKE_BUILD_TYPE', build_type), + define('CMAKE_C_COMPILER:FILEPATH', pkg.compiler.cc.replace('\\', '/')), + define('CMAKE_CXX_COMPILER:FILEPATH', pkg.compiler.cxx.replace('\\', '/')) ] # CMAKE_INTERPROCEDURAL_OPTIMIZATION only exists for CMake >= 3.9 diff --git a/lib/spack/spack/directory_layout.py b/lib/spack/spack/directory_layout.py index bfe7077547..d7884423ce 100644 --- a/lib/spack/spack/directory_layout.py +++ b/lib/spack/spack/directory_layout.py @@ -6,6 +6,7 @@ import errno import glob import os +import posixpath import re import shutil import tempfile @@ -23,9 +24,9 @@ import spack.spec import spack.util.spack_json as sjson from spack.error import SpackError -default_projections = {'all': ('{architecture}/' - '{compiler.name}-{compiler.version}/' - '{name}-{version}-{hash}')} +default_projections = {'all': posixpath.join( + '{architecture}', '{compiler.name}-{compiler.version}', + '{name}-{version}-{hash}')} def _check_concrete(spec): diff --git a/lib/spack/spack/stage.py b/lib/spack/spack/stage.py index 2db705f8fa..83066abe9f 100644 --- a/lib/spack/spack/stage.py +++ b/lib/spack/spack/stage.py @@ -14,6 +14,7 @@ import shutil import stat import sys import tempfile +from sys import platform as _platform from typing import Dict # novm from six import iteritems, string_types @@ -41,6 +42,10 @@ import spack.util.pattern as pattern 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' @@ -50,12 +55,16 @@ stage_prefix = 'spack-stage-' def create_stage_root(path): # type: (str) -> None + """Create the stage root directory and ensure appropriate access perms.""" - assert path.startswith(os.path.sep) and len(path.strip()) > 1 + assert os.path.isabs(path) and len(path.strip()) > 1 err_msg = 'Cannot create stage root {0}: Access to {1} is denied' - user_uid = os.getuid() + if _platform != "win32": + user_uid = os.getuid() # type: ignore[attr-defined] + else: + user_uid = win32api.GetUserName() # Obtain lists of ancestor and descendant paths of the $user node, if any. group_paths, user_node, user_paths = partition_path(path, @@ -100,9 +109,17 @@ def create_stage_root(path): else: p_stat = os.stat(p) - if user_uid != p_stat.st_uid: + 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] + + if user_uid != owner_uid: tty.warn("Expected user {0} to own {1}, but it is owned by {2}" - .format(user_uid, p, p_stat.st_uid)) + .format(user_uid, p, owner_uid)) spack_src_subdir = os.path.join(path, _source_path_subdir) # When staging into a user-specified directory with `spack stage -p `, we need -- cgit v1.2.3-70-g09d2