Packaging of netlib-lapack for windows (#24993)

MSVC's internal CMake and Ninja now detected by spack external find and added to packages.yaml

Saving progress on packaging zlib for Windows

Fixing the shared CMake flag

* Loading Intel's ifx Fortran compiler into MSVC; if there are multiple
versions of MSVC installed and detected, ifx will only be placed into
the first block written in compilers.yaml. The version number of ifx can
be detected using MSVC's version flag (instead of /QV) by using
ignore_version_errors. This commit also provides support for detection
of Intel compilers in their own compiler block by adding ifx.exe to the
fc/f77_name blocks inside intel.py

* Giving CMake a Fortran compiler argument

* Adding patch file for removing duplicated mangling header for versions 3.9.1 and older; static and shared now successfully building on Windows

* Have netlib-lapack depend  on ninja@1.10

Co-authored-by: John R. Cary <cary@txcorp.com>
Co-authored-by: Jared Popelar <jpopelar@txcorp.com>

Making a default config.yaml for Windows

Small path length for build_stage

Provide more prerequisite details, mention default config.yaml

Killing an unnecessary setvars call

Replacing some lost changes, proofreading, updating windows-supported package list

Co-authored-by: John Parent <john.parent@kitware.com>
This commit is contained in:
Jared Popelar 2021-05-17 14:56:42 -06:00 committed by Peter Scheibel
parent 012758c179
commit 15ef85e161
11 changed files with 295 additions and 121 deletions

View File

@ -0,0 +1,5 @@
config:
locks: false
concretizer: original
build_stage::
- '~/.spack'

View File

@ -1523,11 +1523,9 @@ linux distro.
Spack On Windows Spack On Windows
---------------- ----------------
Windows support for Spack is currently under development. While this work is Windows support for Spack is currently under development. While this work is still in an early stage,
still in an early stage, it is currently possible to set up Spack and it is currently possible to set up Spack and perform a few operations on Windows. This section will guide
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.
you through the steps needed to install Spack and start running it on a
fresh Windows machine.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Step 1: Install prerequisites Step 1: Install prerequisites
@ -1536,48 +1534,82 @@ Step 1: Install prerequisites
To use Spack on Windows, you will need the following packages: To use Spack on Windows, you will need the following packages:
* Microsoft Visual Studio * Microsoft Visual Studio
* Intel Fortran (needed for some packages)
* Python * Python
* Git * Git
* Perl (needed for some packages)
* NASM (needed for some packages)
* CMake
""""""""""""""""""""""" """""""""""""""""""""""
Microsoft Visual Studio Microsoft Visual Studio
""""""""""""""""""""""" """""""""""""""""""""""
Microsoft Visual Studio provides the Windows C/C++ compiler that is Microsoft Visual Studio provides the Windows C/C++ compiler that is currently supported by Spack.
currently supported by Spack.
We require several specific components to be included in the Visual Studio We require several specific components to be included in the Visual Studio installation.
installation. One is the C/C++ toolset, which can be selected as "Desktop One is the C/C++ toolset, which can be selected as "Desktop development with C++" or "C++ build tools,"
development with C++" or "C++ build tools," depending on installation type depending on installation type (Professional, Build Tools, etc.) The other required component is
(Professional, Build Tools, etc.) The other required component is "C++ CMake tools for Windows," which can be selected from among the optional packages.
"C++ CMake tools for Windows," which can be selected from among the optional This provides CMake and Ninja for use during Spack configuration.
packages. This provides CMake and Ninja for use during Spack configuration.
If you already have Visual Studio installed, you can make sure these If you already have Visual Studio installed, you can make sure these components are installed by
components are installed by rerunning the installer. Next to your rerunning the installer. Next to your installation, select "Modify" and look at the
installation, select "Modify" and look at the "Installation details" pane on the right. "Installation details" pane on the right.
"""""""""""""
Intel Fortran
"""""""""""""
For Fortran-based packages on Windows, we strongly recommend Intel's oneAPI Fortran compilers.
The suite is free to download from Intel's website, located at
https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/fortran-compiler.html#gs.70t5tw.
The executable of choice for Spack will be Intel's Beta Compiler, ifx, which supports the classic
compiler's (ifort's) frontend and runtime libraries by using LLVM.
"""""" """"""
Python Python
"""""" """"""
As Spack is a Python-based package, an installation of Python will be needed As Spack is a Python-based package, an installation of Python will be needed to run it.
to run it. Python 3 can be downloaded and installed from the Windows Store, Python 3 can be downloaded and installed from the Windows Store, and will be automatically added
and will be automatically added to your ``PATH`` in this case. to your ``PATH`` in this case.
""" """
Git Git
""" """
A bash console and GUI can be downloaded from https://git-scm.com/downloads. A bash console and GUI can be downloaded from https://git-scm.com/downloads.
If you are unfamiliar with Git, there are a myriad of resources online to help
guide you through checking out repositories and switching development branches.
When given the option of adjusting your ``PATH``, choose the ``Git from the 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 command line and also from 3rd-party software`` option. This will automatically
update your ``PATH`` variable to include the ``git`` command. update your ``PATH`` variable to include the ``git`` command.
If you are unfamiliar with Git, there are a myriad of resources online to help """"
guide you through checking out repositories and switching development Perl
branches. """"
Perl is a flexible and feature-rich programming language that comes built-in
on Unix boxes but needs to be installed externally for Windows users. Fortunately,
you can find the most recent release at https://www.perl.org/get.html.
""""
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 Step 2: Install and setup Spack
@ -1629,31 +1661,19 @@ To configure Spack, first run the following command inside the Spack console:
spack compiler find spack compiler find
This creates a ``.spack`` directory in our home directory, along with a This creates a ``.spack`` directory in our home directory, along with a ``windows`` subdirectory
``windows`` subdirectory containing a ``compilers.yaml`` file. On a fresh containing a ``compilers.yaml`` file. On a fresh Windows install with the above packages
Windows install, the only compiler that should be found is your installation installed, this command should only detect Microsoft Visual Studio and the Intel Fortran
of Microsoft Visual Studio. compiler will be integrated within the first version of MSVC present in the ``compilers.yaml``
output.
We need to provide the ``config.yaml`` configuration by ourselves. This goes Spack provides a default ``config.yaml`` file for Windows that it will use unless overridden.
in the ``.spack\windows`` directory in your home directory. Open your text This file is located at ``etc\spack\defaults\windows\config.yaml``. You can read more on how to
editor of choice and enter the following lines for ``config.yaml``: do this and write your own configuration files in the :ref:`Configuration Files<configuration>` section of our
documentation. If you do this, pay particular attention to the ``build_stage`` block of the file
.. code-block:: yaml as this specifies the directory that will temporarily hold the source code for the packages to
be installed. This path name must be sufficiently short for compliance with cmd, otherwise you
config: will see build errors during installation (particularly with CMake) tied to long path names.
locks: false
install_tree:
root: $spack\opt\spack
projections:
all: '${ARCHITECTURE}\${COMPILERNAME}-${COMPILERVER}\${PACKAGE}-${VERSION}-${HASH}'
build_stage:
- ~/.spack/stage
(These settings are identical to those in the default ``config.yaml``
provided with your Spack checkout, except with forward slashes replaced by
backslashes for Windows compatibility.) It is important that all indentions
in .yaml files are done with spaces and not tabs, so take care when editing
one by hand.
For the ``packages.yaml`` file, there are two options. The first 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 and easiest choice is to use Spack to find installation on your system. In
@ -1668,10 +1688,9 @@ The ``spack external find <name>`` will find executables on your system
with the same name given. The command will store the items found in with the same name given. The command will store the items found in
``packages.yaml`` in the ``.spack\`` directory. ``packages.yaml`` in the ``.spack\`` directory.
Assuming the Spack found CMake and Ninja executables in the previous Assuming that the command found CMake and Ninja executables in the previous
step, continue to Step 4. If no executables were found, we will need to step, continue to Step 4. If no executables were found, we need to manually direct spack towards the CMake
direct spack towards the CMake and Ninja installations we set up with and Ninja installations we set up with Visual Studio. Therefore, your ``packages.yaml`` file will look something
Visual Studio. Therefore, your ``packages.yaml`` file will look something
like this, with possibly slight variants in the paths to CMake and Ninja: like this, with possibly slight variants in the paths to CMake and Ninja:
.. code-block:: yaml .. code-block:: yaml
@ -1688,27 +1707,18 @@ like this, with possibly slight variants in the paths to CMake and Ninja:
prefix: 'c:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja' prefix: 'c:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja'
buildable: False buildable: False
It is important to note that the version of your Ninja and CMake could
be different than what is shown here. If there is a difference, make sure
to use your version instead of the version listed above. Similiarly, if
you use a different version of Visual Studio ("Community" for example),
make sure the Professional part of the location is changed to your version.
The ``packages.yaml`` file should be placed inside either the ``.spack``
directory or the ``.spack\windows`` directory.
You can also use an separate installation of CMake if you have one and prefer You can also use an separate installation of CMake if you have one and prefer
to use it. If you don't have a path to Ninja analogous to the above, then to use it. If you don't have a path to Ninja analogous to the above, then you can
you can obtain it by running the Visual Studio Installer and following the obtain it by running the Visual Studio Installer and following the instructions
instructions at the start of this section. at the start of this section. Also note that .yaml files use spaces for indentation
and not tabs, so ensure that this is the case when editing one directly.
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
Step 4: Use Spack Step 4: Use Spack
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
Once the configuration is complete, it is time to give the installation a Once the configuration is complete, it is time to give the installation a test. Install a basic package though the
test. Install a basic package through the Spack console via: Spack console via:
.. code-block:: console .. code-block:: console
@ -1725,6 +1735,9 @@ packages known to work on Windows:
* abseil-cpp * abseil-cpp
* cpuinfo * cpuinfo
* glm * glm
* netlib-lapack (requires Intel Fortran)
* openssl
* zlib
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
For developers For developers

View File

@ -174,6 +174,10 @@ def _std_args(pkg):
define('CMAKE_CXX_COMPILER:FILEPATH', pkg.compiler.cxx.replace('\\', '/')) define('CMAKE_CXX_COMPILER:FILEPATH', pkg.compiler.cxx.replace('\\', '/'))
] ]
if pkg.compiler.fc is not None:
args.append(define('CMAKE_Fortran_COMPILER:FILEPATH',
pkg.compiler.fc.replace('\\', '/')))
# CMAKE_INTERPROCEDURAL_OPTIMIZATION only exists for CMake >= 3.9 # CMAKE_INTERPROCEDURAL_OPTIMIZATION only exists for CMake >= 3.9
if pkg.spec.satisfies('^cmake@3.9:'): if pkg.spec.satisfies('^cmake@3.9:'):
args.append(define('CMAKE_INTERPROCEDURAL_OPTIMIZATION', ipo)) args.append(define('CMAKE_INTERPROCEDURAL_OPTIMIZATION', ipo))

View File

@ -211,7 +211,6 @@ def find_compilers(path_hints=None):
for o in all_os_classes(): for o in all_os_classes():
search_paths = getattr(o, 'compiler_search_paths', default_paths) search_paths = getattr(o, 'compiler_search_paths', default_paths)
arguments.extend(arguments_to_detect_version_fn(o, search_paths)) arguments.extend(arguments_to_detect_version_fn(o, search_paths))
# Here we map the function arguments to the corresponding calls # Here we map the function arguments to the corresponding calls
tp = multiprocessing.pool.ThreadPool() tp = multiprocessing.pool.ThreadPool()
try: try:

View File

@ -3,6 +3,8 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import sys
from spack.compiler import Compiler, UnsupportedCompilerFlag from spack.compiler import Compiler, UnsupportedCompilerFlag
from spack.version import ver from spack.version import ver
@ -29,7 +31,14 @@ class Intel(Compiler):
PrgEnv = 'PrgEnv-intel' PrgEnv = 'PrgEnv-intel'
PrgEnv_compiler = 'intel' PrgEnv_compiler = 'intel'
if sys.platform == 'win32':
version_argument = '/QV'
else:
version_argument = '--version' version_argument = '--version'
if sys.platform == 'win32':
version_regex = r'([1-9][0-9]*\.[0-9]*\.[0-9]*)'
else:
version_regex = r'\((?:IFORT|ICC)\) ([^ ]+)' version_regex = r'\((?:IFORT|ICC)\) ([^ ]+)'
@property @property

View File

@ -8,6 +8,8 @@
import sys import sys
from typing import List # novm from typing import List # novm
import spack.operating_systems.windows_os
import spack.util.executable
from spack.compiler import Compiler from spack.compiler import Compiler
@ -19,20 +21,24 @@ class Msvc(Compiler):
cxx_names = ['cl.exe'] cxx_names = ['cl.exe']
# Subclasses use possible names of Fortran 77 compiler # Subclasses use possible names of Fortran 77 compiler
f77_names = [] # type: List[str] f77_names = ['ifx.exe'] # type: List[str]
# Subclasses use possible names of Fortran 90 compiler # Subclasses use possible names of Fortran 90 compiler
fc_names = [] # type: List[str] fc_names = ['ifx.exe'] # type: List[str]
# Named wrapper links within build_env_path # Named wrapper links within build_env_path
link_paths = {'cc': 'msvc/cl.exe', link_paths = {'cc': '',
'cxx': 'msvc/cl.exe', 'cxx': '',
'f77': '', 'f77': '',
'fc': ''} 'fc': ''}
#: Compiler argument that produces version information #: Compiler argument that produces version information
version_argument = '' version_argument = ''
# For getting ifx's version, call it with version_argument
# and ignore the error code
ignore_version_errors = [1]
#: Regex used to extract version from compiler's output #: Regex used to extract version from compiler's output
version_regex = r'([1-9][0-9]*\.[0-9]*\.[0-9]*)' version_regex = r'([1-9][0-9]*\.[0-9]*\.[0-9]*)'
@ -41,10 +47,15 @@ class Msvc(Compiler):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Msvc, self).__init__(*args, **kwargs) super(Msvc, self).__init__(*args, **kwargs)
self.vcvarsallfile = os.path.abspath( if os.getenv("ONEAPI_ROOT"):
# If this found, it sets all the vars
self.setvarsfile = os.path.join(
os.getenv("ONEAPI_ROOT"), "setvars.bat")
else:
self.setvarsfile = os.path.abspath(
os.path.join(self.cc, '../../../../../../..')) os.path.join(self.cc, '../../../../../../..'))
self.vcvarsallfile = os.path.join( self.setvarsfile = os.path.join(
self.vcvarsallfile, 'Auxiliary', 'Build', 'vcvarsall.bat') self.setvarsfile, 'Auxiliary', 'Build', 'vcvars64.bat')
@property @property
def verbose_flag(self): def verbose_flag(self):
@ -55,28 +66,60 @@ def pic_flag(self):
return "" return ""
def setup_custom_environment(self, pkg, env): def setup_custom_environment(self, pkg, env):
"""Set environment variables for MSVC using the Microsoft-provided """Set environment variables for MSVC using the
script.""" Microsoft-provided script."""
if sys.version_info[:2] > (2, 6): if sys.version_info[:2] > (2, 6):
# Capture output from batch script and DOS environment dump # Set the build environment variables for spack. Just using
# subprocess.call() doesn't work since that operates in its own
# environment which is destroyed (along with the adjusted variables)
# once the process terminates. So go the long way around: examine
# output, sort into dictionary, use that to make the build
# environment.
out = subprocess.check_output( # novermin out = subprocess.check_output( # novermin
'cmd /u /c "{0}" {1} && set'.format(self.vcvarsallfile, 'amd64'), 'cmd /u /c "{}" {} && set'.format(self.setvarsfile, 'amd64'),
stderr=subprocess.STDOUT) stderr=subprocess.STDOUT)
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
out = out.decode('utf-16le', errors='replace') out = out.decode('utf-16le', errors='replace') # novermin
else:
print("Cannot pull msvc compiler information in Python 2.6 or below")
# Process in to nice Python dictionary int_env = { # novermin
vc_env = { # novermin
key.lower(): value key.lower(): value
for key, _, value in for key, _, value in
(line.partition('=') for line in out.splitlines()) (line.partition('=') for line in out.splitlines())
if key and value if key and value
} }
# Request setting environment variables if 'path' in int_env:
if 'path' in vc_env: env.set_path('PATH', int_env['path'].split(';'))
env.set_path('PATH', vc_env['path'].split(';')) env.set_path('INCLUDE', int_env.get('include', '').split(';'))
env.set_path('INCLUDE', vc_env.get('include', '').split(';')) env.set_path('LIB', int_env.get('lib', '').split(';'))
env.set_path('LIB', vc_env.get('lib', '').split(';')) else:
# Should not this be an exception?
print("Cannot pull msvc compiler information in Python 2.6 or below")
# fc_version only loads the ifx compiler into the first MSVC stanza;
# if there are other versions of Microsoft VS installed and detected, they
# will only have cl.exe as the C/C++ compiler
@classmethod
def fc_version(cls, fc):
# We're using intel for the Fortran compilers, which exist if
# ONEAPI_ROOT is a meaningful variable
if os.getenv("ONEAPI_ROOT"):
try:
sps = spack.operating_systems.windows_os.WindowsOs.compiler_search_paths
except Exception:
print("sps not found.")
raise
try:
clp = spack.util.executable.which_string("cl", path=sps)
except Exception:
print("cl not found.")
raise
ver = cls.default_version(clp)
return ver
else:
return cls.default_version(fc)
@classmethod
def f77_version(cls, f77):
return cls.fc_version(f77)

View File

@ -16,6 +16,7 @@
import llnl.util.filesystem import llnl.util.filesystem
import llnl.util.tty import llnl.util.tty
import spack.operating_systems.windows_os as winOs
import spack.util.environment import spack.util.environment
from .common import ( from .common import (
@ -40,7 +41,18 @@ def executables_in_path(path_hints=None):
path_hints (list): list of paths to be searched. If None the list will be path_hints (list): list of paths to be searched. If None the list will be
constructed based on the PATH environment variable. constructed based on the PATH environment variable.
""" """
# build_environment.py::1013: If we're on a Windows box, run vswhere, steal the installationPath using
# windows_os.py logic, construct paths to CMake and Ninja, add to PATH
path_hints = path_hints or spack.util.environment.get_path('PATH') path_hints = path_hints or spack.util.environment.get_path('PATH')
if sys.platform == 'win32':
msvcPaths = winOs.WindowsOs.vsInstallPaths
msvcCMakePaths = [os.path.join(path, "Common7", "IDE", "CommonExtensions", "Microsoft", "CMake", "CMake", "bin")
for path in msvcPaths]
[path_hints.insert(0, path) for path in msvcCMakePaths]
msvcNinjaPaths = [os.path.join(path, "Common7", "IDE", "CommonExtensions", "Microsoft", "CMake", "Ninja")
for path in msvcPaths]
[path_hints.insert(0, path) for path in msvcNinjaPaths]
search_paths = llnl.util.filesystem.search_paths_for_executables(*path_hints) search_paths = llnl.util.filesystem.search_paths_for_executables(*path_hints)
path_to_exe = {} path_to_exe = {}

View File

@ -10,7 +10,6 @@
from spack.architecture import OperatingSystem from spack.architecture import OperatingSystem
from spack.version import Version from spack.version import Version
# FIXME: To get the actual Windows version, we need a python that runs # FIXME: To get the actual Windows version, we need a python that runs
# natively on Windows, not Cygwin. # natively on Windows, not Cygwin.
def windows_version(): def windows_version():
@ -22,21 +21,23 @@ def windows_version():
class WindowsOs(OperatingSystem): class WindowsOs(OperatingSystem):
"""This class represents the Windows operating system. This will be """This class represents the Windows operating system. This will be
auto detected using the python platform.win32_ver() once we have a auto detected using the python platform.win32_ver() once we have a
python setup that runs natively. The Windows platform will be represented python setup that runs natively. The Windows platform will be
using the major version operating system number, e.g. 10. represented using the major version operating system number, e.g.
10.
""" """
# Find MSVC directories using vswhere # Find MSVC directories using vswhere
compSearchPaths = [] compSearchPaths = []
vsInstallPaths = []
root = os.environ.get('ProgramFiles(x86)') or os.environ.get('ProgramFiles') root = os.environ.get('ProgramFiles(x86)') or os.environ.get('ProgramFiles')
if root: if root:
try: try:
extra_args = {} extra_args = {}
if sys.version_info[:3] >= (3, 6, 0): if sys.version_info[:3] >= (3, 6, 0):
extra_args = {'encoding': 'mbcs', 'errors': 'strict'} extra_args = {'encoding': 'mbcs', 'errors': 'strict'}
paths = subprocess.check_output([ paths = subprocess.check_output([ # novermin
os.path.join(root, "Microsoft Visual Studio", "Installer", os.path.join(root, "Microsoft Visual Studio",
"vswhere.exe"), "Installer", "vswhere.exe"),
"-prerelease", "-prerelease",
"-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
"-property", "installationPath", "-property", "installationPath",
@ -44,16 +45,22 @@ class WindowsOs(OperatingSystem):
], **extra_args).strip() ], **extra_args).strip()
if (3, 0) <= sys.version_info[:2] <= (3, 5): if (3, 0) <= sys.version_info[:2] <= (3, 5):
paths = paths.decode() paths = paths.decode()
msvcPaths = paths.split('\n') vsInstallPaths = paths.split('\n')
msvcPaths = [os.path.join(path, "VC", "Tools", "MSVC") msvcPaths = [os.path.join(path, "VC", "Tools", "MSVC")
for path in msvcPaths] for path in vsInstallPaths]
for p in msvcPaths: for p in msvcPaths:
compSearchPaths.extend( compSearchPaths.extend(
glob.glob(os.path.join(p, '*', 'bin', 'Hostx64', 'x64'))) glob.glob(os.path.join(p, '*', 'bin', 'Hostx64', 'x64')))
if os.getenv("ONEAPI_ROOT"):
comp_search_paths.extend(glob.glob(os.path.join(
str(os.getenv("ONEAPI_ROOT")),
'compiler', '*',
'windows', 'bin')))
except (subprocess.CalledProcessError, OSError, UnicodeDecodeError): except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
pass pass
if compSearchPaths: if compSearchPaths:
compiler_search_paths = compSearchPaths compiler_search_paths = compSearchPaths
# print(vsInstallPaths)
def __init__(self): def __init__(self):
super(WindowsOs, self).__init__('Windows10', '10') super(WindowsOs, self).__init__('Windows10', '10')

View File

@ -71,6 +71,7 @@ class NetlibLapack(CMakePackage):
depends_on('blas', when='+external-blas') depends_on('blas', when='+external-blas')
depends_on('netlib-xblas+fortran+plain_blas', when='+xblas') depends_on('netlib-xblas+fortran+plain_blas', when='+xblas')
depends_on('python@2.7:', type='test') depends_on('python@2.7:', type='test')
depends_on('ninja@1.10.0:', when='platform=windows')
# We need to run every phase twice in order to get static and shared # We need to run every phase twice in order to get static and shared
# versions of the libraries. When ~shared, we run the default # versions of the libraries. When ~shared, we run the default
@ -92,6 +93,11 @@ def patch(self):
'${CMAKE_CURRENT_SOURCE_DIR}/cmake/', '${CMAKE_CURRENT_SOURCE_DIR}/cmake/',
'CBLAS/CMakeLists.txt', string=True) 'CBLAS/CMakeLists.txt', string=True)
# Remove duplicate header file that gets generated during CMake shared
# builds: https://github.com/Reference-LAPACK/lapack/issues/583
if self.spec.satisfies('platform=windows @0:3.9.1'):
force_remove('LAPACKE/include/lapacke_mangling.h')
@property @property
def blas_libs(self): def blas_libs(self):
shared = True if '+shared' in self.spec else False shared = True if '+shared' in self.spec else False

View File

@ -89,6 +89,8 @@ class Openssl(Package): # Uses Fake Autotools, should subclass Package
description=('Use certificates from the ca-certificates-mozilla ' description=('Use certificates from the ca-certificates-mozilla '
'package, symlink system certificates, or none')) 'package, symlink system certificates, or none'))
variant('docs', default=False, description='Install docs and manpages') variant('docs', default=False, description='Install docs and manpages')
variant('shared', default=False, description="Build shared library version")
variant('dynamic', default=False, description="Link with MSVC's dynamic runtime library")
depends_on('zlib') depends_on('zlib')
depends_on('perl@5.14.0:', type=('build', 'test')) depends_on('perl@5.14.0:', type=('build', 'test'))
@ -134,6 +136,23 @@ def install(self, spec, prefix):
if self.spec.satisfies('%nvhpc os=centos7'): if self.spec.satisfies('%nvhpc os=centos7'):
options.append('-D__STDC_NO_ATOMICS__') options.append('-D__STDC_NO_ATOMICS__')
# Make a flag for shared library builds
shared_flag = ''
if spec.satisfies('~shared'):
shared_flag = 'no-shared'
# On Windows, we use perl for configuration and build through MSVC
# nmake.
if spec.satisfies('platform=windows'):
config = Executable('perl')
config('Configure',
'--prefix=%s' % prefix,
'--openssldir=%s' % join_path(prefix, 'etc', 'openssl'),
'CC=\"%s\"' % os.environ.get('SPACK_CC'),
'CXX=\"%s\"' % os.environ.get('SPACK_CXX'),
'%s' % shared_flag,
'VC-WIN64A')
else:
config = Executable('./config') config = Executable('./config')
config('--prefix=%s' % prefix, config('--prefix=%s' % prefix,
'--openssldir=%s' % join_path(prefix, 'etc', 'openssl'), '--openssldir=%s' % join_path(prefix, 'etc', 'openssl'),
@ -146,13 +165,35 @@ def install(self, spec, prefix):
# (e.g. gcc) will not accept them. # (e.g. gcc) will not accept them.
filter_file(r'-arch x86_64', '', 'Makefile') filter_file(r'-arch x86_64', '', 'Makefile')
if spec.satisfies('+dynamic'):
# This variant only makes sense for Windows
if spec.satisfies('platform=windows'):
filter_file(r'MT', 'MD', 'makefile')
else:
tty.warn("Dynamic runtime builds are only available for "
"Windows operating systems. Please disable "
"+dynamic to suppress this warning.")
if spec.satisfies('platform=windows'):
nmake = Executable('nmake')
nmake()
else:
make() make()
if self.run_tests: if self.run_tests:
if spec.satisfies('platform=windows'):
nmake = Executable('nmake')
nmake('test', parallel=False)
else:
make('test', parallel=False) # 'VERBOSE=1' make('test', parallel=False) # 'VERBOSE=1'
install_tgt = 'install' if self.spec.satisfies('+docs') else 'install_sw' install_tgt = 'install' if self.spec.satisfies('+docs') else 'install_sw'
# See https://github.com/openssl/openssl/issues/7466#issuecomment-432148137 # See https://github.com/openssl/openssl/issues/7466#issuecomment-432148137
if spec.satisfies('platform=windows'):
nmake = Executable('nmake')
nmake(install_tgt, parallel=False)
else:
make(install_tgt, parallel=False) make(install_tgt, parallel=False)
@run_after('install') @run_after('install')

View File

@ -6,7 +6,7 @@
# Although zlib comes with a configure script, it does not use Autotools # Although zlib comes with a configure script, it does not use Autotools
# The AutotoolsPackage causes zlib to fail to build with PGI # The AutotoolsPackage causes zlib to fail to build with PGI
class Zlib(Package): class Zlib(CMakePackage):
"""A free, general-purpose, legally unencumbered lossless """A free, general-purpose, legally unencumbered lossless
data-compression library. data-compression library.
""" """
@ -37,13 +37,45 @@ def libs(self):
['libz'], root=self.prefix, recursive=True, shared=shared ['libz'], root=self.prefix, recursive=True, shared=shared
) )
def cmake_args(self):
args = ['-DBUILD_SHARED_LIBS:BOOL=' +
('ON' if self._building_shared else 'OFF')]
return args
@property
def build_directory(self):
return join_path(self.stage.source_path,
'spack-build-shared' if self._building_shared
else 'spack-build-static')
def setup_build_environment(self, env): def setup_build_environment(self, env):
if '+pic' in self.spec: if '+pic' in self.spec:
env.append_flags('CFLAGS', self.compiler.cc_pic_flag) env.append_flags('CFLAGS', self.compiler.cc_pic_flag)
if '+optimize' in self.spec: if '+optimize' in self.spec:
env.append_flags('CFLAGS', '-O2') env.append_flags('CFLAGS', '-O2')
# Build, install, and check both static and shared versions of the
# libraries when +shared
@when('+shared platform=windows')
def cmake(self, spec, prefix):
for self._building_shared in (False, True):
super(Zlib, self).cmake(spec, prefix)
@when('+shared platform=windows')
def build(self, spec, prefix):
for self._building_shared in (False, True):
super(Zlib, self).build(spec, prefix)
@when('+shared platform=windows')
def check(self):
for self._building_shared in (False, True):
super(Zlib, self).check()
def install(self, spec, prefix): def install(self, spec, prefix):
if 'platform=windows' in self.spec and '+shared' in self.spec:
for self._building_shared in (False, True):
super(Zlib, self).install(spec, prefix)
else:
config_args = [] config_args = []
if '~shared' in spec: if '~shared' in spec:
config_args.append('--static') config_args.append('--static')
@ -53,3 +85,6 @@ def install(self, spec, prefix):
if self.run_tests: if self.run_tests:
make('check') make('check')
make('install') make('install')