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.
This commit is contained in:
Ben Cowan 2021-10-22 14:29:44 -04:00 committed by Peter Scheibel
parent d4d101f57e
commit a0164793cb
4 changed files with 50 additions and 25 deletions

View File

@ -524,6 +524,7 @@ def _set_variables_for_single_module(pkg, module):
m.configure = Executable('./configure') m.configure = Executable('./configure')
m.meson = Executable('meson') m.meson = Executable('meson')
# m.cmake = Executable('cmake')
m.cmake = Executable('cmake') m.cmake = Executable('cmake')
m.ctest = MakeExecutable('ctest', jobs) m.ctest = MakeExecutable('ctest', jobs)
@ -1136,7 +1137,8 @@ def child_fun():
try: try:
# Forward sys.stdin when appropriate, to allow toggling verbosity # 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_fd = os.dup(sys.stdin.fileno())
input_multiprocess_fd = MultiProcessFd(input_fd) input_multiprocess_fd = MultiProcessFd(input_fd)
@ -1144,6 +1146,7 @@ def child_fun():
target=_setup_pkg_and_run, target=_setup_pkg_and_run,
args=(serialized_pkg, function, kwargs, child_pipe, args=(serialized_pkg, function, kwargs, child_pipe,
input_multiprocess_fd)) input_multiprocess_fd))
p.start() p.start()
except InstallError as e: except InstallError as e:

View File

@ -8,6 +8,7 @@
import os import os
import platform import platform
import re import re
import sys
from typing import List # novm from typing import List # novm
import six import six
@ -17,7 +18,7 @@
import spack.build_environment import spack.build_environment
from spack.directives import conflicts, depends_on, variant 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 # Regex to extract the primary generator from the CMake generator
# string. # string.
@ -91,7 +92,16 @@ class CMakePackage(PackageBase):
#: #:
#: See https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html #: See https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html
#: for more information. #: 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 # https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
variant('build_type', default='RelWithDebInfo', variant('build_type', default='RelWithDebInfo',
@ -138,20 +148,12 @@ def std_cmake_args(self):
@staticmethod @staticmethod
def _std_args(pkg): def _std_args(pkg):
"""Computes the standard cmake arguments for a generic package""" """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 try:
valid_primary_generators = ['Unix Makefiles', 'Ninja'] pkg.generator = pkg.spec.variants['generator'].value
primary_generator = _extract_primary_generator(generator) except KeyError:
if primary_generator not in valid_primary_generators: pkg.generator = 'Make' if sys.platform != 'win32' else 'Ninja'
msg = "Invalid CMake generator: '{0}'\n".format(generator) primary_generator = CMakePackage.generatorMap[pkg.generator]
msg += "CMakePackage currently supports the following "
msg += "primary generators: '{0}'".\
format("', '".join(valid_primary_generators))
raise InstallError(msg)
try: try:
build_type = pkg.spec.variants['build_type'].value build_type = pkg.spec.variants['build_type'].value
@ -165,9 +167,11 @@ def _std_args(pkg):
define = CMakePackage.define define = CMakePackage.define
args = [ args = [
'-G', generator, '-G', primary_generator,
define('CMAKE_INSTALL_PREFIX', pkg.prefix), define('CMAKE_INSTALL_PREFIX', pkg.prefix.replace('\\', '/')),
define('CMAKE_BUILD_TYPE', build_type), 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 # CMAKE_INTERPROCEDURAL_OPTIMIZATION only exists for CMake >= 3.9

View File

@ -6,6 +6,7 @@
import errno import errno
import glob import glob
import os import os
import posixpath
import re import re
import shutil import shutil
import tempfile import tempfile
@ -23,8 +24,8 @@
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
from spack.error import SpackError from spack.error import SpackError
default_projections = {'all': ('{architecture}/' default_projections = {'all': posixpath.join(
'{compiler.name}-{compiler.version}/' '{architecture}', '{compiler.name}-{compiler.version}',
'{name}-{version}-{hash}')} '{name}-{version}-{hash}')}

View File

@ -14,6 +14,7 @@
import stat import stat
import sys import sys
import tempfile import tempfile
from sys import platform as _platform
from typing import Dict # novm from typing import Dict # novm
from six import iteritems, string_types from six import iteritems, string_types
@ -41,6 +42,10 @@
import spack.util.url as url_util import spack.util.url as url_util
from spack.util.crypto import bit_length, prefix_bits from spack.util.crypto import bit_length, prefix_bits
if _platform == "win32":
import win32api
import win32security
# The well-known stage source subdirectory name. # The well-known stage source subdirectory name.
_source_path_subdir = 'spack-src' _source_path_subdir = 'spack-src'
@ -50,12 +55,16 @@
def create_stage_root(path): def create_stage_root(path):
# type: (str) -> None # type: (str) -> None
"""Create the stage root directory and ensure appropriate access perms.""" """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' 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. # Obtain lists of ancestor and descendant paths of the $user node, if any.
group_paths, user_node, user_paths = partition_path(path, group_paths, user_node, user_paths = partition_path(path,
@ -100,9 +109,17 @@ def create_stage_root(path):
else: else:
p_stat = os.stat(p) 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}" 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) spack_src_subdir = os.path.join(path, _source_path_subdir)
# When staging into a user-specified directory with `spack stage -p <PATH>`, we need # When staging into a user-specified directory with `spack stage -p <PATH>`, we need