From 012758c1796577845a98981bd950ef9513d13a14 Mon Sep 17 00:00:00 2001 From: "lou.lawrence@kitware.com" Date: Fri, 8 Jan 2021 15:48:07 -0500 Subject: [PATCH] Windows: Create installer and environment * Add 'make-installer' command for Windows * Add '--bat' arg to env activate, env deactivate and unload commands * An equivalent script to setup-env on linux: spack_cmd.bat. This script has a wrapper to evaluate cd, load/unload, env activate/deactivate.(#21734) * Add spacktivate and config editor (#22049) * spack_cmd: will find python and spack on its own. It preferentially tries to use python on your PATH (#22414) * Ignore Windows python installer if found (#23134) * Bundle git in windows installer (#23597) * Add Windows section to Getting Started document (#23131), (#23295), (#24240) Co-authored-by: Stephen Crowell Co-authored-by: lou.lawrence@kitware.com Co-authored-by: Betsy McPhail Co-authored-by: Jared Popelar Co-authored-by: Ben Cowan Update Installer CI Co-authored-by: John Parent --- .gitignore | 5 + lib/spack/docs/getting_started.rst | 218 +++++++++++++++++ lib/spack/spack/cmd/common/__init__.py | 4 + lib/spack/spack/cmd/env.py | 6 + lib/spack/spack/cmd/installer/CMakeLists.txt | 116 +++++++++ lib/spack/spack/cmd/installer/README.md | 85 +++++++ .../spack/cmd/installer/banner493x58.bmp | Bin 0 -> 29846 bytes lib/spack/spack/cmd/installer/bundle.wxs.in | 23 ++ lib/spack/spack/cmd/installer/patch.xml | 10 + .../spack/cmd/installer/scripts/haspywin.py | 20 ++ .../spack/cmd/installer/scripts/spack.bat | 223 ++++++++++++++++++ lib/spack/spack/cmd/installer/spack.wxs.in | 48 ++++ lib/spack/spack/cmd/installer/spack_cmd.bat | 63 +++++ lib/spack/spack/cmd/load.py | 3 + lib/spack/spack/cmd/make_installer.py | 137 +++++++++++ lib/spack/spack/cmd/unload.py | 3 + lib/spack/spack/environment/shell.py | 10 + lib/spack/spack/util/editor.py | 2 +- lib/spack/spack/util/environment.py | 27 ++- share/spack/spack-completion.bash | 11 +- 20 files changed, 1002 insertions(+), 12 deletions(-) create mode 100644 lib/spack/spack/cmd/installer/CMakeLists.txt create mode 100644 lib/spack/spack/cmd/installer/README.md create mode 100644 lib/spack/spack/cmd/installer/banner493x58.bmp create mode 100644 lib/spack/spack/cmd/installer/bundle.wxs.in create mode 100644 lib/spack/spack/cmd/installer/patch.xml create mode 100644 lib/spack/spack/cmd/installer/scripts/haspywin.py create mode 100644 lib/spack/spack/cmd/installer/scripts/spack.bat create mode 100644 lib/spack/spack/cmd/installer/spack.wxs.in create mode 100644 lib/spack/spack/cmd/installer/spack_cmd.bat create mode 100644 lib/spack/spack/cmd/make_installer.py diff --git a/.gitignore b/.gitignore index 68f83ea38d..6a816e5531 100644 --- a/.gitignore +++ b/.gitignore @@ -269,6 +269,11 @@ local.properties # CDT-specific (C/C++ Development Tooling) .cproject +# VSCode files +.vs +.vscode +.devcontainer + # CDT- autotools .autotools diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst index cb2aa09fb9..353d97bf3f 100644 --- a/lib/spack/docs/getting_started.rst +++ b/lib/spack/docs/getting_started.rst @@ -1516,3 +1516,221 @@ To ensure that Spack does not autodetect the Cray programming environment, unset the environment variable ``MODULEPATH``. This will cause Spack to treat a linux container on a Cray system as a base linux distro. + +.. _windows_support: + +---------------- +Spack On Windows +---------------- + +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. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Step 1: Install prerequisites +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To use Spack on Windows, you will need the following packages: + +* Microsoft Visual Studio +* Python +* Git + +""""""""""""""""""""""" +Microsoft Visual Studio +""""""""""""""""""""""" + +Microsoft Visual Studio provides the Windows C/C++ compiler that is +currently supported by Spack. + +We require several specific components to be included in the Visual Studio +installation. One is the C/C++ toolset, which can be selected as "Desktop +development with C++" or "C++ build tools," depending on installation type +(Professional, Build Tools, etc.) The other required component is +"C++ CMake tools for Windows," which can be selected from among the optional +packages. This provides CMake and Ninja for use during Spack configuration. + +If you already have Visual Studio installed, you can make sure these +components are installed by rerunning the installer. Next to your +installation, select "Modify" and look at the "Installation details" pane on the right. + +"""""" +Python +"""""" + +As Spack is a Python-based package, an installation of Python will be needed +to run it. Python 3 can be downloaded and installed from the Windows Store, +and will be automatically added to your ``PATH`` in this case. + +""" +Git +""" + +A bash console and GUI can be downloaded from https://git-scm.com/downloads. + +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. + +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. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Step 2: Install and setup Spack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We are now ready to get the Spack environment set up on our machine. We +begin by creating a top-level directory to do our work in: we will call +it ``spack_install`` in this tutorial. Inside this directory, use Git to +clone the Spack repo, hosted at https://github.com/spack/spack.git. + +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. Then navigate to +``lib\spack\spack\cmd\installer`` and copy the ``scripts`` directory and +``spack_cmd.bat`` up to the top-level ``spack_install`` directory. In a +Windows console, you can do both of these things by executing the following +commands from the ``spack_install`` level: + +.. code-block:: console + + xcopy lib\spack\spack\cmd\installer\scripts\ scripts\ + xcopy lib\spack\spack\cmd\installer\spack_cmd.bat . + +Your file structure should look like this after following the above +steps: + +.. code-block:: console + + spack_install + |--------spack + |--------scripts + |--------spack_cmd.bat + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Step 3: Run and configure Spack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To use Spack, run ``spack_cmd.bat`` (you may need to Run as Administrator). +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 configure Spack, first run the following command inside the Spack console: + +.. code-block:: console + + spack compiler find + +This creates a ``.spack`` directory in our home directory, along with a +``windows`` subdirectory containing a ``compilers.yaml`` file. On a fresh +Windows install, the only compiler that should be found is your installation +of Microsoft Visual Studio. + +We need to provide the ``config.yaml`` configuration by ourselves. This goes +in the ``.spack\windows`` directory in your home directory. Open your text +editor of choice and enter the following lines for ``config.yaml``: + +.. code-block:: yaml + + config: + 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 +and easiest choice is to use Spack to find installation on your system. In +the Spack terminal, run the following commands: + +.. code-block:: console + + spack external find cmake + spack external find ninja + +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. + +Assuming the Spack found CMake and Ninja executables in the previous +step, continue to Step 4. If no executables were found, we will need to +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: + +.. code-block:: yaml + + packages: + cmake: + externals: + - spec: cmake@3.19 + prefix: 'c:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake' + buildable: False + ninja: + externals: + - spec: ninja@1.8.2 + prefix: 'c:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja' + 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 +to use it. If you don't have a path to Ninja analogous to the above, then +you can obtain it by running the Visual Studio Installer and following the +instructions at the start of this section. + + +^^^^^^^^^^^^^^^^^ +Step 4: Use Spack +^^^^^^^^^^^^^^^^^ + +Once the configuration is complete, it is time to give the installation a +test. Install a basic package through the Spack console via: + +.. code-block:: console + + spack install cpuinfo + +""""""""""""""""""""""""""" +Windows Compatible Packages +""""""""""""""""""""""""""" + +Many Spack packages are not currently compatible with Windows, due to Unix +dependencies or incompatible build tools like autoconf. Here are several +packages known to work on Windows: + +* abseil-cpp +* cpuinfo +* glm + +^^^^^^^^^^^^^^ +For developers +^^^^^^^^^^^^^^ + +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. diff --git a/lib/spack/spack/cmd/common/__init__.py b/lib/spack/spack/cmd/common/__init__.py index 9d35aa8f3b..f4d7a57dd3 100644 --- a/lib/spack/spack/cmd/common/__init__.py +++ b/lib/spack/spack/cmd/common/__init__.py @@ -35,6 +35,9 @@ def shell_init_instructions(cmd, equivalent): color.colorize("@*c{For fish:}"), " source %s/setup-env.fish" % spack.paths.share_path, "", + color.colorize("@*c{For Windows batch:}"), + " source %s/spack_cmd.bat" % spack.paths.share_path, + "", "Or, if you do not want to use shell support, run " + ( "one of these" if shell_specific else "this") + " instead:", "", @@ -45,6 +48,7 @@ def shell_init_instructions(cmd, equivalent): equivalent.format(sh_arg="--sh ") + " # bash/zsh/sh", equivalent.format(sh_arg="--csh ") + " # csh/tcsh", equivalent.format(sh_arg="--fish") + " # fish", + equivalent.format(sh_arg="--bat ") + " # batch" ] else: msg += [" " + equivalent] diff --git a/lib/spack/spack/cmd/env.py b/lib/spack/spack/cmd/env.py index 5e2bc03d7a..8583fde8ca 100644 --- a/lib/spack/spack/cmd/env.py +++ b/lib/spack/spack/cmd/env.py @@ -60,6 +60,9 @@ def env_activate_setup_parser(subparser): shells.add_argument( '--fish', action='store_const', dest='shell', const='fish', help="print fish commands to activate the environment") + shells.add_argument( + '--bat', action='store_const', dest='shell', const='bat', + help="print bat commands to activate the environment") view_options = subparser.add_mutually_exclusive_group() view_options.add_argument( @@ -173,6 +176,9 @@ def env_deactivate_setup_parser(subparser): shells.add_argument( '--fish', action='store_const', dest='shell', const='fish', help="print fish commands to activate the environment") + shells.add_argument( + '--bat', action='store_const', dest='shell', const='bat', + help="print bat commands to activate the environment") def env_deactivate(args): diff --git a/lib/spack/spack/cmd/installer/CMakeLists.txt b/lib/spack/spack/cmd/installer/CMakeLists.txt new file mode 100644 index 0000000000..fe418cf337 --- /dev/null +++ b/lib/spack/spack/cmd/installer/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required (VERSION 3.13) +project(spack_installer NONE) + +set(PYTHON_VERSION "3.9.0" CACHE STRING "Version of Python to build.") +set(PY_DOWNLOAD_LINK "https://www.paraview.org/files/dependencies") +set(PY_FILENAME "Python-${PYTHON_VERSION}-win64.tar.xz") +set(PYTHON_DIR "Python-${PYTHON_VERSION}") + +if (SPACK_VERSION) + set(SPACK_DL "https://github.com/spack/spack/releases/download/v${SPACK_VERSION}") + set(SPACK_FILENAME "spack-${SPACK_VERSION}.tar.gz") + set(SPACK_DIR "spack-${SPACK_VERSION}") + + # SPACK DOWLOAD AND EXTRACTION----------------------------------- + file(DOWNLOAD "${SPACK_DL}/${SPACK_FILENAME}" + "${CMAKE_CURRENT_BINARY_DIR}/${SPACK_FILENAME}" + STATUS download_status + ) + list(GET download_status 0 res) + if(res) + list(GET download_status 1 err) + message(FATAL_ERROR "Failed to download ${SPACK_FILENAME} ${err}") + endif() + message(STATUS "Successfully downloaded ${SPACK_FILENAME}") + + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xfz + "${CMAKE_CURRENT_BINARY_DIR}/${SPACK_FILENAME}" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + RESULT_VARIABLE res) + if(NOT res EQUAL 0) + message(FATAL_ERROR "Extraction of ${SPACK_FILENAME} failed.") + endif() + message(STATUS "Extracted ${SPACK_DIR}") + SET(SPACK_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/${SPACK_DIR}") +elseif(SPACK_SOURCE) + get_filename_component(SPACK_DIR ${SPACK_SOURCE} NAME) +else() + message(FATAL_ERROR "Must specify SPACK_VERSION or SPACK_SOURCE") +endif() + + +# GIT DOWNLOAD---------------------------------------------------- +set(GIT_FILENAME "Git-2.31.1-64-bit.exe") +file(DOWNLOAD "https://github.com/git-for-windows/git/releases/download/v2.31.1.windows.1/Git-2.31.1-64-bit.exe" + "${CMAKE_CURRENT_BINARY_DIR}/${GIT_FILENAME}" + STATUS download_status + EXPECTED_HASH "SHA256=c43611eb73ad1f17f5c8cc82ae51c3041a2e7279e0197ccf5f739e9129ce426e" +) +list(GET download_status 0 res) +if(res) + list(GET download_status 1 err) + message(FATAL_ERROR "Failed to download ${GIT_FILENAME} ${err}") +endif() +message(STATUS "Successfully downloaded ${GIT_FILENAME}") + + +# PYTHON DOWLOAD AND EXTRACTION----------------------------------- +file(DOWNLOAD "${PY_DOWNLOAD_LINK}/${PY_FILENAME}" + "${CMAKE_CURRENT_BINARY_DIR}/${PY_FILENAME}" + STATUS download_status + EXPECTED_HASH "SHA256=f6aeebc6d1ff77418678ed5612b64ce61be6bc9ef3ab9c291ac557abb1783420" +) +list(GET download_status 0 res) +if(res) + list(GET download_status 1 err) + message(FATAL_ERROR "Failed to download ${PY_FILENAME} ${err}") +endif() +message(STATUS "Successfully downloaded ${PY_FILENAME}") + +execute_process(COMMAND ${CMAKE_COMMAND} -E tar xfz + "${CMAKE_CURRENT_BINARY_DIR}/${PY_FILENAME}" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + RESULT_VARIABLE res) +if(NOT res EQUAL 0) + message(FATAL_ERROR "Extraction of ${PY_FILENAME} failed.") +endif() +message(STATUS "Extracted ${PY_FILENAME}.") + +# license must be a .txt or .rtf file +configure_file("${SPACK_LICENSE}" "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.rtf" COPYONLY) + + +#INSTALLATION COMMANDS--------------------------------------------------- +install(DIRECTORY "${SPACK_SOURCE}/" + DESTINATION "${SPACK_DIR}") +install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python-${PYTHON_VERSION}-win64/" + DESTINATION "${PYTHON_DIR}") +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/scripts/" DESTINATION "scripts") +#install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/spack_cmd.bat/" DESTINATION ".") + +# CPACK Installer Instructions +set(CPACK_PACKAGE_NAME "Spack") +set(CPACK_PACKAGE_VENDOR "Lawrence Livermore National Laboratories") +set(CPACK_PACKAGE_VERSION "0.16.0") +set(CPACK_PACKAGE_DESCRIPTION "A flexible package manager designed to support multiple versions, configurations, platforms, and compilers.") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://spack.io") +set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}") +set(CPACK_PACKAGE_ICON "${SPACK_LOGO}") +set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.rtf") +#set(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_CURRENT_SOURCE_DIR}/NOTICE") +# WIX options (the default) +set(CPACK_GENERATOR "WIX") +set(CPACK_WIX_PRODUCT_ICON "${SPACK_LOGO}") +set(CPACK_WIX_UI_BANNER "${CMAKE_CURRENT_SOURCE_DIR}/banner493x58.bmp") +set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/patch.xml") +set(CPACK_WIX_UPGRADE_GUID "D2C703E4-721D-44EC-8016-BCB96BB64E0B") +set(CPACK_WIX_SKIP_PROGRAM_FOLDER TRUE) + +# Set full path to icon, shortcut in spack.wxs +set(SPACK_SHORTCUT "${CMAKE_CURRENT_SOURCE_DIR}/spack_cmd.bat") +configure_file("spack.wxs.in" "${CMAKE_CURRENT_BINARY_DIR}/spack.wxs") +configure_file("bundle.wxs.in" "${CMAKE_CURRENT_BINARY_DIR}/bundle.wxs") +set(CPACK_WIX_EXTRA_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/spack.wxs") + +include(CPack) diff --git a/lib/spack/spack/cmd/installer/README.md b/lib/spack/spack/cmd/installer/README.md new file mode 100644 index 0000000000..602c594f09 --- /dev/null +++ b/lib/spack/spack/cmd/installer/README.md @@ -0,0 +1,85 @@ +This README is a guide for creating a Spack installer for Windows using the +``make-installer`` command. The installer is an executable file that users +can run to install Spack like any other Windows binary. + +Before proceeding, follow the setup instructions in Steps 1 and 2 of +[Getting Started on Windows](https://spack.readthedocs.io/en/latest/getting_started.html#windows_support). + +# Step 1: Install prerequisites + +The only additional prerequisite for making the installer is Wix. Wix is a +utility used for .msi creation and can be downloaded and installed at +https://wixtoolset.org/releases/. The Visual Studio extensions are not +necessary. + +# Step 2: Make the installer + +To use Spack, run ``spack_cmd.bat``. This will provide a Windows command +prompt with an environment properly set up with Spack and its prerequisites. + +Ensure that Python and CMake are on your PATH. If needed, you may add the +CMake executable provided by Visual Studio to your path, which will look +something like: + +``C:\Program Files (x86)\Microsoft Visual Studio\\\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake`` + +**IMPORTANT**: If you use Tab to complete any part of this path, the console +will automatically add quotation marks to the start and the end since it will +see the spaces and want to parse the whole of it as a string. This is +incorrect for our purposes so before submitting the command, ensure that the +quotes are removed. You will encounter configuration errors if you fail to do +this. + +There are two ways to create the installer using Spack's ``make-installer`` +command. The recommended method is to build the installer using a local +checkout of Spack source (release or development), using the +`-s` flag to specify the directory where the local checkout is. For +example, if the local checkout is in a directory called ``spack-develop`` +and want to generate an installer with the source there, you can use: + +``spack make-installer -s spack-develop tmp`` + +Both the Spack source directory (e.g. ``spack-develop``) and installer +destination directory (e.g. ``tmp``) may be an absolute path or relative to +the current working directory. The entire contents of the specified +directory will be included in the installer (e.g. .git files or local +changes). + +Alternatively, if you would like to create an installer from a release version +of Spack, say, 0.16.0, and store it in ``tmp``, you can use the following +command: + +``spack make-installer -v 0.16.0 tmp`` + +**IMPORTANT**: Windows features are not currently supported in Spack's +official release branches, so an installer created using this method will +*not* run on Windows. + +Regardless of your method, a file called ``Spack.exe`` will be created +inside the destination directory. This executable bundles the Spack installer +(``Spack.msi`` also located in destination directory) and the git installer. + +# Step 3: Run the installer + +After accepting the terms of service, select where on your computer you would +like Spack installed, and after a few minutes Spack, Python and git will be +installed and ready for use. + +**IMPORTANT**: To avoid permissions issues, it is recommended to select an +install location other than ``C:\Program Files``. + +**IMPORTANT**: There is a specific option that must be chosen when letting Git +install. 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. +Certain Spack commands expect ``git`` to be part of the ``PATH``. If this step +is not performed properly, certain Spack comands will not work. + +If your Spack installation needs to be modified, repaired, or uninstalled, +you can do any of these things by rerunning ``Spack.exe``. + +Running the installer creates a shortcut on your desktop that, when +launched, will run ``spack_cmd.bat`` and launch a console with its initial +directory being wherever Spack was installed on your computer. If Python is +found on your PATH, that will be used. If not, the Python included with the +installer will be used when running Spack. diff --git a/lib/spack/spack/cmd/installer/banner493x58.bmp b/lib/spack/spack/cmd/installer/banner493x58.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e7ebb2d3b9556d6a05f50adaef88e9f5a1c31a26 GIT binary patch literal 29846 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 literal 0 HcmV?d00001 diff --git a/lib/spack/spack/cmd/installer/bundle.wxs.in b/lib/spack/spack/cmd/installer/bundle.wxs.in new file mode 100644 index 0000000000..6818044651 --- /dev/null +++ b/lib/spack/spack/cmd/installer/bundle.wxs.in @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/lib/spack/spack/cmd/installer/patch.xml b/lib/spack/spack/cmd/installer/patch.xml new file mode 100644 index 0000000000..1093b782b7 --- /dev/null +++ b/lib/spack/spack/cmd/installer/patch.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/lib/spack/spack/cmd/installer/scripts/haspywin.py b/lib/spack/spack/cmd/installer/scripts/haspywin.py new file mode 100644 index 0000000000..ea08e74d41 --- /dev/null +++ b/lib/spack/spack/cmd/installer/scripts/haspywin.py @@ -0,0 +1,20 @@ +# 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 subprocess +import sys + + +def getpywin(): + try: + import win32con # noqa + except ImportError: + subprocess.check_call( + [sys.executable, "-m", "pip", "-q", "install", "--upgrade", "pip"]) + subprocess.check_call( + [sys.executable, "-m", "pip", "-q", "install", "pywin32"]) + + +if __name__ == '__main__': + getpywin() diff --git a/lib/spack/spack/cmd/installer/scripts/spack.bat b/lib/spack/spack/cmd/installer/scripts/spack.bat new file mode 100644 index 0000000000..3b6b7905a4 --- /dev/null +++ b/lib/spack/spack/cmd/installer/scripts/spack.bat @@ -0,0 +1,223 @@ +:: 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) +::####################################################################### +:: +:: This file is part of Spack and sets up the spack environment for batch, +:: This includes environment modules and lmod support, +:: and it also puts spack in your path. The script also checks that at least +:: module support exists, and provides suggestions if it doesn't. Source +:: it like this: +:: +:: . /path/to/spack/install/spack_cmd.bat +:: +@echo off + +set spack=%SPACK_ROOT%\bin\spack + +::####################################################################### +:: This is a wrapper around the spack command that forwards calls to +:: 'spack load' and 'spack unload' to shell functions. This in turn +:: allows them to be used to invoke environment modules functions. +:: +:: 'spack load' is smarter than just 'load' because it converts its +:: arguments into a unique Spack spec that is then passed to module +:: commands. This allows the user to use packages without knowing all +:: their installation details. +:: +:: e.g., rather than requiring a full spec for libelf, the user can type: +:: +:: spack load libelf +:: +:: This will first find the available libelf module file and use a +:: matching one. If there are two versions of libelf, the user would +:: need to be more specific, e.g.: +:: +:: spack load libelf@0.8.13 +:: +:: This is very similar to how regular spack commands work and it +:: avoids the need to come up with a user-friendly naming scheme for +:: spack module files. +::####################################################################### + +:_sp_shell_wrapper +set "_sp_flags=" +set "_sp_args=" +set "_sp_subcommand=" +setlocal enabledelayedexpansion +:: commands have the form '[flags] [subcommand] [args]' +:: flags will always start with '-', e.g. --help or -V +:: subcommands will never start with '-' +:: everything after the subcommand is an arg +for %%x in (%*) do ( + set t="%%~x" + if "!t:~0,1!" == "-" ( + if defined _sp_subcommand ( + :: We already have a subcommand, processing args now + set "_sp_args=!_sp_args! !t!" + ) else ( + set "_sp_flags=!_sp_flags! !t!" + shift + ) + ) else if not defined _sp_subcommand ( + set "_sp_subcommand=!t!" + shift + ) else ( + set "_sp_args=!_sp_args! !t!" + shift + ) +) + +:: --help, -h and -V flags don't require further output parsing. +:: If we encounter, execute and exit +if defined _sp_flags ( + if NOT "%_sp_flags%"=="%_sp_flags:-h=%" ( + python "%spack%" %_sp_flags% + exit /B 0 + ) else if NOT "%_sp_flags%"=="%_sp_flags:--help=%" ( + python "%spack%" %_sp_flags% + exit /B 0 + ) else if NOT "%_sp_flags%"=="%_sp_flags:-V=%" ( + python "%spack%" %_sp_flags% + exit /B 0 + ) +) +:: pass parsed variables outside of local scope. Need to do +:: this because delayedexpansion can only be set by setlocal +echo %_sp_flags%>flags +echo %_sp_args%>args +echo %_sp_subcommand%>subcmd +endlocal +set /p _sp_subcommand= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/spack/spack/cmd/installer/spack_cmd.bat b/lib/spack/spack/cmd/installer/spack_cmd.bat new file mode 100644 index 0000000000..a6eede3441 --- /dev/null +++ b/lib/spack/spack/cmd/installer/spack_cmd.bat @@ -0,0 +1,63 @@ +@ECHO OFF +setlocal EnableDelayedExpansion +:: (c) 2021 Lawrence Livermore National Laboratory +:: To use this file independently of Spack's installer, please copy this file, and the +:: 'scripts' directory, to be adjacent to your spack directory. You must have python on +:: your path for Spack to locate it. +:: source_dir -------- spack +:: |--- scripts +:: |--- spack_cmd.bat +pushd %~dp0 +set spackinstdir=%CD% +popd + +:: Check if Python is on the PATH +(for /f "delims=" %%F in ('where python.exe') do (set python_pf_ver=%%F) ) 2> NUL + +if not defined python_pf_ver ( + :: If not, look for Python from the Spack installer + :get_builtin + (for /f "tokens=*" %%g in ('dir /b /a:d "!spackinstdir!\Python*"') do ( + set python_ver=%%g)) 2> NUL + + if not defined python_ver ( + echo Python was not found on your system. + echo Please install Python or add Python to your PATH. + ) else ( + set py_path=!spackinstdir!\!python_ver! + set py_exe=!py_path!\python.exe + ) + goto :exitpoint +) else ( + :: Python is already on the path + set py_exe=!python_pf_ver! + (for /F "tokens=* USEBACKQ" %%F in ( + `!py_exe! --version`) do (set "output=%%F")) 2>NUL + if not "!output:Microsoft Store=!"=="!output!" goto :get_builtin + goto :exitpoint +) +:exitpoint + + +for /f "tokens=*" %%g in ('dir /b /a:d "%spackinstdir%\spack*"') do (set spack_ver=%%g) +set "SPACK_ROOT=%spackinstdir%\%spack_ver%" + +set "PATH=%spackinstdir%\scripts\;%PATH%" +if defined py_path ( + set "PATH=%py_path%;%PATH%" +) + +if defined py_exe ( + "%py_exe%" "%spackinstdir%\scripts\haspywin.py" + "%py_exe%" "%SPACK_ROOT%\bin\spack" external find python >NUL +) + +set "EDITOR=notepad" + +DOSKEY spacktivate=spack env activate $* + +@echo ********************************************************************** +@echo ** Spack Package Manager +@echo ********************************************************************** + +%comspec% /k diff --git a/lib/spack/spack/cmd/load.py b/lib/spack/spack/cmd/load.py index 4ecde81fb7..64ae08930c 100644 --- a/lib/spack/spack/cmd/load.py +++ b/lib/spack/spack/cmd/load.py @@ -33,6 +33,9 @@ def setup_parser(subparser): shells.add_argument( '--fish', action='store_const', dest='shell', const='fish', help="print fish commands to load the package") + shells.add_argument( + '--bat', action='store_const', dest='shell', const='bat', + help="print bat commands to load the package") subparser.add_argument( '--first', diff --git a/lib/spack/spack/cmd/make_installer.py b/lib/spack/spack/cmd/make_installer.py new file mode 100644 index 0000000000..6ddb049b8d --- /dev/null +++ b/lib/spack/spack/cmd/make_installer.py @@ -0,0 +1,137 @@ +# 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 os +import posixpath +import subprocess +import sys + +import spack.paths +import spack.util.executable +from spack.spec import Spec + +description = "generate Windows installer" +section = "admin" +level = "long" + + +def txt_to_rtf(file_path): + rtf_header = """{{\\rtf1\\ansi\\deff0\\nouicompat + {{\\fonttbl{{\\f0\\fnil\\fcharset0 Courier New;}}}} + {{\\colortbl ;\\red0\\green0\\blue255;}} + {{\\*\\generator Riched20 10.0.19041}}\\viewkind4\\uc1 + \\f0\\fs22\\lang1033 + {} + }} + """ + + def line_to_rtf(str): + return str.replace("\n", "\\par") + contents = "" + with open(file_path, "r+") as f: + for line in f.readlines(): + contents += line_to_rtf(line) + return rtf_header.format(contents) + + +def setup_parser(subparser): + spack_source_group = subparser.add_mutually_exclusive_group(required=True) + spack_source_group.add_argument( + '-v', '--spack_version', default="", + help='download given spack version e.g. 0.16.0') + spack_source_group.add_argument( + '-s', '--spack_source', default="", + help='full path to spack source') + + subparser.add_argument( + '-g', '--git-installer-verbosity', default="", + choices=set(['SILENT', 'VERYSILENT']), + help="Level of verbosity provided by bundled Git Installer.\ + Default is fully verbose", + required=False, action='store', dest="git_verbosity" + ) + + subparser.add_argument( + 'output_dir', help="output directory") + + +def make_installer(parser, args): + """ + Use CMake to generate WIX installer in newly created build directory + """ + if sys.platform == 'win32': + output_dir = args.output_dir + cmake_spec = Spec('cmake') + cmake_spec.concretize() + cmake_path = os.path.join(cmake_spec.prefix, "bin", "cmake.exe") + cpack_path = os.path.join(cmake_spec.prefix, "bin", "cpack.exe") + spack_source = args.spack_source + git_verbosity = "" + if args.git_verbosity: + git_verbosity = "/" + args.git_verbosity + + if spack_source: + if not os.path.exists(spack_source): + print("%s does not exist" % spack_source) + return + else: + if not os.path.isabs(spack_source): + spack_source = posixpath.abspath(spack_source) + spack_source = spack_source.replace('\\', '/') + + spack_version = args.spack_version + + here = os.path.dirname(os.path.abspath(__file__)) + source_dir = os.path.join(here, "installer") + posix_root = spack.paths.spack_root.replace('\\', '/') + spack_license = posixpath.join(posix_root, "LICENSE-APACHE") + rtf_spack_license = txt_to_rtf(spack_license) + spack_license = posixpath.join(source_dir, "LICENSE.rtf") + + with open(spack_license, 'w') as rtf_license: + written = rtf_license.write(rtf_spack_license) + if written == 0: + raise RuntimeError("Failed to generate properly formatted license file") + spack_logo = posixpath.join(posix_root, + "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: + print("Failed to generate installer") + return subprocess.CalledProcessError.returncode + + try: + subprocess.check_call( + '"%s" --config "%s/CPackConfig.cmake" -B "%s/"' + % (cpack_path, output_dir, output_dir), + shell=True) + except subprocess.CalledProcessError: + print("Failed to generate installer") + return subprocess.CalledProcessError.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: + print("Failed to generate installer chain") + return subprocess.CalledProcessError.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: + print("Failed to generate installer chain") + return subprocess.CalledProcessError.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/cmd/unload.py b/lib/spack/spack/cmd/unload.py index 68823b39fe..e1b926a6ea 100644 --- a/lib/spack/spack/cmd/unload.py +++ b/lib/spack/spack/cmd/unload.py @@ -32,6 +32,9 @@ def setup_parser(subparser): shells.add_argument( '--fish', action='store_const', dest='shell', const='fish', help="print fish commands to load the package") + shells.add_argument( + '--bat', action='store_const', dest='shell', const='bat', + help="print bat commands to load the package") subparser.add_argument('-a', '--all', action='store_true', help='unload all loaded Spack packages.') diff --git a/lib/spack/spack/environment/shell.py b/lib/spack/spack/environment/shell.py index 0574ec97ce..377c760930 100644 --- a/lib/spack/spack/environment/shell.py +++ b/lib/spack/spack/environment/shell.py @@ -37,6 +37,11 @@ def activate_header(env, shell, prompt=None): # solution to the PS1 variable) here. This is a bit fiddly, and easy to # screw up => spend time reasearching a solution. Feedback welcome. # + elif shell == 'bat': + # TODO: Color + cmds += 'set "SPACK_ENV=%s"\n' % env.path + # TODO: despacktivate + # TODO: prompt else: if 'color' in os.getenv('TERM', '') and prompt: prompt = colorize('@G{%s}' % prompt, color=True) @@ -69,6 +74,11 @@ def deactivate_header(shell): # # NOTE: Not changing fish_prompt (above) => no need to restore it here. # + elif shell == 'bat': + # TODO: Color + cmds += 'set "SPACK_ENV="\n' + # TODO: despacktivate + # TODO: prompt else: cmds += 'if [ ! -z ${SPACK_ENV+x} ]; then\n' cmds += 'unset SPACK_ENV; export SPACK_ENV;\n' diff --git a/lib/spack/spack/util/editor.py b/lib/spack/spack/util/editor.py index 5aa79bbe99..dccd3a46d2 100644 --- a/lib/spack/spack/util/editor.py +++ b/lib/spack/spack/util/editor.py @@ -21,7 +21,7 @@ from spack.util.executable import which_string #: editors to try if VISUAL and EDITOR are not set -_default_editors = ['vim', 'vi', 'emacs', 'nano'] +_default_editors = ['vim', 'vi', 'emacs', 'nano', 'notepad'] def _find_exe_from_env_var(var): diff --git a/lib/spack/spack/util/environment.py b/lib/spack/spack/util/environment.py index 9b143b0b6b..19e028ee67 100644 --- a/lib/spack/spack/util/environment.py +++ b/lib/spack/spack/util/environment.py @@ -36,7 +36,8 @@ _shell_set_strings = { 'sh': 'export {0}={1};\n', 'csh': 'setenv {0} {1};\n', - 'fish': 'set -gx {0} {1};\n' + 'fish': 'set -gx {0} {1};\n', + 'bat': 'set "{0}={1}"\n' } @@ -44,6 +45,7 @@ 'sh': 'unset {0};\n', 'csh': 'unsetenv {0};\n', 'fish': 'set -e {0};\n', + 'bat': 'set "{0}="\n' } @@ -83,7 +85,7 @@ def prune_duplicate_paths(paths): def get_path(name): path = os.environ.get(name, "").strip() if path: - return path.split(":") + return path.split(os.pathsep) else: return [] @@ -96,7 +98,7 @@ def env_flag(name): def path_set(var_name, directories): - path_str = ":".join(str(dir) for dir in directories) + path_str = os.pathsep.join(str(dir) for dir in directories) os.environ[var_name] = path_str @@ -104,7 +106,7 @@ def path_put_first(var_name, directories): """Puts the provided directories first in the path, adding them if they're not already there. """ - path = os.environ.get(var_name, "").split(':') + path = os.environ.get(var_name, "").split(os.pathsep) for dir in directories: if dir in path: @@ -214,7 +216,7 @@ class NameModifier(object): def __init__(self, name, **kwargs): self.name = name - self.separator = kwargs.get('separator', ':') + self.separator = kwargs.get('separator', os.pathsep) self.args = {'name': name, 'separator': self.separator} self.args.update(kwargs) @@ -234,7 +236,7 @@ class NameValueModifier(object): def __init__(self, name, value, **kwargs): self.name = name self.value = value - self.separator = kwargs.get('separator', ':') + self.separator = kwargs.get('separator', os.pathsep) self.args = {'name': name, 'value': value, 'separator': self.separator} self.args.update(kwargs) @@ -634,8 +636,13 @@ def shell_modifications(self, shell='sh', explicit=False, env=None): if new is None: cmds += _shell_unset_strings[shell].format(name) else: - cmds += _shell_set_strings[shell].format( - name, cmd_quote(new_env[name])) + if sys.platform != "win32": + cmd = _shell_set_strings[shell].format( + name, cmd_quote(new_env[name])) + else: + cmd = _shell_set_strings[shell].format( + name, new_env[name]) + cmds += cmd return cmds @staticmethod @@ -815,13 +822,13 @@ def return_separator_if_any(*args): return env -def concatenate_paths(paths, separator=':'): +def concatenate_paths(paths, separator=os.pathsep): """Concatenates an iterable of paths into a string of paths separated by separator, defaulting to colon. Args: paths: iterable of paths - separator: the separator to use, default ':' + separator: the separator to use, default ';' windows, ':' otherwise Returns: string diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash index ff8506d36e..3045052ecd 100755 --- a/share/spack/spack-completion.bash +++ b/share/spack/spack-completion.bash @@ -337,7 +337,7 @@ _spack() { then SPACK_COMPREPLY="-h --help -H --all-help --color -c --config -C --config-scope -d --debug --show-cores --timestamp --pdb -e --env -D --env-dir -E --no-env --use-env-repo -k --insecure -l --enable-locks -L --disable-locks -m --mock -b --bootstrap -p --profile --sorted-profile --lines -v --verbose --stacktrace -V --version --print-shell-vars" else - SPACK_COMPREPLY="activate add analyze arch audit blame bootstrap build-env buildcache cd checksum ci clean clone commands compiler compilers concretize config containerize create deactivate debug dependencies dependents deprecate dev-build develop diff docs edit env extensions external fetch find gc gpg graph help info install license list load location log-parse maintainers mark mirror module monitor patch pkg providers pydoc python reindex remove rm repo resource restage solve spec stage style tags test test-env tutorial undevelop uninstall unit-test unload url verify versions view" + SPACK_COMPREPLY="activate add analyze arch audit blame bootstrap build-env buildcache cd checksum ci clean clone commands compiler compilers concretize config containerize create deactivate debug dependencies dependents deprecate dev-build develop diff docs edit env extensions external fetch find gc gpg graph help info install license list load location log-parse maintainers make-installer mark mirror module monitor patch pkg providers pydoc python reindex remove rm repo resource restage solve spec stage style tags test test-env tutorial undevelop uninstall unit-test unload url verify versions view" fi } @@ -1238,6 +1238,15 @@ _spack_maintainers() { fi } +_spack_make_installer() { + if $list_options + then + SPACK_COMPREPLY="-h --help -v --spack_version -s --spack_source" + else + SPACK_COMPREPLY="" + fi +} + _spack_mark() { if $list_options then