stack 2.15.7 → 3.1.1
raw patch · 275 files changed
+19874/−14525 lines, 275 filesdep +hashabledep ~Cabaldep ~directorydep ~extrasetup-changed
Dependencies added: hashable
Dependency ranges changed: Cabal, directory, extra, ghc-boot, hspec, pantry, path-io, tar, unix-compat
Files
- CONTRIBUTING.md +62/−5
- ChangeLog.md +105/−3
- Setup.hs +29/−20
- cabal.config +6/−6
- cabal.project +2/−2
- doc/CI.md +0/−17
- doc/CONTRIBUTING.md +62/−5
- doc/ChangeLog.md +105/−3
- doc/GUIDE.md +0/−1483
- doc/GUIDE_advanced.md +0/−74
- doc/README.md +258/−252
- doc/Stack_and_VS_Code.md +0/−133
- doc/azure_ci.md +0/−174
- doc/build_command.md +0/−1005
- doc/build_overview.md +3/−2
- doc/clean_command.md +0/−21
- doc/commands/bench_command.md +28/−0
- doc/commands/build_command.md +1101/−0
- doc/commands/clean_command.md +21/−0
- doc/commands/config_command.md +151/−0
- doc/commands/docker_command.md +37/−0
- doc/commands/dot_command.md +103/−0
- doc/commands/eval_command.md +20/−0
- doc/commands/exec_command.md +72/−0
- doc/commands/ghc_command.md +21/−0
- doc/commands/ghci_command.md +161/−0
- doc/commands/haddock_command.md +30/−0
- doc/commands/hoogle_command.md +33/−0
- doc/commands/hpc_command.md +167/−0
- doc/commands/ide_command.md +72/−0
- doc/commands/index.md +136/−0
- doc/commands/init_command.md +42/−0
- doc/commands/install_command.md +30/−0
- doc/commands/list_command.md +64/−0
- doc/commands/ls_command.md +276/−0
- doc/commands/new_command.md +138/−0
- doc/commands/path_command.md +49/−0
- doc/commands/purge_command.md +10/−0
- doc/commands/query_command.md +44/−0
- doc/commands/repl_command.md +14/−0
- doc/commands/run_command.md +46/−0
- doc/commands/runghc_command.md +22/−0
- doc/commands/runhaskell_command.md +12/−0
- doc/commands/script_command.md +329/−0
- doc/commands/sdist_command.md +43/−0
- doc/commands/setup_command.md +95/−0
- doc/commands/templates_command.md +34/−0
- doc/commands/test_command.md +28/−0
- doc/commands/uninstall_command.md +11/−0
- doc/commands/unpack_command.md +51/−0
- doc/commands/update_command.md +12/−0
- doc/commands/upgrade_command.md +103/−0
- doc/commands/upload_command.md +135/−0
- doc/community/index.md +75/−0
- doc/config_command.md +0/−136
- doc/configure/customisation_scripts.md +133/−0
- doc/configure/environment_variables.md +152/−0
- doc/configure/global_flags.md +362/−0
- doc/configure/index.md +41/−0
- doc/configure/yaml/index.md +126/−0
- doc/configure/yaml/non-project.md +1606/−0
- doc/configure/yaml/project.md +455/−0
- doc/custom_snapshot.md +0/−136
- doc/debugging.md +0/−95
- doc/dev_containers.md +2/−2
- doc/developing_on_windows.md +0/−102
- doc/docker_command.md +0/−37
- doc/docker_integration.md +0/−473
- doc/dot_command.md +0/−103
- doc/editor_integration.md +0/−20
- doc/environment_variables.md +0/−134
- doc/eval_command.md +0/−20
- doc/exec_command.md +0/−72
- doc/faq.md +428/−508
- doc/ghc_command.md +0/−21
- doc/ghci.md +0/−161
- doc/global_flags.md +0/−351
- doc/glossary.md +1/−1
- doc/hoogle_command.md +0/−33
- doc/hpc_command.md +0/−167
- doc/ide_command.md +0/−72
- doc/init_command.md +0/−42
- doc/install_and_upgrade.md +838/−711
- doc/list_command.md +0/−66
- doc/lock_files.md +0/−185
- doc/ls_command.md +0/−244
- doc/maintainers/7zip.md +92/−0
- doc/maintainers/archive/README.md +4/−0
- doc/maintainers/archive/releases.md +308/−0
- doc/maintainers/docker.md +180/−0
- doc/maintainers/docker_images.md +34/−0
- doc/maintainers/ghc.md +124/−0
- doc/maintainers/haskellstack.org.md +173/−0
- doc/maintainers/msys.md +115/−0
- doc/maintainers/releases.md +700/−0
- doc/maintainers/self-hosted_runners.md +87/−0
- doc/maintainers/stack_errors.md +674/−0
- doc/maintainers/team_process.md +262/−0
- doc/new_command.md +0/−137
- doc/nix_integration.md +0/−439
- doc/nonstandard_project_init.md +0/−36
- doc/other_resources.md +4/−4
- doc/pantry.md +0/−300
- doc/path_command.md +0/−49
- doc/purge_command.md +0/−10
- doc/query_command.md +0/−44
- doc/run_command.md +0/−46
- doc/runghc_command.md +0/−22
- doc/script_command.md +0/−177
- doc/scripts.md +0/−268
- doc/sdist_command.md +0/−42
- doc/setup_command.md +0/−85
- doc/shell_autocompletion.md +0/−70
- doc/stack_root.md +0/−260
- doc/stack_work.md +0/−144
- doc/stack_yaml_vs_cabal_package_file.md +0/−162
- doc/templates_command.md +0/−34
- doc/topics/CI.md +17/−0
- doc/topics/Stack_and_VS_Code.md +133/−0
- doc/topics/azure_ci.md +174/−0
- doc/topics/custom_snapshot.md +137/−0
- doc/topics/debugging.md +96/−0
- doc/topics/developing_on_windows.md +109/−0
- doc/topics/docker_integration.md +473/−0
- doc/topics/editor_integration.md +20/−0
- doc/topics/haskell_and_c_code.md +229/−0
- doc/topics/index.md +96/−0
- doc/topics/lock_files.md +186/−0
- doc/topics/nix_integration.md +440/−0
- doc/topics/nonstandard_project_init.md +36/−0
- doc/topics/package_location.md +225/−0
- doc/topics/scripts.md +290/−0
- doc/topics/shell_autocompletion.md +70/−0
- doc/topics/snapshot_location.md +80/−0
- doc/topics/stack_root.md +284/−0
- doc/topics/stack_work.md +148/−0
- doc/topics/stack_yaml_vs_cabal_package_file.md +162/−0
- doc/topics/travis_ci.md +182/−0
- doc/travis_ci.md +0/−182
- doc/tutorial/building_existing_projects.md +139/−0
- doc/tutorial/building_your_project.md +332/−0
- doc/tutorial/cabal_flags_and_ghc_options.md +101/−0
- doc/tutorial/executing_commands.md +62/−0
- doc/tutorial/hello_world_example.md +442/−0
- doc/tutorial/index.md +59/−0
- doc/tutorial/installed_package_databases.md +110/−0
- doc/tutorial/locations_used_by_stack.md +86/−0
- doc/tutorial/multi-package_projects.md +63/−0
- doc/tutorial/stack_build_synonyms.md +94/−0
- doc/tutorial/stack_build_targets.md +107/−0
- doc/tutorial/stack_configuration.md +75/−0
- doc/tutorial/tutorial_conclusion.md +43/−0
- doc/tutorial/using_ghc_interactively.md +31/−0
- doc/uninstall_command.md +0/−11
- doc/unpack_command.md +0/−51
- doc/update_command.md +0/−12
- doc/upgrade_command.md +0/−103
- doc/upload_command.md +0/−131
- doc/yaml_configuration.md +0/−2069
- src/Codec/Archive/Tar/Utf8.hs +0/−182
- src/Data/Attoparsec/Interpreter.hs +2/−2
- src/Options/Applicative/Builder/Extra.hs +2/−3
- src/Options/Applicative/Complicated.hs +4/−3
- src/Path/CheckInstall.hs +9/−6
- src/Stack.hs +9/−13
- src/Stack/Build.hs +100/−40
- src/Stack/Build/Cache.hs +8/−13
- src/Stack/Build/ConstructPlan.hs +105/−102
- src/Stack/Build/Execute.hs +16/−14
- src/Stack/Build/ExecuteEnv.hs +10/−21
- src/Stack/Build/ExecutePackage.hs +197/−249
- src/Stack/Build/Haddock.hs +143/−63
- src/Stack/Build/Installed.hs +1/−1
- src/Stack/Build/Source.hs +105/−60
- src/Stack/Build/Target.hs +48/−28
- src/Stack/BuildOpts.hs +3/−0
- src/Stack/BuildPlan.hs +5/−5
- src/Stack/CLI.hs +30/−11
- src/Stack/Clean.hs +4/−4
- src/Stack/Component.hs +0/−8
- src/Stack/ComponentFile.hs +32/−32
- src/Stack/Config.hs +229/−212
- src/Stack/Config/Build.hs +9/−0
- src/Stack/Config/Docker.hs +22/−22
- src/Stack/ConfigCmd.hs +108/−49
- src/Stack/Constants.hs +32/−45
- src/Stack/Constants/Config.hs +5/−5
- src/Stack/Coverage.hs +33/−49
- src/Stack/Docker.hs +5/−6
- src/Stack/Dot.hs +4/−3
- src/Stack/Exec.hs +10/−6
- src/Stack/FileWatch.hs +77/−21
- src/Stack/Ghci.hs +82/−75
- src/Stack/Hoogle.hs +18/−20
- src/Stack/Init.hs +54/−52
- src/Stack/List.hs +19/−17
- src/Stack/Lock.hs +2/−2
- src/Stack/Ls.hs +49/−12
- src/Stack/New.hs +10/−11
- src/Stack/Options/BuildMonoidParser.hs +23/−4
- src/Stack/Options/BuildParser.hs +15/−4
- src/Stack/Options/ConfigParser.hs +7/−2
- src/Stack/Options/DotParser.hs +1/−1
- src/Stack/Options/GhciParser.hs +1/−7
- src/Stack/Options/GlobalParser.hs +10/−10
- src/Stack/Options/LsParser.hs +33/−5
- src/Stack/Options/ResolverParser.hs +0/−41
- src/Stack/Options/SetupParser.hs +2/−2
- src/Stack/Options/SnapshotParser.hs +41/−0
- src/Stack/Options/UploadParser.hs +7/−1
- src/Stack/Options/Utils.hs +2/−2
- src/Stack/Package.hs +124/−90
- src/Stack/PackageDump.hs +33/−11
- src/Stack/Path.hs +22/−11
- src/Stack/Runners.hs +2/−2
- src/Stack/SDist.hs +14/−15
- src/Stack/Script.hs +2/−1
- src/Stack/Setup.hs +62/−37
- src/Stack/Setup/Installed.hs +22/−30
- src/Stack/SetupCmd.hs +20/−9
- src/Stack/SourceMap.hs +0/−44
- src/Stack/Storage/Project.hs +28/−34
- src/Stack/Storage/User.hs +9/−11
- src/Stack/Storage/Util.hs +41/−49
- src/Stack/Types/ApplyGhcOptions.hs +3/−3
- src/Stack/Types/ApplyProgOptions.hs +3/−3
- src/Stack/Types/Build.hs +14/−12
- src/Stack/Types/Build/ConstructPlan.hs +28/−3
- src/Stack/Types/Build/Exception.hs +86/−46
- src/Stack/Types/BuildConfig.hs +24/−18
- src/Stack/Types/BuildOpts.hs +13/−2
- src/Stack/Types/BuildOptsCLI.hs +4/−1
- src/Stack/Types/BuildOptsMonoid.hs +25/−2
- src/Stack/Types/Cache.hs +3/−2
- src/Stack/Types/CompCollection.hs +12/−13
- src/Stack/Types/CompilerBuild.hs +1/−0
- src/Stack/Types/Component.hs +8/−7
- src/Stack/Types/ComponentUtils.hs +31/−10
- src/Stack/Types/Config.hs +23/−13
- src/Stack/Types/Config/Exception.hs +31/−29
- src/Stack/Types/ConfigMonoid.hs +54/−23
- src/Stack/Types/ConfigureOpts.hs +69/−27
- src/Stack/Types/Dependency.hs +12/−0
- src/Stack/Types/Docker.hs +1/−1
- src/Stack/Types/DownloadInfo.hs +0/−1
- src/Stack/Types/EnvConfig.hs +7/−7
- src/Stack/Types/EnvSettings.hs +1/−1
- src/Stack/Types/GhcPkgId.hs +26/−12
- src/Stack/Types/GlobalOpts.hs +2/−3
- src/Stack/Types/GlobalOptsMonoid.hs +5/−5
- src/Stack/Types/InterfaceOpt.hs +19/−0
- src/Stack/Types/MsysEnvironment.hs +65/−0
- src/Stack/Types/NamedComponent.hs +30/−18
- src/Stack/Types/Nix.hs +1/−1
- src/Stack/Types/Package.hs +9/−0
- src/Stack/Types/Project.hs +4/−4
- src/Stack/Types/ProjectAndConfigMonoid.hs +4/−4
- src/Stack/Types/Resolver.hs +0/−107
- src/Stack/Types/Snapshot.hs +112/−0
- src/Stack/Types/SourceMap.hs +6/−9
- src/Stack/Types/StackYamlLoc.hs +1/−1
- src/Stack/Types/UploadOpts.hs +33/−0
- src/Stack/Types/WantedCompilerSetter.hs +17/−0
- src/Stack/Uninstall.hs +5/−5
- src/Stack/Unpack.hs +3/−9
- src/Stack/Upgrade.hs +7/−7
- src/Stack/Upload.hs +70/−85
- src/System/Process/Pager.hs +0/−1
- src/setup-shim/StackSetupShim.hs +11/−32
- stack.cabal +137/−91
- stack.yaml +10/−2
- tests/integration/IntegrationSpec.hs +7/−2
- tests/integration/lib/StackTest.hs +4/−5
- tests/unit/Stack/Config/DockerSpec.hs +7/−7
- tests/unit/Stack/ConfigSpec.hs +24/−16
CONTRIBUTING.md view
@@ -209,6 +209,62 @@ that contain the link text See the [Git documentation](https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresymlinks). +The online documentation can be previewed using the `mkdocs` tool, as described +in [Getting Started with MkDocs](https://www.mkdocs.org/getting-started/). The +prerequisites are: + +* [Python](https://www.python.org/); and +* the required Python packages set out in `doc/requirements.txt`. They can be + installed using Python's package manager `pip` with: + + ~~~text + pip install --requirement doc/requirements.txt + ~~~ + +Once the required version of `mkdocs` is installed, command `mkdocs serve` in +the same directory as the `mkdocs.yml` file to start a web server. The command +will, eventually, output the URL at which the documentation is being served. + +Command `mkdocs build` to build the documentation. + +=== "Windows" + + With the correct prerequisites (see further below), users of the `make` tool + in the Stack-supplied MSYS2 environment can automate some of these steps + from Stack's project directory with: + + * preview: `stack exec -- make docs-serve`; and + * build: `stack exec -- make _site/index.html`. + + However, Windows and the Stack-supplied MSYS2 environment do not come with + Python or `make` by default. Further, Python on Windows does not use the + `python3` command (used on Unix-like operating systems) to invoke Python. + Further still, in the MSYS2 environment, development versions of packages + `libxml2` and `libxslt` are necessary dependencies. Consequently, the + automation requires the following command to install requirements into the + the MSYS2 environment: + + ~~~text + stack exec -- pacman --sync python make libxml2-devel libxslt-devel + ~~~ + + !!! note + + If the automation fails before the `mkdocs` tool etc is installed, the + directory `.python-doc-virtualenv` created by the automation will need + to be deleted before the automation will work again. + + For most users, the automation will be less convenient than simply using the + `mkdocs serve` command directly. + +=== "Unix-like" + + With `python3` and `make` available on the PATH, users of the `make` tool + can automate some of these steps from Stack's project directory with: + + * preview: `make docs-serve`; and + * build: `make _site/index.html`. + ## Error messages Stack catches exceptions thrown by its dependencies or by Stack itself in @@ -285,8 +341,9 @@ Stack aims to depend on well-known packages. The specific versions on which it depends at any time are specified by `package.yaml` and `stack.yaml`. It does not aim to be compatible with more than one version of the `Cabal` package at -any time. At the time of writing (May 2024) the package versions are primarily -ones in Stackage snapshot LTS Haskell 22.21 (for GHC 9.6.5). +any time. At the time of writing (July 2024) the package versions are primarily +ones in Stackage snapshot LTS Haskell 22.28 (for GHC 9.6.6), together with +extra-deps to depend on the latest version of `hpack`, `pantry` and `tar`. A Stack executable makes use of Cabal (the library) through a small 'Setup' executable that it compiles from Haskell source code. The executable compiles @@ -548,7 +605,7 @@ `--pedantic` flag. The `unit-tests` job runs on a matrix of operating systems and Stack -project-level YAML configuration files (`stack.yaml`, by default). It builds and +project-level configuration files (`stack.yaml`, by default). It builds and tests Stack with the following flags: `--haddock --no-haddock-deps`. Its approach to creating a cache depends on the operating system. Its 'Cache @@ -606,7 +663,7 @@ [Stan](https://hackage.haskell.org/package/stan) is a Haskell static analysis tool. As of `stan-0.1.0.1`, it supports GHC >= 9.6.3 and Stack is built with -GHC 9.6.5. The tool is configured by the contents of the `.stan.toml` file. +GHC 9.6.6. The tool is configured by the contents of the `.stan.toml` file. This workflow will run if: @@ -735,7 +792,7 @@ ~~~ A cradle is not committed to Stack's repository because it imposes a choice of -build tool. +tool used for building. ## Dev Containers
ChangeLog.md view
@@ -1,5 +1,102 @@ # Changelog +## v3.1.1 2024-07-28 + +Release notes: + +* The change in major version from 2.x to 3.1 marks the dropping of support for + versions of GHC before 8.4, deprecated in Stack 2.15.1. + +**Changes since v2.15.7:** + +Behavior changes: + +* Stack uses the version of the Cabal package that comes with the specified + version of GHC. Stack no longer supports such Cabal versions before 2.2, which + came with versions of GHC before 8.4. Consequently, the `init` command will + not try LTS Haskell before 12.0. +* The `init` command initialises `stack.yaml` with a `snapshot` key rather than + a `resolver` key. +* After installing GHC or another tool, Stack deletes the archive file which + provided the tool. +* Remove hidden flag `--skip-intermediate-deps`, effectively deprecated since + Stack 1.3.0, from `ghci` and `repl` commands. +* The `haddock --haddock-for-hackage` command only seeks to create an archive of + the `<package_version>-docs` directory for build targets and if flags + excluding the building of project packages are not set. +* The predecessor of configuration option `package-index`, `package-indices` + (deprecated in Stack 2.9.3) has been removed as an alternative option. +* If a build target is a package identifier, and the package version is not in + the snapshot or the package index, Stack will report an error when the target + is parsed. Previously, if another version of the package was in the snapshot, + Stack would construct the build plan with that other version or, if it was + not, Stack would defer an error to the construction of the build plan. +* The `list` command, with a specified snapshot and package, also reports the + version of the package included indirectly in the snapshot (as a boot package + of the compiler specified by the snapshot). +* `stack build --flag *:[-]<flag_name>` now only applies the flag setting to + packages for which the Cabal flag is defined, as opposed to all packages. +* On Unix-like operating systems, drop support for `/etc/stack/config`, + deprecated in Stack 0.1.6.0. +* Drop support for, in the Stack root, directory `global` and file `stack.yaml`, + both deprecated in Stack 0.1.6.0. + +Other enhancements: + +* Bump to Hpack 0.37.0. +* In YAML configuration files, the `msys-environment` key is introduced to + allow, on Windows, the MSYS2 environment to be specified. The default + environment is still `MINGW64` on 64-bit Windows and `MINGW32` on 32-bit + Windows. +* In YAML configuration files, the `default-init-snapshot` key is introduced to + allow a default snapshot to be specified for use with the `stack init` + command, as if it had been specified at the command line. +* Add flags `--haddock-executables`, `--haddock-tests` and + `--haddock-benchmarks` to Stack's `build` command (including the `haddock` + synonym for `build --haddock`) to enable also building Haddock + documentation for executables, test suites and benchmarks. Due to a bug in + Cabal (the library), Stack will ignore the flags with a warning for GHC + versions before 9.4. +* Add flag `--[no-]save-hackage-creds` to Stack's `upload` command, which takes + precedence over the existing `save-hackage-creds` configuration option. +* In YAML configuration files, the `global-hints-location` key is introduced to + allow the location of the global hints YAML specification file to be + specified. +* By default, Hpack 0.20.0 or later will decline to overwrite a Cabal file that + was modified manually. In YAML configuration files, the `hpack-force` key is + introduced to allow Hpack to overwrite such a Cabal file. The corresponding + `--hpack-force` flag is also added. +* Add the `stack config set recommend-stack-upgrade` command to configure + whether or not Stack should notify the user if it identifes a new version of + Stack is available in YAML configuration files. +* Add the `ls globals` command to list all global packages for the version of + GHC specified by the snapshot. +* Add `stack -h` (equivalent to `stack --help`). +* In YAML configuration files, the `file-watch-hook` key is introduced to allow + `--file-watch` post-processing to be customised with a executable or `sh` + shell script. +* Add flag `--[no-]allow-newer` to Stack's `build` command, which takes + precedence over the existing `allow-newer` configuration option. + +Bug fixes: + +* The `config set snapshot` and `config set resolver` commands now respect the + presence of a synoymous key. +* The `config set` commands support existing keys only in the form `key: value` + on a single line. The commands now recognise that a line `key:` does not have + that form. +* On Unix-like operating systems, the `test --coverage` command now finds + package keys even for very long package names. +* The Error S-6362 message now acknowledges when the wanted compiler has been + specified at the command line. +* Fix a regression, introduced in Stack 2.11.1, that caused the `script` command + to parse an (otherwise ignored) project-level configuration file. +* Stack no longer makes recommendations about a project-level configuration file + when only a global configuration file is in use. +* Fix a regression, introduced in Stack 2.15.7, that caused GHC 8.10.7 or + earlier to fail to build a package with a `Custom` build type, if GHC option + `-haddock` was specified. + ## v2.15.7 - 2024-05-12 Release notes: @@ -273,6 +370,11 @@ * On Windows, `stack upgrade` does not offer `sudo` command alternatives if attempting to write to the original file name of the running Stack exectuable results in a 'Permission' error. +* On Linux, Stack's `setup` command now distinguishes GHC build + `tinfo6-libc6-pre232` from existing `tinfo6`. The former refers to systems + where the version of `libc6` (the GNU C Library) is not compatible with + version 2.32. `tinfo6-libc6-pre232` is now a possible value for the + `ghc-build` configuration option. Other enhancements: @@ -1221,9 +1323,9 @@ [help file](https://github.com/commercialhaskell/stack-templates/blob/master/STACK_HELP.md) with more information on how to discover templates. See: [#4039](https://github.com/commercialhaskell/stack/issues/4039) -* Build tools are now handled in a similar way to `cabal-install`. In - particular, for legacy `build-tools` fields, we use a hard-coded - list of build tools in place of looking up build tool packages in a +* Tools used during building ('build tools') are now handled in a similar way to + `cabal-install`. In particular, for legacy `build-tools` fields, we use a + hard-coded list of build tools in place of looking up build tool packages in a tool map. This both brings Stack's behavior closer into line with `cabal-install`, avoids some bugs, and opens up some possible optimizations/laziness. See:
Setup.hs view
@@ -4,24 +4,24 @@ import Data.List ( nub, sortOn ) import Distribution.InstalledPackageInfo - ( sourcePackageId, installedUnitId ) -import Distribution.Package ( UnitId, packageVersion, packageName ) + ( installedUnitId, sourcePackageId ) +import Distribution.Package ( UnitId, packageName, packageVersion ) import Distribution.PackageDescription - ( PackageDescription (), Executable (..) ) + ( Executable (..), PackageDescription ) import Distribution.Pretty ( prettyShow ) import Distribution.Simple - ( defaultMainWithHooks, UserHooks(..), simpleUserHooks ) + ( UserHooks(..), defaultMainWithHooks, simpleUserHooks ) import Distribution.Simple.BuildPaths ( autogenPackageModulesDir ) import Distribution.Simple.LocalBuildInfo - ( installedPkgs, withLibLBI, withExeLBI, LocalBuildInfo () - , ComponentLocalBuildInfo (componentPackageDeps) + ( ComponentLocalBuildInfo (..), LocalBuildInfo, installedPkgs + , withExeLBI, withLibLBI ) import Distribution.Simple.PackageIndex ( allPackages, dependencyClosure ) import Distribution.Simple.Setup ( BuildFlags (..), ReplFlags (..), fromFlag ) import Distribution.Simple.Utils - ( rewriteFileEx, createDirectoryIfMissingVerbose ) + ( createDirectoryIfMissingVerbose, rewriteFileEx ) import Distribution.Types.PackageName ( unPackageName ) import Distribution.Types.UnqualComponentName ( unUnqualComponentName ) @@ -41,7 +41,11 @@ replHook simpleUserHooks pkg lbi hooks flags args } -generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO () +generateBuildModule :: + Verbosity + -> PackageDescription + -> LocalBuildInfo + -> IO () generateBuildModule verbosity pkg lbi = do let dir = autogenPackageModulesDir lbi createDirectoryIfMissingVerbose verbosity True dir @@ -60,17 +64,22 @@ formatdeps = map formatone . sortOn unPackageName' formatone p = unPackageName' p ++ "-" ++ prettyShow (packageVersion p) unPackageName' = unPackageName . packageName - transDeps xs ys = - either (map sourcePackageId . allPackages) handleDepClosureFailure $ dependencyClosure allInstPkgsIdx availInstPkgIds - where - allInstPkgsIdx = installedPkgs lbi - allInstPkgIds = map installedUnitId $ allPackages allInstPkgsIdx - -- instPkgIds includes `stack-X.X.X`, which is not a dependency hence is missing from allInstPkgsIdx. Filter that out. - availInstPkgIds = filter (`elem` allInstPkgIds) $ testDeps xs ys - handleDepClosureFailure unsatisfied = - error $ - "Computation of transitive dependencies failed." ++ - if null unsatisfied then "" else " Unresolved dependencies: " ++ show unsatisfied + transDeps xs ys = either + (map sourcePackageId . allPackages) + handleDepClosureFailure $ dependencyClosure allInstPkgsIdx availInstPkgIds + where + allInstPkgsIdx = installedPkgs lbi + allInstPkgIds = map installedUnitId $ allPackages allInstPkgsIdx + -- instPkgIds includes `stack-X.X.X`, which is not a dependency hence is + -- missing from allInstPkgsIdx. Filter that out. + availInstPkgIds = filter (`elem` allInstPkgIds) $ testDeps xs ys + handleDepClosureFailure unsatisfied = + error $ + "Computation of transitive dependencies failed." + ++ if null unsatisfied + then "" + else " Unresolved dependencies: " ++ show unsatisfied testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [UnitId] -testDeps xs ys = map fst $ nub $ componentPackageDeps xs ++ componentPackageDeps ys +testDeps xs ys = + map fst $ nub $ componentPackageDeps xs ++ componentPackageDeps ys
cabal.config view
@@ -80,8 +80,8 @@ , generic-deriving ==1.14.5 , generically ==0.1.1 , ghc-bignum ==1.3 - , ghc-boot ==9.6.5 - , ghc-boot-th ==9.6.5 + , ghc-boot ==9.6.6 + , ghc-boot-th ==9.6.6 , ghc-prim ==0.10.0 , githash ==0.1.7.0 , hackage-security ==0.6.2.4 @@ -89,7 +89,7 @@ , hi-file-parser ==0.1.6.0 , hinotify ==0.4.1 , hourglass ==0.2.12 - , hpack ==0.36.0 + , hpack ==0.37.0 , hpc ==0.6.2.0 , http-api-data ==0.5.1 , http-client ==0.7.17 @@ -132,7 +132,7 @@ , optparse-applicative ==0.18.1.0 , optparse-simple ==0.1.1.4 , os-string ==2.0.2.1 - , pantry ==0.9.3.2 + , pantry ==0.10.0 , parsec ==3.1.16.1 , parser-combinators ==1.3.0 , path ==0.9.5 @@ -165,14 +165,14 @@ , socks ==0.6.1 , split ==0.2.5 , splitmix ==0.1.0.5 - , stack ==2.15.7 + , stack ==3.1.1 , static-bytes ==0.1.0 , stm ==2.5.1.0 , stm-chans ==3.0.0.9 , streaming-commons ==0.2.2.6 , strict ==0.5 , tagged ==0.8.8 - , tar ==0.5.1.1 + , tar ==0.6.2.0 , tar-conduit ==0.4.1 , template-haskell ==2.20.0.0 , temporary ==1.3
cabal.project view
@@ -33,8 +33,8 @@ -- specified by the snapshot specifed in Stack's project-level YAML -- configuration file (`stack.yaml`). The relevant version of GHC can be -- confirmed by reviewing the snapshot on Stackage. For example, at: --- https://www.stackage.org/lts-22.21/cabal.config. +-- https://www.stackage.org/lts-22.28/cabal.config. -- -with-compiler: ghc-9.6.5 +with-compiler: ghc-9.6.6 import: cabal.config packages: .
− doc/CI.md
@@ -1,17 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Continuous integration (CI) - -## GitHub Actions - -The Stack repository uses GitHub Actions for its own CI. For further -information, see the guide to -[contributing](CONTRIBUTING.md#continuous-integration-ci). - -## Azure - -For further information, see the [Azure CI](azure_ci.md) documentation. - -## Travis - -For further information, see the [Travis CI](travis_ci.md) documentation.
doc/CONTRIBUTING.md view
@@ -209,6 +209,62 @@ that contain the link text See the [Git documentation](https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresymlinks). +The online documentation can be previewed using the `mkdocs` tool, as described +in [Getting Started with MkDocs](https://www.mkdocs.org/getting-started/). The +prerequisites are: + +* [Python](https://www.python.org/); and +* the required Python packages set out in `doc/requirements.txt`. They can be + installed using Python's package manager `pip` with: + + ~~~text + pip install --requirement doc/requirements.txt + ~~~ + +Once the required version of `mkdocs` is installed, command `mkdocs serve` in +the same directory as the `mkdocs.yml` file to start a web server. The command +will, eventually, output the URL at which the documentation is being served. + +Command `mkdocs build` to build the documentation. + +=== "Windows" + + With the correct prerequisites (see further below), users of the `make` tool + in the Stack-supplied MSYS2 environment can automate some of these steps + from Stack's project directory with: + + * preview: `stack exec -- make docs-serve`; and + * build: `stack exec -- make _site/index.html`. + + However, Windows and the Stack-supplied MSYS2 environment do not come with + Python or `make` by default. Further, Python on Windows does not use the + `python3` command (used on Unix-like operating systems) to invoke Python. + Further still, in the MSYS2 environment, development versions of packages + `libxml2` and `libxslt` are necessary dependencies. Consequently, the + automation requires the following command to install requirements into the + the MSYS2 environment: + + ~~~text + stack exec -- pacman --sync python make libxml2-devel libxslt-devel + ~~~ + + !!! note + + If the automation fails before the `mkdocs` tool etc is installed, the + directory `.python-doc-virtualenv` created by the automation will need + to be deleted before the automation will work again. + + For most users, the automation will be less convenient than simply using the + `mkdocs serve` command directly. + +=== "Unix-like" + + With `python3` and `make` available on the PATH, users of the `make` tool + can automate some of these steps from Stack's project directory with: + + * preview: `make docs-serve`; and + * build: `make _site/index.html`. + ## Error messages Stack catches exceptions thrown by its dependencies or by Stack itself in @@ -285,8 +341,9 @@ Stack aims to depend on well-known packages. The specific versions on which it depends at any time are specified by `package.yaml` and `stack.yaml`. It does not aim to be compatible with more than one version of the `Cabal` package at -any time. At the time of writing (May 2024) the package versions are primarily -ones in Stackage snapshot LTS Haskell 22.21 (for GHC 9.6.5). +any time. At the time of writing (July 2024) the package versions are primarily +ones in Stackage snapshot LTS Haskell 22.28 (for GHC 9.6.6), together with +extra-deps to depend on the latest version of `hpack`, `pantry` and `tar`. A Stack executable makes use of Cabal (the library) through a small 'Setup' executable that it compiles from Haskell source code. The executable compiles @@ -548,7 +605,7 @@ `--pedantic` flag. The `unit-tests` job runs on a matrix of operating systems and Stack -project-level YAML configuration files (`stack.yaml`, by default). It builds and +project-level configuration files (`stack.yaml`, by default). It builds and tests Stack with the following flags: `--haddock --no-haddock-deps`. Its approach to creating a cache depends on the operating system. Its 'Cache @@ -606,7 +663,7 @@ [Stan](https://hackage.haskell.org/package/stan) is a Haskell static analysis tool. As of `stan-0.1.0.1`, it supports GHC >= 9.6.3 and Stack is built with -GHC 9.6.5. The tool is configured by the contents of the `.stan.toml` file. +GHC 9.6.6. The tool is configured by the contents of the `.stan.toml` file. This workflow will run if: @@ -735,7 +792,7 @@ ~~~ A cradle is not committed to Stack's repository because it imposes a choice of -build tool. +tool used for building. ## Dev Containers
doc/ChangeLog.md view
@@ -1,5 +1,102 @@ # Changelog +## v3.1.1 2024-07-28 + +Release notes: + +* The change in major version from 2.x to 3.1 marks the dropping of support for + versions of GHC before 8.4, deprecated in Stack 2.15.1. + +**Changes since v2.15.7:** + +Behavior changes: + +* Stack uses the version of the Cabal package that comes with the specified + version of GHC. Stack no longer supports such Cabal versions before 2.2, which + came with versions of GHC before 8.4. Consequently, the `init` command will + not try LTS Haskell before 12.0. +* The `init` command initialises `stack.yaml` with a `snapshot` key rather than + a `resolver` key. +* After installing GHC or another tool, Stack deletes the archive file which + provided the tool. +* Remove hidden flag `--skip-intermediate-deps`, effectively deprecated since + Stack 1.3.0, from `ghci` and `repl` commands. +* The `haddock --haddock-for-hackage` command only seeks to create an archive of + the `<package_version>-docs` directory for build targets and if flags + excluding the building of project packages are not set. +* The predecessor of configuration option `package-index`, `package-indices` + (deprecated in Stack 2.9.3) has been removed as an alternative option. +* If a build target is a package identifier, and the package version is not in + the snapshot or the package index, Stack will report an error when the target + is parsed. Previously, if another version of the package was in the snapshot, + Stack would construct the build plan with that other version or, if it was + not, Stack would defer an error to the construction of the build plan. +* The `list` command, with a specified snapshot and package, also reports the + version of the package included indirectly in the snapshot (as a boot package + of the compiler specified by the snapshot). +* `stack build --flag *:[-]<flag_name>` now only applies the flag setting to + packages for which the Cabal flag is defined, as opposed to all packages. +* On Unix-like operating systems, drop support for `/etc/stack/config`, + deprecated in Stack 0.1.6.0. +* Drop support for, in the Stack root, directory `global` and file `stack.yaml`, + both deprecated in Stack 0.1.6.0. + +Other enhancements: + +* Bump to Hpack 0.37.0. +* In YAML configuration files, the `msys-environment` key is introduced to + allow, on Windows, the MSYS2 environment to be specified. The default + environment is still `MINGW64` on 64-bit Windows and `MINGW32` on 32-bit + Windows. +* In YAML configuration files, the `default-init-snapshot` key is introduced to + allow a default snapshot to be specified for use with the `stack init` + command, as if it had been specified at the command line. +* Add flags `--haddock-executables`, `--haddock-tests` and + `--haddock-benchmarks` to Stack's `build` command (including the `haddock` + synonym for `build --haddock`) to enable also building Haddock + documentation for executables, test suites and benchmarks. Due to a bug in + Cabal (the library), Stack will ignore the flags with a warning for GHC + versions before 9.4. +* Add flag `--[no-]save-hackage-creds` to Stack's `upload` command, which takes + precedence over the existing `save-hackage-creds` configuration option. +* In YAML configuration files, the `global-hints-location` key is introduced to + allow the location of the global hints YAML specification file to be + specified. +* By default, Hpack 0.20.0 or later will decline to overwrite a Cabal file that + was modified manually. In YAML configuration files, the `hpack-force` key is + introduced to allow Hpack to overwrite such a Cabal file. The corresponding + `--hpack-force` flag is also added. +* Add the `stack config set recommend-stack-upgrade` command to configure + whether or not Stack should notify the user if it identifes a new version of + Stack is available in YAML configuration files. +* Add the `ls globals` command to list all global packages for the version of + GHC specified by the snapshot. +* Add `stack -h` (equivalent to `stack --help`). +* In YAML configuration files, the `file-watch-hook` key is introduced to allow + `--file-watch` post-processing to be customised with a executable or `sh` + shell script. +* Add flag `--[no-]allow-newer` to Stack's `build` command, which takes + precedence over the existing `allow-newer` configuration option. + +Bug fixes: + +* The `config set snapshot` and `config set resolver` commands now respect the + presence of a synoymous key. +* The `config set` commands support existing keys only in the form `key: value` + on a single line. The commands now recognise that a line `key:` does not have + that form. +* On Unix-like operating systems, the `test --coverage` command now finds + package keys even for very long package names. +* The Error S-6362 message now acknowledges when the wanted compiler has been + specified at the command line. +* Fix a regression, introduced in Stack 2.11.1, that caused the `script` command + to parse an (otherwise ignored) project-level configuration file. +* Stack no longer makes recommendations about a project-level configuration file + when only a global configuration file is in use. +* Fix a regression, introduced in Stack 2.15.7, that caused GHC 8.10.7 or + earlier to fail to build a package with a `Custom` build type, if GHC option + `-haddock` was specified. + ## v2.15.7 - 2024-05-12 Release notes: @@ -273,6 +370,11 @@ * On Windows, `stack upgrade` does not offer `sudo` command alternatives if attempting to write to the original file name of the running Stack exectuable results in a 'Permission' error. +* On Linux, Stack's `setup` command now distinguishes GHC build + `tinfo6-libc6-pre232` from existing `tinfo6`. The former refers to systems + where the version of `libc6` (the GNU C Library) is not compatible with + version 2.32. `tinfo6-libc6-pre232` is now a possible value for the + `ghc-build` configuration option. Other enhancements: @@ -1221,9 +1323,9 @@ [help file](https://github.com/commercialhaskell/stack-templates/blob/master/STACK_HELP.md) with more information on how to discover templates. See: [#4039](https://github.com/commercialhaskell/stack/issues/4039) -* Build tools are now handled in a similar way to `cabal-install`. In - particular, for legacy `build-tools` fields, we use a hard-coded - list of build tools in place of looking up build tool packages in a +* Tools used during building ('build tools') are now handled in a similar way to + `cabal-install`. In particular, for legacy `build-tools` fields, we use a + hard-coded list of build tools in place of looking up build tool packages in a tool map. This both brings Stack's behavior closer into line with `cabal-install`, avoids some bugs, and opens up some possible optimizations/laziness. See:
− doc/GUIDE.md
@@ -1,1483 +0,0 @@- <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# User guide (introductory) - -Stack is a modern, cross-platform build tool for Haskell code. - -This introductory guide takes a new Stack user through the typical workflows. -This guide will not teach Haskell or involve much code, and it requires no prior -experience with the Haskell packaging system or other build tools. Terms used in -the guide are defined in the [glossary](glossary.md). - -Some of Stack's features will not be needed regularly or by all users. See the -[advanced user's guide](GUIDE_advanced.md) for information about those features. - -## Stack's functions - -Stack handles the management of your toolchain (including GHC — the Glasgow -Haskell Compiler — and, for Windows users, MSYS2), building and registering -libraries, building build tool dependencies, and more. While it can use existing -tools on your system, Stack has the capacity to be your one-stop shop for all -Haskell tooling you need. This guide will follow that Stack-centric approach. - -### What makes Stack special? - -The primary Stack design point is __reproducible builds__. If you run -`stack build` today, you should get the same result running `stack build` -tomorrow. There are some cases that can break that rule (changes in your -operating system configuration, for example), but, overall, Stack follows this -design philosophy closely. To make this a simple process, Stack uses curated -package sets called __snapshots__. - -Stack has also been designed from the ground up to be user friendly, with an -intuitive, discoverable command line interface. For many users, simply -downloading Stack and reading `stack --help` will be enough to get up and -running. This guide provides a more gradual tour for users who prefer that -learning style. - -To build your project, Stack uses a project-level configuration file, named -`stack.yaml`, in the root directory of your project as a sort of blueprint. That -file contains a reference to the snapshot (also known as a __resolver__) which -your package will be built against. - -Finally, Stack is __isolated__: it will not make changes outside of specific -Stack directories. Stack-built files generally go in either the Stack root -directory or `./.stack-work` directories local to each project. The -[Stack root](stack_root.md) directory holds packages belonging to snapshots and -any Stack-installed versions of GHC. Stack will not tamper with any system -version of GHC or interfere with packages installed by other build tools, such -as Cabal (the tool). - -## Downloading and Installation - -The [documentation dedicated to downloading Stack](install_and_upgrade.md) has -the most up-to-date information for a variety of operating systems. Instead of -repeating that content here, please go check out that page and come back here -when you can successfully run `stack --version`. - -We also assume that the directory reported by `stack path --local-bin` has been -added to the PATH. - -## Hello World Example - -With Stack installed, let's create a new project from a template and walk -through the most common Stack commands. - -In this guide, an initial `$` represents the command line prompt. The prompt may -differ in the terminal on your operating system. Unless stated otherwise, the -working directory is the project's root directory. - -### The `stack new` command - -We'll start off with the `stack new` command to create a new *project*, that -will contain a Haskell *package* of the same name. So let's pick a valid -package name first: - -> A package is identified by a globally-unique package name, which consists -> of one or more alphanumeric words separated by hyphens. To avoid ambiguity, -> each of these words should contain at least one letter. - -(From the -[Cabal users guide](https://www.haskell.org/cabal/users-guide/developing-packages.html#developing-packages)) - -We'll call our project `helloworld`, and we'll use the `new-template` project -template. This template is used by default, but in our example we will refer to -it expressly. Other templates are available. For further information about -templates, see the `stack templates` command -[documentation](templates_command.md). - -From the root directory for all our Haskell projects, we command: - -~~~text -stack new helloworld new-template -~~~ - -For this first Stack command, there's quite a bit of initial setup it needs to -do (such as downloading the list of packages available upstream), so you'll see -a lot of output. Over the course of this guide a lot of the content will begin -to make more sense. - -After creating the project directory, and obtaining and populating the project -template, Stack will initialise its own project-level configuration. For further -information about setting paramaters to populate templates, see the YAML -configuration [documentation](yaml_configuration.md#templates). For further -information about initialisation, see the `stack init` command -[documentation](#the-stack-init-command). The `stack new` and `stack init` -commands have options and flags in common. - -!!! info - - Pass the `--bare` flag to cause Stack to create the project in the current - working directory rather than in a new project directory. - -!!! info - - Parameters to populate project templates can be set at the command line with - the `--param <key>:<value>` (or `-p`) option. - -We now have a project in the `helloworld` directory! We will change to that -directory, with command: - -~~~text -cd helloworld -~~~ - -### The `stack build` command - -Next, we'll run the most important Stack command, `stack build`: - -~~~text -stack build -# installing ... building ... -~~~ - -Stack needs a version of GHC in order to build your project. Stack will discover -that you are missing it and will install it for you. - -You'll get intermediate download percentage statistics while the download is -occurring. This command may take some time, depending on download speeds. - -!!! note - - GHC will be installed to your Stack programs directory, so calling `ghc` on - the command line won't work. See the `stack exec`, `stack ghc`, and - `stack runghc` commands below for more information. - -Once a version of GHC is installed, Stack will then build your project. - -### The `stack exec` command - -Looking closely at the output of the previous command, you can see that it built -both a library called `helloworld` and an executable called `helloworld-exe` (on -Windows, `helloworld-exe.exe`). We'll explain more in the next section, but, for -now, just notice that the executables are installed in a location in our -project's `.stack-work` directory. - -Now, Let's use the `stack exec` command to run our executable (which just -outputs "someFunc"): - -~~~text -stack exec helloworld-exe -someFunc -~~~ - -`stack exec` works by providing the same reproducible environment that was used -to build your project to the command that you are running. Thus, it knew where -to find `helloworld-exe` even though it is hidden in the `.stack-work` -directory. Command `stack path --bin-path` to see the PATH in the Stack -environment. - -!!! info - - On Windows, the Stack environment includes the `\mingw64\bin`, `\usr\bin` - and `\usr\local\bin` directories of the Stack-supplied MSYS2. If your - executable depends on files (for example, dynamic-link libraries) in those - directories and you want ro run it outside of the Stack environment, you - will need to ensure copies of those files are on the PATH. - -### The `stack test` command - -Finally, like all good software, `helloworld` actually has a test suite. - -Let's run it with the `stack test` command: - -~~~text -stack test -# build output ... -~~~ - -Reading the output, you'll see that Stack first builds the test suite and then -automatically runs it for us. For both the `build` and `test` command, already -built components are not built again. You can see this by using the -`stack build` and `stack test` commands a second time: - -~~~text -stack build -stack test -# build output ... -~~~ - -## Inner Workings of Stack - -In this subsection, we'll dissect the `helloworld` example in more detail. - -### Files in helloworld - -Before studying Stack more, let's understand our project a bit better. The files -in the directory include: - -~~~text -app/Main.hs -src/Lib.hs -test/Spec.hs -ChangeLog.md -README.md -LICENSE -Setup.hs -helloworld.cabal -package.yaml -stack.yaml -.gitignore -~~~ - -The `app/Main.hs`, `src/Lib.hs`, and `test/Spec.hs` files are all Haskell -source files that compose the actual functionality of our project (we won't -dwell on them here). - -The `ChangeLog.md`, `README.md`, `LICENSE` and `.gitignore` files have no effect -on the build. - -The `helloworld.cabal` file is updated automatically as part of the -`stack build` process and should not be modified. - -The files of interest here are `Setup.hs`, `stack.yaml`, and `package.yaml`. - -The `Setup.hs` file is a component of the Cabal build system which Stack uses. -It's technically not needed by Stack, but it is still considered good practice -in the Haskell world to include it. The file we're using is straight -boilerplate: - -~~~haskell -import Distribution.Simple -main = defaultMain -~~~ - -Next, let's look at our `stack.yaml` file, which gives our project-level -settings. Ignoring comments beginning `#`, the contents will look something like -this: - -~~~yaml -resolver: - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/21.yaml -packages: -- . -~~~ - -The value of the [`resolver`](yaml_configuration.md#resolver) key tells Stack -*how* to build your package: which GHC version to use, versions of package -dependencies, and so on. Our value here says to use -[LTS Haskell 22.21](https://www.stackage.org/lts-22.21), which implies GHC 9.6.5 -(which is why `stack build` installs that version of GHC if it is not already -available to Stack). There are a number of values you can use for `resolver`, -which we'll cover later. - -The value of the `packages` key tells Stack which project packages, located -locally, to build. In our simple example, we have only a single project package, -located in the same directory, so '`.`' suffices. However, Stack has powerful -support for multi-package projects, which we'll elaborate on as this guide -progresses. - -Another file important to the build is `package.yaml`. - -The `package.yaml` file describes the package in the -[Hpack](https://github.com/sol/hpack) format. Stack has in-built Hpack -functionality and this is its preferred package format. The default behaviour is -to generate the Cabal file (here named `helloworld.cabal`) from this -`package.yaml` file, and accordingly you should **not** modify the Cabal file. - -It is also important to remember that Stack is built on top of the Cabal build -system. Therefore, an understanding of the moving parts in Cabal are necessary. -In Cabal, we have individual *packages*, each of which contains a single Cabal -file, named `<package_name>.cabal`. The Cabal file can define one or more -*components*: a library, executables, test suites, and benchmarks. It also -specifies additional information such as library dependencies, default -language pragmas, and so on. - -In this guide, we'll discuss the bare minimum necessary to understand how to -modify a `package.yaml` file. You can see a full list of the available options -at the [Hpack documentation](https://github.com/sol/hpack#quick-reference). The -Cabal User Guide is the definitive reference for the -[Cabal file format](https://cabal.readthedocs.io/en/stable/cabal-package.html). - -### The location of GHC - -As we saw above, the `build` command installed GHC for us. You can use the -`stack path` command for quite a bit of path information (which we'll play with -more later). We'll look at where GHC is installed: - -=== "Unix-like" - - Command: - - ~~~text - stack exec -- which ghc - /home/<user_name>/.stack/programs/x86_64-linux/ghc-9.0.2/bin/ghc - ~~~ - -=== "Windows (with PowerShell)" - - Command: - - ~~~text - stack exec -- where.exe ghc - C:\Users\<user_name>\AppData\Local\Programs\stack\x86_64-windows\ghc-9.0.2\bin\ghc.exe - ~~~ - -As you can see from that path (and as emphasized earlier), the installation is -placed to not interfere with any other GHC installation, whether system-wide or -even different GHC versions installed by Stack. - -## Cleaning your project - -You can clean up build artifacts for your project using the `stack clean` and -`stack purge` commands. - -### The `stack clean` command - -`stack clean` deletes the local working directories containing compiler output. -By default, that means the contents of directories in `.stack-work/dist`, for -all the `.stack-work` directories within a project. - -Use `stack clean <specific-package>` to delete the output for the package -_specific-package_ only. - -### The `stack purge` command - -`stack purge` deletes the local stack working directories, including extra-deps, -git dependencies and the compiler output (including logs). It does not delete -any snapshot packages, compilers or programs installed using `stack install`. -This essentially reverts the project to a completely fresh state, as if it had -never been built. `stack purge` is just a shortcut for `stack clean --full` - -### The `stack build` command - -The `build` command is the heart and soul of Stack. It is the engine that powers -building your code, testing it, getting dependencies, and more. Quite a bit of -the remainder of this guide will cover more advanced `build` functions and -features, such as building test and Haddocks at the same time, or constantly -rebuilding blocking on file changes. - -!!! note - - Using the `build` command twice with the same options and arguments should - generally do nothing (besides things like rerunning test suites), and - should, in general, produce a reproducible result between different runs. - -## Adding dependencies - -Let's say we decide to modify our `helloworld` source a bit to use a new -library, perhaps the ubiquitous `text` package. In `src/Lib.hs`, we can, for -example add: - -~~~haskell -{-# LANGUAGE OverloadedStrings #-} -module Lib - ( someFunc - ) where - -import qualified Data.Text.IO as T - -someFunc :: IO () -someFunc = T.putStrLn "someFunc" -~~~ - -When we try to build this, things don't go as expected: - -~~~text -stack build -# build failure output (abridged for clarity) ... -src\Lib.hs:6:1: error: - Could not load module ‘Data.Text.IO’ - It is a member of the hidden package ‘text-1.2.5.0’. - Perhaps you need to add ‘text’ to the build-depends in your .cabal file. - Use -v (or `:set -v` in ghci) to see a list of the files searched for. - | -6 | import qualified Data.Text.IO as T - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -~~~ - -This means that the package containing the module in question is not available. -To tell Stack to use [text](https://hackage.haskell.org/package/text), you need -to add it to your `package.yaml` file — specifically in your `dependencies` -section, like this: - -~~~yaml -dependencies: -- base >= 4.7 && < 5 -- text # added here -~~~ - -Now if we rerun `stack build`, we should get a successful result. Command: - -~~~text -stack build -# build output ... -~~~ - -This output means that the `text` package was downloaded, configured, built, and -locally installed. Once that was done, we moved on to building our project -package (`helloworld`). At no point did we need to ask Stack to build -dependencies — it does so automatically. - -### Listing Dependencies - -Let's have Stack add a few more dependencies to our project. First, we'll -include two new packages in the `dependencies` section for our library in our -`package.yaml`: - -~~~yaml -dependencies: -- base >= 4.7 && < 5 -- text -- filepath -- containers -~~~ - -After adding these two dependencies, we can again run `stack build` to have them -installed. Command: - -~~~text -stack build -# build output ... -~~~ - -Finally, to find out which versions of these libraries Stack installed, we can -ask Stack to `ls dependencies`. Command: - -~~~text -stack ls dependencies -# dependency output ... -~~~ - -### extra-deps - -Let's try a more off-the-beaten-track package: the joke -[acme-missiles](http://www.stackage.org/package/acme-missiles) package. Our -source code is simple: - -~~~haskell -module Lib - ( someFunc - ) where - -import Acme.Missiles - -someFunc :: IO () -someFunc = launchMissiles -~~~ - -Again, we add this new dependency to the `package.yaml` file like this: - -~~~yaml -dependencies: -- base >= 4.7 && < 5 -- text -- filepath -- containers -- acme-missiles # added -~~~ - -However, rerunning `stack build` shows us the following error message. Command: - -~~~text -stack build -# build failure output ... -~~~ - -It says that it was unable to construct the build plan. - -This brings us to the next major topic in using Stack. - -## Curated package sets - -Remember above when `stack new` selected some -[LTS snapshot](https://github.com/commercialhaskell/lts-haskell#readme) for us? -That defined our build plan and available packages. When we tried using the -`text` package, it just worked, because it was part of the LTS *package set*. - -We've specified the `acme-missiles` package in the `package.yaml` file (see -above), but `acme-missiles` is not part of that LTS package set, so building -failed. - -To add `acme-missiles` to the available packages, we'll use the `extra-deps` key -in the `stack.yaml` file. That key defines extra packages, not present in the -snapshot, that will be needed as dependencies. You can add this like so: - -~~~yaml -extra-deps: -- acme-missiles-0.3 # not in the LTS snapshot -~~~ - -Now `stack build` will succeed. - -With that out of the way, let's dig a little bit more into these package sets, -also known as *snapshots*. We mentioned the LTS snapshots, and you can get quite -a bit of information about it at -[https://www.stackage.org/lts](https://www.stackage.org/lts), including: - -* The appropriate value (`lts-22.13`, as is currently the latest LTS) -* The GHC version used -* A full list of all packages available in this snapshot -* The ability to perform a Hoogle search on the packages in this snapshot -* A [list of all modules](https://www.stackage.org/lts/docs) in a snapshot, - which can be useful when trying to determine which package to add to your - `package.yaml` file. - -You can also see a -[list of all available snapshots](https://www.stackage.org/snapshots). You'll -notice two flavors: LTS (for "Long Term Support") and Nightly. You can read more -about them on the -[LTS Haskell GitHub page](https://github.com/commercialhaskell/lts-haskell#readme). -If you're not sure which to use, start with LTS Haskell (which Stack will lean -towards by default as well). - -## Snapshots and changing your compiler version - -Let's explore package sets a bit further. Instead of `lts-22.13`, let's change -our `stack.yaml` file to use the -[latest nightly](https://www.stackage.org/nightly). Right now, this is currently -2024-03-20 - please see the snapshot from the link above to get the latest. - -Then, commanding `stack build` again will produce: - -~~~text -stack build -# Downloaded nightly-2024-03-20 build plan. -# build output ... -~~~ - -We can also change snapshots on the command line, which can be useful in a -Continuous Integration (CI) setting, like on Travis. For example, command: - -~~~text -stack --snapshot lts-21.25 build -# Downloaded lts-21.25 build plan. -# build output ... -~~~ - -When passed on the command line, you also get some additional "short-cut" -versions of snapshots: `--snapshot nightly` will use the newest Nightly snapshot -available, `--snapshot lts` will use the newest LTS, and `--snapshot lts-22` -will use the newest LTS in the 22.x series. The reason these are only available -on the command line and not in your `stack.yaml` file is that using them: - -1. Will slow down your build (since Stack then needs to download information on - the latest available LTS each time it builds) -2. Produces unreliable results (since a build run today may proceed differently - tomorrow because of changes outside of your control) - -### Changing GHC versions - -Finally, let's try using an older LTS snapshot. We'll use the newest 21.x -snapshot with the command: - -~~~text -stack --snapshot lts-21 build -# build output ... -~~~ - -This succeeds, automatically installing the necessary GHC along the way. So, we -see that different LTS versions use different GHC versions and Stack can handle -that. - -### Other snapshot values - -We've mentioned `nightly-YYYY-MM-DD` and `lts-X.Y` values for the snapshot. -There are actually other options available, and the list will grow over time. -At the time of writing: - -* `ghc-X.Y.Z`, for requiring a specific GHC version but no additional packages -* Experimental custom snapshot support - -The most up-to-date information can always be found in the -[stack.yaml documentation](yaml_configuration.md#snapshot). - -## Existing projects - -Alright, enough playing around with simple projects. Let's take an open source -package and try to build it. We'll be ambitious and use -[yackage](https://hackage.haskell.org/package/yackage), a local package server -using [Yesod](http://www.yesodweb.com/). To get the code, we'll use the -`stack unpack` command from the root directory for all our Haskell projects: - -~~~text -stack unpack yackage -Unpacked yackage-0.8.1 to <root_directory>/yackage-0.8.1/ -~~~ - -You can also unpack to the directory of your liking instead of the current one -by issuing the command: - -~~~text -stack unpack yackage --to <desired_directory> -~~~ - -This will create a `yackage-0.8.1` directory inside `<desired_directory>`. - -We will change to that directory, with the command: - -~~~text -cd yackage-0.8.1 -~~~ - -### The `stack init` command - -This new directory does not have a `stack.yaml` file, so we need to make one -first. We could do it by hand, but let's be lazy instead with the `stack init` -command: - -~~~text -stack init -# init output ... -~~~ - -`stack init` does quite a few things for you behind the scenes: - -* Finds all of the Cabal files in your current directory and subdirectories - (unless you use `--ignore-subdirs`) and determines the packages and versions - they require -* Finds the best combination of snapshot and package flags that allows - everything to compile with minimum external dependencies -* It tries to look for the best matching snapshot from latest LTS, latest - nightly, other LTS versions in that order - -Assuming it finds a match, it will write your `stack.yaml` file, and everything -will work. - -!!! note - - The `yackage` package does not currently support Hpack, but you can also use - `hpack-convert` should you need to generate a `package.yaml` file. - -#### Excluded Packages - -Sometimes multiple packages in your project may have conflicting requirements. -In that case `stack init` will fail, so what do you do? - -You could manually create `stack.yaml` by omitting some packages to resolve the -conflict. Alternatively you can ask `stack init` to do that for you by -specifying `--omit-packages` flag on the command line. Let's see how that -works. - -To simulate a conflict we will use `acme-missiles-0.3` in `yackage` and we will -also copy `yackage.cabal` to another directory and change the name of the file -and package to `yackage-test`. In this new package we will use -`acme-missiles-0.2` instead. Let's see what happens when we command `stack init` -again: - -~~~text -stack init --force --omit-packages -# init failure output ... -~~~ - -Looking at `stack.yaml`, you will see that the excluded packages have been -commented out under the `packages` field. In case wrong packages are excluded -you can uncomment the right one and comment the other one. - -Packages may get excluded due to conflicting requirements among user packages or -due to conflicting requirements between a user package and the snapshot -compiler. If all of the packages have a conflict with the compiler then all of -them may get commented out. - -When packages are commented out you will see a warning every time you run a -command which needs the configuration file. The warning can be disabled by -editing the configuration file and removing it. - -#### Using a specific snapshot - -Sometimes you may want to use a specific snapshot for your project instead of -`stack init` picking one for you. You can do that by using -`stack init --snapshot <snapshot>`. - -You can also init with a compiler snapshot if you do not want to use a -Stackage snapshot. That will result in all of your project's dependencies being -put under the `extra-deps` section. - -#### Installing the compiler - -Stack will automatically install the compiler when you run `stack build` but you -can manually specify the compiler by running `stack setup <GHC-VERSION>`. - -#### Miscellaneous and diagnostics - -_Add selected packages_: If you want to use only selected packages from your -project directory you can do so by explicitly specifying the package directories -on the command line. - -_Duplicate package names_: If multiple packages under the directory tree have -same name, `stack init` will report those and automatically ignore one of them. - -_Ignore subdirectories_: By default `stack init` searches all the subdirectories -for Cabal files. If you do not want that then you can use `--ignore-subdirs` -command line switch. - -_Cabal warnings_: `stack init` will show warnings if there were issues in -reading a Cabal file. You may want to pay attention to the warnings as sometimes -they may result in incomprehensible errors later on during dependency solving. - -_Package naming_: If the `Name` field defined in a Cabal file does not match -with the Cabal file name then `stack init` will refuse to continue. - -_User warnings_: When packages are excluded or external dependencies added Stack -will show warnings every time the configuration file is loaded. You can suppress -the warnings by editing the configuration file and removing the warnings from -it. You may see something like this: - -~~~text -stack build -Warning: Some packages were found to be incompatible with the resolver and have been left commented out in the packages section. -Warning: Specified resolver could not satisfy all dependencies. Some external packages have been added as dependencies. -You can suppress this message by removing it from stack.yaml -~~~ - -## Different databases - -Time to take a short break from hands-on examples and discuss a little -architecture. Stack has the concept of multiple *databases*. - -A database consists of a GHC package database (which contains the compiled -version of a library), executables, and a few other things as well. To give you -an idea, the contents of the parent directory of the `stack path --local-pkg-db` -directory are the directories: - -~~~text -bin -doc -lib -pkgdb -~~~ - -Databases in Stack are *layered*. For example, the database listing we just gave -is called a *local* database (also known as a *mutable* database). That is -layered on top of a *snapshot* database (also known as a *write-only* database). -The snapshot database contains the libraries and executables that are considered -to be *immutable*. Finally, GHC itself ships with a number of libraries and -executables, also considered to be immutable, which forms the *global* database. - -To get a quick idea of this, we can look at the output of the -`stack exec -- ghc-pkg list` command in our `helloworld` project: - -~~~text -<stack path --global-pkg-db directory> - Cabal-3.6.3.0 - Win32-2.12.0.1 - array-0.5.4.0 - base-4.16.2.0 - binary-0.8.9.0 - bytestring-0.11.3.1 - containers-0.6.5.1 - deepseq-1.4.6.1 - directory-1.3.6.2 - exceptions-0.10.4 - filepath-1.4.2.2 - (ghc-9.2.3) - ghc-bignum-1.2 - ghc-boot-9.2.3 - ghc-boot-th-9.2.3 - ghc-compact-0.1.0.0 - ghc-heap-9.2.3 - ghc-prim-0.8.0 - ghci-9.2.3 - haskeline-0.8.2 - hpc-0.6.1.0 - integer-gmp-1.1 - libiserv-9.2.3 - mtl-2.2.2 - parsec-3.1.15.0 - pretty-1.1.3.6 - process-1.6.13.2 - rts-1.0.2 - stm-2.5.0.2 - template-haskell-2.18.0.0 - text-1.2.5.0 - time-1.11.1.1 - transformers-0.5.6.2 - xhtml-3000.2.2.1 - -<stack path --snapshot-pkg-db directory> - acme-missiles-0.3 - -<stack path --local-pkg-db directory> - helloworld-0.1.0.0 -~~~ - -where `<stack path --global-pkg-db directory>` refers to the directory output by -the command `stack path --global-pkg-db`, and so on. - -Notice that `acme-missiles` ends up in the *snapshot* database. Any package -which comes from Hackage, an archive, or a repository is considered to be an -*immutable* package. - -Anything which is considered *mutable*, or depends on something mutable, ends up -in the *local* database. This includes your own code and any other packages -located on a local file path. - -The reason we have this structure is that: - -* it lets multiple projects reuse the same binary builds of immutable packages, -* but doesn't allow different projects to "contaminate" each other by putting - non-standard content into the shared snapshot database. - -As you probably guessed, there can be multiple snapshot databases available. See -the contents of the `snapshots` directory in the [Stack root](stack_root.md). - -* On Unix-like operating systems, each snapshot is in the last of a sequence of - three subdirectories named after the platform, a 256-bit hash of the source - map (how the package should be built -- including the compiler, options, and - immutable dependencies), and the GHC version. - -* On Windows, each snapshot is in a subdirectory that is a shorter hash (eight - characters) of the sequence of three directories used on Unix-like operating - systems. This is done to avoid problems created by default limits on file - path lengths on Windows systems. - -These snapshot databases don't get layered on top of each other; they are each -used separately. - -In reality, you'll rarely — if ever — interact directly with these databases, -but it's good to have a basic understanding of how they work so you can -understand why rebuilding may occur at different points. - -## The build synonyms - -Let's look at a subset of the `stack --help` output: - -~~~text -build Build the package(s) in this directory/configuration -install Shortcut for 'build --copy-bins' -test Shortcut for 'build --test' -bench Shortcut for 'build --bench' -haddock Shortcut for 'build --haddock' -~~~ - -Four of these commands are just synonyms for the `build` command. They are -provided for convenience for common cases (e.g., `stack test` instead of -`stack build --test`) and so that commonly expected commands just work. - -What's so special about these commands being synonyms? It allows us to make -much more composable command lines. For example, we can have a command that -builds executables, generates Haddock documentation (Haskell API-level docs), -and builds and runs your test suites, with: - -~~~text -stack build --haddock --test -~~~ - -You can even get more inventive as you learn about other flags. For example, -take the following command: - -~~~text -stack build --pedantic --haddock --test --exec "echo Yay, it succeeded" --file-watch -~~~ - -This command will: - -* turn on all warnings and errors (the `--pedantic` flag) -* build your library and executables -* generate Haddocks (the `--haddock` flag) -* build and run your test suite (the `--test` flag) -* run the command `echo Yay, it succeeded` when that completes (the `--exec` - option) -* after building, watch for changes in the files used to build the project, and - kick off a new build when done (the `--file-watch` flag) - -### The `stack install` command and `copy-bins` option - -It's worth calling out the behavior of the `install` command and `--copy-bins` -option, since this has confused a number of users (especially when compared to -behavior of other tools like Cabal (the tool)). The `install` command does -precisely one thing in addition to the build command: it copies any generated -executables to the local binary directory. You may recognize the default value -for that path: - -On Unix-like operating systems, command: - -~~~text -stack path --local-bin -/home/<user_name>/.local/bin -~~~ - -On Windows, command: - -~~~text -stack path --local-bin -C:\Users\<user_name>\AppData\Roaming\local\bin -~~~ - -That's why the download page recommends adding that directory to your PATH. This -feature is convenient, because now you can simply run `executable-name` in your -shell instead of having to run `stack exec executable-name` from inside your -project directory. - -Since it's such a point of confusion, let me list a number of things Stack does -*not* do specially for the `install` command: - -* Stack will always build any necessary dependencies for your code. The install - command is not necessary to trigger this behavior. If you just want to build a - project, run `stack build`. -* Stack will *not* track which files it's copied to your local binary directory - nor provide a way to automatically delete them. There are many great tools out - there for managing installation of binaries, and Stack does not attempt to - replace those. -* Stack will not necessarily be creating a relocatable executable. If your - executables hard-codes paths, copying the executable will not change those - hard-coded paths. - - * At the time of writing, there's no way to change those kinds of paths with - Stack, but see - [issue #848 about --prefix](https://github.com/commercialhaskell/stack/issues/848) - for future plans. - -That's really all there is to the `install` command: for the simplicity of what -it does, it occupies a much larger mental space than is warranted. - -## Targets, locals, and extra-deps - -We haven't discussed this too much yet, but, in addition to having a number of -synonyms *and* taking a number of options on the command line, the `build` -command *also* takes many arguments. These are parsed in different ways, and can -be used to achieve a high level of flexibility in telling Stack exactly what you -want to build. - -We're not going to cover the full generality of these arguments here; instead, -there's documentation covering the full -[build command syntax](build_command.md). Here, we'll just point out a few -different types of arguments: - -* You can specify a *package name*, e.g. `stack build vector`. - * This will attempt to build the `vector` package, whether it's a local - package, in your extra-deps, in your snapshot, or just available upstream. - If it's just available upstream but not included in your locals, - extra-deps, or snapshot, the newest version is automatically promoted to - an extra-dep. -* You can also give a *package identifier*, which is a package name plus - version, e.g. `stack build yesod-bin-1.4.14`. - * This is almost identical to specifying a package name, except it will (1) - choose the given version instead of latest, and (2) error out if the given - version conflicts with the version of a project package. -* The most flexibility comes from specifying individual *components*, e.g. - `stack build helloworld:test:helloworld-test` says "build the test suite - component named helloworld-test from the helloworld package." - * In addition to this long form, you can also shorten it by skipping what - type of component it is, e.g. `stack build helloworld:helloworld-test`, or - even skip the package name entirely, e.g. `stack build :helloworld-test`. -* Finally, you can specify individual *directories* to build to trigger building - of any project packages included in those directories or subdirectories. - -When you give no specific arguments on the command line (e.g., `stack build`), -it's the same as specifying the names of all of your project packages. If you -just want to build the package for the directory you're currently in, you can -use `stack build .`. - -### Components, --test, and --bench - -Here's one final important yet subtle point. Consider our `helloworld` package: -it has a library component, an executable `helloworld-exe`, and a test suite -`helloworld-test`. When you run `stack build helloworld`, how does it know which -ones to build? By default, it will build the library (if any) and all of the -executables but ignore the test suites and benchmarks. - -This is where the `--test` and `--bench` flags come into play. If you use them, -those components will also be included. So `stack build --test helloworld` will -end up including the helloworld-test component as well. - -You can bypass this implicit adding of components by being much more explicit, -and stating the components directly. For example, the following will not build -the `helloworld-exe` executable: - -~~~text -stack purge -stack build :helloworld-test -helloworld> configure (lib + test) -Configuring helloworld-0.1.0.0... -helloworld> build (lib + test) with ghc-9.6.5 -Preprocessing library for helloworld-0.1.0.0.. -Building library for helloworld-0.1.0.0.. -[1 of 2] Compiling Lib -[2 of 2] Compiling Paths_helloworld -Preprocessing test suite 'helloworld-test' for helloworld-0.1.0.0.. -Building test suite 'helloworld-test' for helloworld-0.1.0.0.. -[1 of 2] Compiling Main -[2 of 2] Compiling Paths_helloworld -[3 of 3] Linking .stack-work\dist\<hash>\build\helloworld-test\helloworld-test.exe -helloworld> copy/register -Installing library in ...\helloworld\.stack-work\install\... -Registering library for helloworld-0.1.0.0.. -helloworld> test (suite: helloworld-test) - -Test suite not yet implemented - - - -helloworld> Test suite helloworld-test passed -Completed 2 action(s). -~~~ - -We first purged our project to clear old results so we know exactly what Stack -is trying to do. - -The last line shows that our command also *runs* the test suite it just built. -This may surprise some people who would expect tests to only be run when using -`stack test`, but this design decision is what allows the `stack build` command -to be as composable as it is (as described previously). The same rule applies to -benchmarks. To spell it out completely: - -* The `--test` and `--bench` flags simply state which components of a package - should be built, if no explicit set of components is given -* The default behavior for any test suite or benchmark component which has been - built is to also run it - -You can use the `--no-run-tests` and `--no-run-benchmarks` flags to disable -running of these components. You can also use `--no-rerun-tests` to prevent -running a test suite which has already passed and has not changed. - -!!! note - - Stack doesn't build or run test suites and benchmarks for non-local - packages. This is done so that a command like `stack test` doesn't need to - run 200 test suites! - -## Multi-package projects - -Until now, everything we've done with Stack has used a single-package project. -However, Stack's power truly shines when you're working on multi-package -projects. All the functionality you'd expect to work just does: dependencies -between packages are detected and respected, dependencies of all packages are -just as one cohesive whole, and if anything fails to build, the build commands -exits appropriately. - -Let's demonstrate this with the `wai-app-static` and `yackage` packages, -starting in the root directory for all our Haskell projects. Command: - -~~~text -mkdir multi -cd multi -stack unpack wai-app-static yackage -Unpacked wai-app-static (from Hackage) to .../multi/wai-app-static-3.1.7.4/ -Unpacked yackage (from Hackage) to .../multi/yackage-0.8.1/ -stack init -Looking for .cabal or package.yaml files to use to init the project. -Using cabal packages: -- wai-app-static-3.1.7.4/ -- yackage-0.8.1/ - -Cabal file warning in .../multi/yackage-0.8.1/yackage.cabal@47:40: version operators used. To use version operators the package needs to specify at least 'cabal-version: >= 1.8'. -Cabal file warning in .../multi/yackage-0.8.1/yackage.cabal@21:36: version operators used. To use version operators the package needs to specify at least 'cabal-version: >= 1.8'. -Selecting the best among 18 snapshots... - -* Matches ... - -Selected resolver: ... -Initialising configuration using resolver: ... -Total number of user packages considered: 2 -Writing configuration to file: stack.yaml -stack build --haddock --test -# Goes off to build a whole bunch of packages -~~~ - -If you look at the `stack.yaml` file, you'll see exactly what you'd expect: - -~~~yaml -resolver: - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/17.yaml -packages: -- wai-app-static-3.1.7.4 -- yackage-0.8.1 -~~~ - -Notice that multiple directories are listed in the `packages` key. - -In addition to local directories, you can also refer to packages available in a -Git repository or in a tarball over HTTP/HTTPS. This can be useful for using a -modified version of a dependency that hasn't yet been released upstream. - -!!! note - - When adding upstream packages directly to your project it is important to - distinguish _project packages_ located locally from the upstream - _dependency packages_. Otherwise you may have trouble running `stack ghci`. - See [stack.yaml documentation](yaml_configuration.md#packages) for more - details. - -## Flags and GHC options - -There are two common ways to alter how a package will install: with Cabal flags -and with GHC options. - -### Cabal flag management - -To change a Cabal flag setting, we can use the command line `--flag` option. The -`yackage` package has an `upload` flag that is enabled by default. We can -command: - -~~~text -stack build --flag yackage:-upload -~~~ - -This means: when compiling the `yackage` package, turn off the `upload` flag -(thus the `-` in `-upload`). Unlike other tools, Stack is explicit about which -package's flag you want to change. It does this for two reasons: - -1. There's no global meaning for Cabal flags, and therefore two packages can - use the same flag name for completely different things. -2. By following this approach, we can avoid unnecessarily recompiling snapshot - packages that happen to use a flag that we're using. - -You can also change flag values on the command line for extra-dep and snapshot -packages. If you do this, that package will automatically be promoted to an -extra-dep, since the build plan is different than what the plan snapshot -definition would entail. - -### GHC options - -GHC options follow a similar logic as in managing Cabal flags, with a few -nuances to adjust for common use cases. Let's consider the command: - -~~~text -stack build --ghc-options="-Wall -Werror" -~~~ - -This will set the `-Wall -Werror` options for all *local targets*. Note that -this will not affect extra-dep and snapshot packages at all. This design -provides us with reproducible and fast builds. - -(By the way: the above GHC options have a special convenience flag: -`--pedantic`.) - -There's one extra nuance about command line GHC options: Since they only apply -to local targets, if you change your local targets, they will no longer apply -to other packages. Let's play around with an example from the `wai` repository, -which includes the `wai` and `warp` packages, the latter depending on the -former. If we command again: - -~~~text -stack build --ghc-options=-O0 wai -~~~ - -It will build all of the dependencies of `wai`, and then build `wai` with all -optimizations disabled. Now let's add in `warp` as well. Command: - -~~~text -stack build --ghc-options=-O0 wai warp -~~~ - -This builds the additional dependencies for `warp`, and then builds `warp` with -optimizations disabled. Importantly: it does not rebuild `wai`, since `wai`'s -configuration has not been altered. Now the surprising case. Command: - -~~~text -stack build --ghc-options=-O0 warp -wai-3.0.3.0-5a49351d03cba6cbaf906972d788e65d: unregistering (flags changed from ["--ghc-options","-O0"] to []) -warp-3.1.3-a91c7c3108f63376877cb3cd5dbe8a7a: unregistering (missing dependencies: wai) -wai-3.0.3.0: configure -~~~ - -You may expect this to be a no-op: neither `wai` nor `warp` has changed. -However, Stack will instead recompile `wai` with optimizations enabled again, -and then rebuild `warp` (with optimizations disabled) against this newly built -`wai`. The reason: reproducible builds. If we'd never built `wai` or `warp` -before, trying to build `warp` would necessitate building all of its -dependencies, and it would do so with default GHC options (optimizations -enabled). This dependency would include `wai`. So when we command: - -~~~text -stack build --ghc-options=-O0 warp -~~~ - -We want its behavior to be unaffected by any previous build steps we took. -While this specific corner case does catch people by surprise, the overall goal -of reproducible builds is - in the Stack maintainers' views - worth the -confusion. - -Final point: if you have GHC options that you'll be regularly passing to your -packages, you can add them to your `stack.yaml` file. See the -[documentation section on ghc-options](yaml_configuration.md#ghc-options) -for more information. - -!!! note - - That's it, the heavy content of this guide is done! Everything from here on - out is simple explanations of commands. Congratulations! - -## The `stack path` command - -Generally, you don't need to worry about where Stack stores various files. But -some people like to know this stuff. That's when the `stack path` command is -useful. `stack path --help` explains the available options and, consequently, -the output of the command: - -~~~text ---stack-root Global Stack root directory ---global-config Global Stack configuration file ---project-root Project root (derived from stack.yaml file) ---config-location Configuration location (where the stack.yaml file is) ---bin-path PATH environment variable ---programs Install location for GHC and other core tools (see - 'stack ls tools' command) ---compiler-exe Compiler binary (e.g. ghc) ---compiler-bin Directory containing the compiler binary (e.g. ghc) ---compiler-tools-bin Directory containing binaries specific to a - particular compiler ---local-bin Directory where Stack installs executables (e.g. - ~/.local/bin (Unix-like OSs) or %APPDATA%\local\bin - (Windows)) ---extra-include-dirs Extra include directories ---extra-library-dirs Extra library directories ---snapshot-pkg-db Snapshot package database ---local-pkg-db Local project package database ---global-pkg-db Global package database ---ghc-package-path GHC_PACKAGE_PATH environment variable ---snapshot-install-root Snapshot installation root ---local-install-root Local project installation root ---snapshot-doc-root Snapshot documentation root ---local-doc-root Local project documentation root ---local-hoogle-root Local project documentation root ---dist-dir Dist work directory, relative to package directory ---local-hpc-root Where HPC reports and tix files are stored -~~~ - -In addition, `stack path` accepts the flags above on the command line to state -which keys you're interested in. This can be convenient for scripting. As a -simple example, let's find out the sandboxed versions of GHC that Stack -installed: - -=== "Unix-like" - - Command: - - ~~~text - ls $(stack path --programs)/*.installed - /home/<user_name>/.stack/programs/x86_64-linux/ghc-9.0.2.installed - ~~~ - -=== "Windows (with PowerShell)" - - Command: - - ~~~text - dir "$(stack path --programs)/*.installed" - - Directory: C:\Users\mikep\AppData\Local\Programs\stack\x86_64-windows - - Mode LastWriteTime Length Name - ---- ------------- ------ ---- - -a--- 27/07/2022 5:40 PM 9 ghc-9.0.2.installed - -a--- 25/02/2022 11:39 PM 9 msys2-20210604.installed - ~~~ - -While we're talking about paths, to wipe our Stack install completely, here's -what typically needs to be removed: - -1. the Stack root folder (see `stack path --stack-root`, before you uninstall); -2. if different, the folder containing Stack's global YAML configuration file - (see `stack path --global-config`, before you uninstall); -3. on Windows, the folder containing Stack's tools (see `stack path --programs`, - before you uninstall), which is located outside of the Stack root folder; and -4. the `stack` executable file (see `which stack`, on Unix-like operating - systems, or `where.exe stack`, on Windows). - -You may also want to delete `.stack-work` folders in any Haskell projects that -you have built using Stack. The `stack uninstall` command provides information -about how to uninstall Stack. - -## The `stack exec` command - -We've already used `stack exec` multiple times in this guide. As you've likely -already guessed, it allows you to run executables, but with a slightly modified -environment. In particular: `stack exec` looks for executables on Stack's bin -paths, and sets a few additional environment variables (like adding those paths -to the PATH, and setting `GHC_PACKAGE_PATH`, which tells GHC which package -databases to use). - -If you want to see exactly what the modified environment looks like, try -command: - -~~~text -stack exec env -~~~ - -The only issue is how to distinguish flags to be passed to Stack versus those -for the underlying program. Thanks to the `optparse-applicative` library, Stack -follows the Unix convention of `--` to separate these. For example, command: - -~~~text -stack exec --package stm -- echo I installed the stm package via --package stm -~~~ - -yields output like: - -~~~text -Run from outside a project, using implicit global project config -Using latest snapshot resolver: lts-22.21 -Writing global (non-project-specific) config file to: /home/michael/.stack/global/stack.yaml -Note: You can change the snapshot via the resolver field there. -I installed the stm package via --package stm -~~~ - -Flags worth mentioning: - -* `--package foo` can be used to force a package to be installed before running - the given command. -* `--no-ghc-package-path` can be used to stop the `GHC_PACKAGE_PATH` environment - variable from being set. Some tools — notably Cabal (the tool) — do not behave - well with that variable set. - -You may also find it convenient to use `stack exec` to launch a subshell -(substitute `bash` with your preferred shell) where your compiled executable is -available at the front of your PATH. Command: - -~~~text -stack exec bash -~~~ - -## The `stack ghci` or `stack repl` command - -GHCi is the interactive GHC environment, a.k.a. the REPL. You *could* access it -with command: - -~~~text -stack exec ghci -~~~ - -But that won't load up locally written modules for access. For that, use the -`stack ghci` or `stack repl` commands, which are equivalent. To then load -modules from your project in GHCi, use the `:module` command (`:m` for short) -followed by the module name. - -!!! note - - If you have added packages to your project please make sure to mark them as - extra-deps for faster and reliable usage of `stack ghci`. Otherwise GHCi may - have trouble due to conflicts of compilation flags or having to - unnecessarily interpret too many modules. See Stack's project-level - [configuration](yaml_configuration.md#extra-deps) to learn how to - configure a package as an extra-dep. - -For further information, see the [REPL environment](ghci.md) documentation. - -## The `stack ghc` and `stack runghc` commands - -You'll sometimes want to just compile (or run) a single Haskell source file, -instead of creating an entire Cabal package for it. You can use `stack exec ghc` -or `stack exec runghc` for that. As simple helpers, we also provide the -`stack ghc` and `stack runghc` commands, for these common cases. - -## Finding project configs, and the implicit global project - -Whenever you run something with Stack, it needs a project-level configuration -file. The algorithm Stack uses to find such a file is: - -1. Check for a `--stack-yaml` option on the command line -2. Check for a `STACK_YAML` environment variable -3. Check the current directory and all ancestor directories for a `stack.yaml` - file - -The first two provide a convenient method for using an alternate configuration. -For example: `stack build --stack-yaml stack-ghc-9.2.3.yaml` can be used by your -CI system to check your code against GHC 9.2.3. Setting the `STACK_YAML` -environment variable can be convenient if you're going to be running commands -like `stack ghc` in other directories, but you want to use the configuration you -defined in a specific project. - -If Stack does not find a project level configuration file in any of the three -specified locations, the *implicit global* logic kicks in. You've probably -noticed that phrase a few times in the output from commands above. Implicit -global is essentially a hack to allow Stack to be useful in a non-project -setting. When no implicit global configuration file exists, Stack creates one -for you with the latest LTS snapshot. This allows you to do things like: - -* compile individual files easily with `stack ghc` -* build executables without starting a project, e.g. `stack install pandoc` - -Keep in mind that there's nothing magical about this implicit global -configuration. It has no effect on projects at all. Every package you install -with it is put into isolated databases just like everywhere else. The only magic -is that it's the catch-all project whenever you're running Stack somewhere else. - -## `stack.yaml` versus Cabal files - -Now that we've covered a lot of Stack use cases, this quick summary of -`stack.yaml` versus Cabal files will hopefully make sense and be a good reminder -for future uses of Stack: - -* A project can have multiple packages. -* Each project has a `stack.yaml`. -* Each package has a Cabal file, named `<package_name>.cabal`. -* The Cabal file specifies which packages are dependencies. -* The `stack.yaml` file specifies which packages are available to be used. -* The Cabal file specifies the components, modules, and build flags provided by - a package -* `stack.yaml` can override the flag settings for individual packages -* `stack.yaml` specifies which packages to include - -## Comparison to other tools - -Stack is not the only tool available for building Haskell code. Stack came into -existence due to limitations at that time with some of the existing tools. If -you are happily building Haskell code with other tools, you may not need Stack. -If you're experiencing problems with other tools, give Stack a try instead. - -If you're a new user who has no experience with other tools, we recommend Stack. -The defaults match modern best practices in Haskell development, and there are -fewer corner cases you need to be aware of. You *can* develop Haskell code with -other tools, but you probably want to spend your time writing code, not -convincing a tool to do what you want. - -### Underlying package format - -Before turning to differences, we clarify an important similarity: Stack, Cabal -(the tool), and presumably all other tools share the same underlying package -format of Cabal (the library). This is a Good Thing: we can share the same set -of upstream libraries, and collaboratively work on the same project with Stack, -Cabal (the tool), and NixOS. In that sense, we're sharing the same ecosystem. - -### Curation vs dependency solving - -* Stack uses 'curation' (snapshots and Stack's project-level configuration file - (`stack.yaml`, by default) define precisely the set of packages available for - a project). The Stack team firmly believes that the majority of users want to - simply ignore dependency resolution nightmares and get a valid build plan from - day one. That's why we've made 'curation' the focus of Stack. - -* Cabal (the tool) can use 'curation' too but its origins are in dependency - solving. - -### Emphasis on reproducibility - -* Stack goes to great lengths to ensure that `stack build` today does the - same thing tomorrow. With Stack, changing the build plan is always an explicit - decision. - -* Cabal (the tool) does not go to the same lengths: build plans can be affected - by the presence of pre-installed packages, and running `cabal update` can - cause a previously successful build to fail. - -### Automatic building of dependencies - -* Stack's automatically builds dependencies. So for example, in Stack, - `stack test` does the same job as: - - ~~~text - cabal install --enable-tests --only-dependencies - cabal configure --enable-tests - cabal build - cabal test - ~~~ - - (newer versions of Cabal (the tool) may make this command sequence shorter). - -* With Cabal (the tool), you need to use `cabal install` to trigger dependency - building. This is somewhat necessary as building dependencies can, in some - cases, break existing installed packages. - -### Isolation - -* Stack is isolated - provides 'sandboxed' behaviour - by default, via its - databases. In other words: when you use Stack, there's - __no need for sandboxes__, everything is (essentially) sandboxed by default. - -* With Cabal (the tool), the default behavior is a non-isolated build where - working on two projects can cause the user package database to become - corrupted. The Cabal solution to this is sandboxes. - -### Tools other than Stack and Cabal (the tool) - -* [cabal-meta](https://hackage.haskell.org/package/cabal-meta) inspired a lot of - the multi-package functionality of Stack. Still relevant for Cabal (the - tool). -* [cabal-src](https://hackage.haskell.org/package/cabal-src). Deprecated in - favor of Stack in 2016. -* [stackage-cli](https://hackage.haskell.org/package/stackage-cli).Deprecated - in favor of Stack in 2015. -* [cabal-dev](https://hackage.haskell.org/package/cabal-dev). Deprecated in - favor of Cabal (the tool) in 2013.
− doc/GUIDE_advanced.md
@@ -1,74 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# User guide (advanced) - -Some of Stack's features will not be needed regularly or by all users. This part -of the guide provides information about those features, organised as a reference -guide. Some of the features are complex and separate pages are dedicated to -them. - -## Environment variables - -The existence or content of certain environment variables can affect how Stack -behaves. For further information, see the -[environment variables](environment_variables.md) documentation. - -## YAML configuration files - -Stack is configured by the content of YAML files. A global YAML configuration -file contains non-project specific options. A project-level YAML configuration -file contains project-specific options and may contain non-project specific -options. For further information, see the -[YAML configuration](yaml_configuration.md) documentation. - -## Global flags and options - -Stack can also be configured by flags and options on the command line. Global -flags and options apply to all of Stack's commands. For further information, see -the [global flags and options](global_flags.md) documentation. - -## Stack commands - -Stack's commands are listed below, in alphabetical order. - -* [`bench`](build_command.md) - a synonym for `stack build --bench` -* [`build`](build_command.md) - build packages -* [`clean`](clean_command.md) - delete build artefacts for the project packages -* [`config`](config_command.md) - access and modify Stack's configuration -* [`docker`](docker_command.md) - use Stack with Docker -* [`dot`](dot_command.md) - dependency visualization -* [`eval`](eval_command.md) - evaluate some Haskell code inline -* [`exec`](exec_command.md) - executate a command in the Stack environment -* [`haddock`](build_command.md) - a synonym for `stack build --haddock` -* [`hoogle`](hoogle_command.md) - run `hoogle` -* [`hpc`](hpc_command.md) - generate Haskell Program Coverage (HPC) code coverage - reports -* [`ghc`](ghc_command.md) - run `ghc` -* [`ghci`](ghci.md) - run GHCi, a REPL environment -* [`ide`](ide_command.md) - information for an integrated development - environment (IDE) -* [`init`](init_command.md) - initialise Stack's project-level YAML configuration file for an - existing project -* [`install`](build_command.md) - a synonym for `stack build --copy-bins` -* [`list`](list_command.md) - list packages on Hackage or in a snapshot -* [`ls`](ls_command.md) - list information about Stack -* [`new`](new_command.md) - create a new project with Stack -* [`path`](path_command.md) - information about locations used by Stack -* [`purge`](purge_command.md) - delete the Stack working directories -* [`query`](query_command.md) - information about the build -* [`repl`](ghci.md) - a synonym for `stack ghci` -* [`run`](run_command.md) - build and run an executable -* [`runghc`](runghc_command.md) - run `runghc` -* [`runhaskell`](runghc_command.md) - a synonym for `stack runghc` -* [`script`](script_command.md) - run a Haskell source file as a script -* [`sdist`](sdist_command.md) - create an archive file for a package, in a form - accepted by Hackage -* [`setup`](setup_command.md) - get GHC for a Stack project -* [`templates`](templates_command.md) - information about templates for use with - `stack new` -* [`test`](build_command.md) - a synonym for `stack build --test` -* [`uninstall`](uninstall_command.md) - information about how to uninstall Stack -* [`unpack`](unpack_command.md) - unpack one or more packages locally -* [`update`](update_command.md) - update the package index -* [`upgrade`](upgrade_command.md) - upgrade Stack -* [`upload`](upload_command.md) - upload a package to Hackage
doc/README.md view
@@ -4,70 +4,45 @@ Welcome to the [Haskell](https://www.haskell.org/) programming language and the Haskell Tool Stack (Stack)! Stack is a program for developing Haskell projects. -It is aimed at Haskellers both new and experienced. It is cross-platform and -aims to support fully users on Linux, macOS and Windows. +It is aimed at new and experienced users of Haskell and seeks to support +them fully on Linux, macOS and Windows. +Haskell code is compiled by the +[Glasgow Haskell Compiler](https://www.haskell.org/ghc/) (GHC), which can also +be used interactively. + <img src="https://i.imgur.com/WW69oTj.gif" width="50%" align="right"> -Stack features: +Stack features include: -* Installing the [Glasgow Haskell Compiler (GHC)](https://www.haskell.org/ghc/) - automatically, in an isolated location. +* Installing GHC automatically. * Installing packages needed for your project. * Building your project. * Testing your project. * Benchmarking your project. +* Using GHC interactively. +Stack is used at the command line. You will need terminal software for your +system (which will likely come with its operating system) and a program to edit +code files. There are a number of freely-available and popular code editors that +have Haskell extensions. + ## How to install Stack Stack can be installed on most Unix-like operating systems (including macOS) and Windows. It will require at least about 5 GB of disk space, for use with one version of GHC. -!!! info - - In addition to the methods described below, Stack can also be installed - using the separate [GHCup](https://www.haskell.org/ghcup/) installer for - Haskell-related tools. GHCup provides Stack for some combinations of machine - architecture and operating system not provided elsewhere. By default, the - script to install GHCup (which can be run more than once) also configures - Stack so that if Stack needs a version of GHC, GHCup takes over obtaining - and installing that version. - -=== "Linux" - - For most Linux distributions, the easiest way to install Stack - directly (rather than use GHCup) is to command: - - ~~~text - curl -sSL https://get.haskellstack.org/ | sh - ~~~ - - or: - - ~~~text - wget -qO- https://get.haskellstack.org/ | sh - ~~~ - - !!! note - - The script at [get.haskellstack.org](https://get.haskellstack.org/) will - ask for root access using `sudo`. It needs such access in order to use - your platform's package manager to install dependencies and to install - to `/usr/local/bin`. If you prefer more control, follow the manual - installation instructions in the - [install and upgrade guide](install_and_upgrade.md). +Stack can be installed directly or by using the GHCup tool. -=== "macOS" +=== "Directly" - From late 2020, Apple began a transition from Mac computers with Intel - processors (Intel-based Mac) to - [Mac computers with Apple silicon](https://support.apple.com/en-gb/HT211814). + Stack can be installed directly on various operating systems. - === "Intel-based" + === "Linux" - For most Intel-based Mac computers, the easiest way to install Stack - directly (rather than use GHCup) is to command: + For most Linux distributions, on x86_64 or AArch64 machine + architectures, the easiest way to install Stack is to command either: ~~~text curl -sSL https://get.haskellstack.org/ | sh @@ -79,112 +54,189 @@ wget -qO- https://get.haskellstack.org/ | sh ~~~ - !!! note + These commands download a script file and run it using `sh`. + ??? question "Will the installation script need root access?" + The script at [get.haskellstack.org](https://get.haskellstack.org/) will ask for root access using `sudo`. It needs such access in order to use your platform's package manager to install dependencies and to install to `/usr/local/bin`. If you prefer more control, follow - the manual installation instructions in the - [install and upgrade guide](install_and_upgrade.md). + the manual installation instructions in the guide to + [setting up](install_and_upgrade.md). - === "Apple silicon" + === "macOS" - Mac computers with Apple silicon have an M1, M1 Pro, M1 Max, M1 Ultra or - M2 chip. These chips use an architecture known as ARM64 or AArch64. + From late 2020, Apple began a transition from Mac computers with Intel + processors (Intel-based Mac) to + [Mac computers with Apple silicon](https://support.apple.com/en-gb/HT211814). - For Mac computers with Apple silicon, the easiest way to install Stack - directly (rather than use GHCup) is to command: + === "Intel-based" - ~~~text - curl -sSL https://get.haskellstack.org/ | sh - ~~~ + For most Intel-based Mac computers, the easiest way to install Stack + is to command either: - or: + ~~~text + curl -sSL https://get.haskellstack.org/ | sh + ~~~ - ~~~text - wget -qO- https://get.haskellstack.org/ | sh - ~~~ + or: - !!! note + ~~~text + wget -qO- https://get.haskellstack.org/ | sh + ~~~ - The script at [get.haskellstack.org](https://get.haskellstack.org/) - will ask for root access using `sudo`. It needs such access in order - to use your platform's package manager to install dependencies and - to install to `/usr/local/bin`. If you prefer more control, follow - the manual installation instructions in the - [install and upgrade guide](install_and_upgrade.md). + These commands download a script file and run it using `sh`. -=== "Windows" + ??? question "Will the installation script need root access?" - On 64-bit Windows, the easiest way to install Stack directly (rather than - use GHCup) is to download and install the - [Windows installer](https://get.haskellstack.org/stable/windows-x86_64-installer.exe). + The script at + [get.haskellstack.org](https://get.haskellstack.org/) will ask + for root access using `sudo`. It needs such access in order + to use your platform's package manager to install dependencies + and to install to `/usr/local/bin`. If you prefer more control, + follow the manual installation instructions in the guide to + [setting up](install_and_upgrade.md). - !!! info + === "Apple silicon" - By default, the Windows installer will set the Stack root to `C:\sr`. + Mac computers with Apple silicon have an M series chip. These chips + use an architecture known as ARM64 or AArch64. - !!! warning + For Mac computers with Apple silicon, the easiest way to install + Stack is to command either: - The Windows installer for Stack 2.9.1, 2.9.3 and 2.11.1 (only) will - replace the user `PATH` environment variable (rather than append to it) - if a 1024 character limit is exceeded. If the content of your existing - user `PATH` is long, preserve it before running the installer. + ~~~text + curl -sSL https://get.haskellstack.org/ | sh + ~~~ - !!! note + or: - Systems with antivirus software may need to add Stack to the list of - 'trusted' applications. + ~~~text + wget -qO- https://get.haskellstack.org/ | sh + ~~~ -=== "Other/direct downloads" + These commands download a script file and run it using `sh`. - For other operating systems and direct downloads (rather than use GHCup), - see the [install and upgrade guide](install_and_upgrade.md). + ??? question "Will the installation script need root access?" -## How to upgrade Stack + The script at + [get.haskellstack.org](https://get.haskellstack.org/) will ask + for root access using `sudo`. It needs such access in order + to use your platform's package manager to install dependencies + and to install to `/usr/local/bin`. If you prefer more control, + follow the manual installation instructions in the guide to + [setting up](install_and_upgrade.md). -If Stack is already installed, you can upgrade it to the latest version by the -command: + === "Windows" -~~~text -stack upgrade -~~~ + Most machines using the Windows operating system have a x86_64 + architecture. More recently, Microsoft has provided Windows on Arm that + runs on other processors. -!!! note + === "x86_64" - If you used [GHCup](https://www.haskell.org/ghcup/) to install Stack, you - should also use GHCup, and not Stack, to upgrade Stack. + On 64-bit Windows, the easiest way to install Stack is to download + and install the + [Windows installer](https://get.haskellstack.org/stable/windows-x86_64-installer.exe). + !!! info + + By default, the Windows installer will set the + [Stack root](topics/stack_root.md) to `C:\sr`. + + !!! note + + Systems with antivirus software may need to add Stack to the + list of 'trusted' applications. + + === "Windows on Arm" + + The GHC project does not yet provide a version of GHC that runs on + Windows on Arm. + + === "Other/direct downloads" + + For other operating systems and direct downloads see the guide to + [setting up](install_and_upgrade.md). + +=== "GHCup" + + The separate [GHCup](https://www.haskell.org/ghcup/) project provides a tool + that can be used to install Stack and other Haskell-related tools, including + GHC and + [Haskell Language Server](https://github.com/haskell/haskell-language-server) + (HLS). HLS is a program that is used by Haskell extensions for popular code + editors. + + GHCup provides Stack for some combinations of machine architecture and + operating system not provided elsewhere. + + By default, the script to install GHCup (which can be run more than once) + also configures Stack so that if Stack needs a version of GHC, GHCup takes + over obtaining and installing that version. + +??? question "How do I upgrade Stack?" + + Follow the advice under [setting up](install_and_upgrade.md#upgrade-stack). + +??? question "How do I remove Stack?" + + For information about how to uninstall Stack, command: + + ~~~text + stack uninstall + ~~~ + + To uninstall Stack, it should be sufficient to delete: + + 1. the Stack root directory (see `stack path --stack-root`, before you + uninstall); + 2. if different, the directory containing Stack's global configuration file + (see `stack path --global-config`, before you uninstall); + 3. on Windows, the directory containing Stack's tools (see + `stack path --programs`, before you uninstall), which is usually located + outside of the Stack root directory; and + 4. the `stack` executable file (see `which stack`, on Unix-like operating + systems, or `where.exe stack`, on Windows). + + You may also want to delete ``.stack-work`` directories in any Haskell + projects that you have built using Stack. + ## Quick Start guide -For an immediate experience of using Stack to build an executable with Haskell, -first you need to follow the [guide to install Stack](#how-to-install-Stack). +Once Stack is installed, you can get an immediate experience of using it to +build an executable with Haskell. ### Step 1: Start your new project -To start a new project named `my-project`, issue these four commands in a -terminal: +A complex project can have more than one package and each package can have more +than one executable (program). However, to start a new single-package project +named `my-project`, issue these four commands in a terminal (click +:material-plus-circle: to learn more about each command): -~~~text -stack new my-project -cd my-project -stack build -stack exec my-project-exe +~~~shell +stack new my-project # (1)! +cd my-project # (2)! +stack build # (3)! +stack exec my-project-exe # (4)! ~~~ -- The `stack new my-project` command will create a new directory, named - `my-project`. It contains all the files needed to start a project correctly, - using a default template. -- The `cd my-project` command will change the current working directory to that - directory. -- The `stack build` command will build the template project and create an - executable named `my-project-exe` (on Windows, `my-project-exe.exe`). First, - if necessary, Stack will download a version of GHC in an isolated location. - That won't interfere with other GHC installations on your system. -- The `stack exec my-project-exe` command will run (execute) the built - executable, in Stack's environment. +1. Create a new directory named `my-project`. It contains all the files needed + to start a project correctly, using a default template. +2. Change the current working directory to `my-project`. + +3. Build the template project and create an executable named `my-project-exe`. + + First, if necessary, Stack will download a version of GHC in an isolated + location. That won't interfere with other GHC installations on your system. + (On Windows, if necessary, Stack will also download + [MSYS2](https://www.msys2.org/). MSYS2 is a project that provides popular + tools for developers on Windows.) + +4. Run (execute) the built executable, in Stack's environment. + For a complete list of Stack's commands, and flags and options common to those commands, simply command: @@ -201,13 +253,11 @@ If you want to launch a run-eval-print loop (REPL) environment, then command: -~~~text -stack repl +~~~shell +stack repl # (1)! ~~~ -!!! info - - `stack ghci` can be used instead of `stack repl`. GHCi is GHC's REPL tool. +1. `stack ghci` can be used instead of `stack repl`. GHCi is GHC's REPL tool. People organise Haskell code into packages. If you want to use Stack to install an executable provided by a Haskell package, then all you have to do is command: @@ -219,189 +269,145 @@ ### Step 2: Next steps The `stack new my-project` command in step one should have created the following -files and directories (among others): +files and directories, among others. Click :material-plus-circle: to learn more +about each file: -~~~text +~~~shell . ├── app -│ └── Main.hs +│ └── Main.hs # (1)! ├── src -│ └── Lib.hs +│ └── Lib.hs # (2)! ├── test -│ └── Spec.hs -├── my-project.cabal -├── package.yaml -└── stack.yaml +│ └── Spec.hs # (3)! +├── my-project.cabal # (4)! +├── package.yaml # (5)! +└── stack.yaml # (6)! ~~~ -The Haskell source code for the executable (application) is in file `Main.hs`. +1. The Haskell source code for the executable (application). -The executable uses a library. Its source code is in file `Lib.hs`. + As your project develops you can add further source code files to the `app` + directory. -The contents of `my-project.cabal` describes the project's package. That file is -generated by the contents of `package.yaml`. +2. The executable uses a library. The Haskell source code for the library. -!!! info + As your project develops you can add further source code files to the `src` + directory. - If you want, you can delete the `package.yaml` file and update the - `my-project.cabal` file directly. Stack will then use that file. +3. The package has a test suite executable. The Haskell source code for the + test suite. -The contents of `stack.yaml` describe Stack's own project-level configuration. + As your project develops you can add further source code files to the `test` + directory. -You can edit the source files in the `src` directory (used for the library) or -the `app` directory (used for the executable (application)). +4. A file describing the package in the Cabal format, including other packages + on which depends. Stack generates it from the contents of the `package.yaml` + file. -As your project develops, you may need to depend on a library provided by -another Haskell package. If you do, then add the name of that new package to the -file `package.yaml`, in its `dependencies:` section. + If the `package.yaml` file is deleted, Stack will use the Cabal file. -!!! info +5. A file describing the package in the Hpack format. Stack generates the + `my-project.cabal` file from its contents. - When you use `stack build` again, Stack will use `package.yaml` to create an - updated `my-project.cabal` for you. + If you want, you can delete the file and update the Cabal file directly. -If Stack reports that the Stack configuration has no specified version for the -new package, then follow Stack's likely recommended action to add a specific -version of that package your project's `stack.yaml` file, in its `extra-deps:` -section. + As your project develops, you may need to depend on a library provided by + another Haskell package. If you do, add the name of that new package to + the `dependencies:` section. +6. Stack's project-level configuration. This specifies a snapshot that, in + turn, specifies a version of GHC and a set of package versions chosen to + work well together. It also identifies the local packages in the project. + + If you add a new package as a dependency in the package description, and + Stack reports that the Stack configuration has no specified version for it, + then follow Stack's likely recommended action to add a specific version to + the `extra-deps:` section. + That was a really fast introduction on how to start to code in Haskell using -Stack. If you want to go further, we highly recommend you read Stack's -introductory [user's guide](GUIDE.md). +Stack. If you want to go further, we recommend you read Stack's guide to +[getting started](tutorial/index.md). ## Complete guide to Stack -A complete [user's guide](GUIDE.md) to Stack is available, covering all of -the most common ways to use Stack. Terms used in Stack's documentation are also -explained in the [glossary](glossary.md). +A complete guide to Stack is available, covering the most common ways to +[use Stack](tutorial/index.md), its [commands](commands/index.md), its +[configuration](configure/index.md), specific [topics](topics/index.md), and +[frequently asked questions](faq.md). Terms used in Stack's documentation are +also explained in the [glossary](glossary.md). ## Why Stack? -Stack is a build tool for Haskell designed to answer the needs of Haskell users, -both new and experienced. It has a strong focus on reproducible build plans, -multi-package projects, and a consistent, easy-to-learn set of Stack commands. -It also aims to provide the customizability and power that experienced -developers need. +Stack has a strong focus on plans for building that are reproducible; projects +that have more than one package; and a consistent, easy-to-learn set of +Stack commands. It also aims to provide the ability to customise and power that +experienced developers need. Stack does not stand alone. It is built on the great work provided by: -* The __Glasgow Haskell Compiler__ ([GHC](https://www.haskell.org/ghc/)), the - premier Haskell compiler. Stack will manage your GHC installations and - automatically select the appropriate version of GHC for your project. -* The __Cabal build system__. Cabal is a specification for defining Haskell - packages and a [library](https://hackage.haskell.org/package/Cabal) for - performing builds. - - !!! info - - Cabal is also the name of another build tool, provided by the - `cabal-install` package. This guide distinguishes between them by Cabal - (the library) and Cabal (the tool). - -* The __Hackage Haskell Package Repository__, a - [repository](https://hackage.haskell.org/) of Haskell packages providing - thousands of open source libraries and applications to help you get your work - done. -* The __Stackage package collection__, sets of packages from Hackage that are - [curated](https://www.stackage.org/). That is, they are regularly tested for - compatibility. Stack defaults to using Stackage package sets to avoid - problems with incompatible dependencies. - -Stack is provided by a team of volunteers and companies under the auspices of -the [Commercial Haskell](http://commercialhaskell.com/) group. The project was -spearheaded by [FP Complete](https://www.fpcomplete.com/) to answer the needs of -commercial Haskell users. It has since become a thriving open source project -meeting the needs of Haskell users of all stripes. - -If you'd like to get involved with Stack, check out the -[newcomer friendly](https://github.com/commercialhaskell/stack/issues?q=is%3Aopen+is%3Aissue+label%3a%22newcomer+friendly%22) -label on the GitHub issue tracker. +<div class="grid cards" markdown> -## Questions, feedback, and discussion +- :fontawesome-solid-gears:{ .lg .middle } __Glasgow Haskell Compiler__ -* For answers to frequently asked questions about Stack, please see the - [FAQ](faq.md). -* For general questions, comments, feedback and support, please post to the - [Haskell Community](https://discourse.haskell.org/about). -* For bugs, issues, or requests, please - [open an issue](https://github.com/commercialhaskell/stack/issues/new). -* When using Stack Overflow, please use the - [haskell-stack](http://stackoverflow.com/questions/tagged/haskell-stack) tag. + The premier Haskell compiler. Stack will manage your GHC + installations and automatically select the appropriate version of GHC for + your project. -## How to contribute to the maintenance or development of Stack + --- -A [guide](CONTRIBUTING.md) is provided to help potential contributors to the -Stack project. + [:octicons-arrow-right-24: Learn more](https://www.haskell.org/ghc/) -If you have already installed a version of Stack and the -[Git application](https://git-scm.com/) the followings steps should get you -started with building Stack from source with Stack: +- :fontawesome-solid-trowel-bricks:{ .lg .middle } __Cabal build system__ -1. Clone the `stack` repository from GitHub with the command: + A specification for defining Haskell packages and a library for performing + builds.[^1] - ~~~text - git clone https://github.com/commercialhaskell/stack.git - ~~~ + [^1]: + Cabal is also the name of a tool used for building Haskell code, + provided by the `cabal-install` package. This guide distinguishes + between them by Cabal (the library) and Cabal (the tool). -2. Change the current working directory to the cloned `stack` directory with - the command: + --- - ~~~text - cd stack - ~~~ + [:octicons-arrow-right-24: Learn more](https://hackage.haskell.org/package/Cabal) -3. Build the `stack` executable using a preexisting installation of Stack with - the command: +- :octicons-database-24:{ .lg .middle } __Hackage__ - ~~~text - stack build - ~~~ + A repository of Haskell packages providing thousands of open source + libraries and applications to help you get your work done. -4. Once the `stack` executable has been built, check its version with the - command: + --- - ~~~text - stack exec -- stack --version - ~~~ + [:octicons-arrow-right-24: Learn more](https://hackage.haskell.org/) - Make sure the version is the latest one. +- :fontawesome-solid-cubes-stacked:{ .lg .middle } __Stackage__ -5. In the GitHub repository's issue tracker, look for issues tagged with - [newcomer friendly](https://github.com/commercialhaskell/stack/issues?q=is%3Aopen+is%3Aissue+label%3a%22newcomer+friendly%22) - and - [awaiting pull request](https://github.com/commercialhaskell/stack/issues?q=is%3Aopen+is%3Aissue+label%3A%22awaiting+pull+request%22) - labels. + Sets of packages from Hackage that are chosen to work well together and + with a specific version of GHC. -If you need to check your changes quickly command: + --- -~~~text -stack repl -~~~ + [:octicons-arrow-right-24: Learn more](https://www.stackage.org/) -and then, at the REPL's prompt, command: +</div> -~~~text -:main --stack-root=<path_to_root> --stack-yaml=<path_to_stack.yaml> <COMMAND> -~~~ +Stack is provided by a team of volunteers and companies under the auspices of +the [Commercial Haskell](http://commercialhaskell.com/) group. The project was +originally spearheaded by [FP Complete](https://www.fpcomplete.com/) to answer +the needs of commercial Haskell users. It has since become a thriving open +source project meeting the needs of Haskell users of all types. -This allows you to set a special Stack root (instead of the default Stack root) -and to target your commands at a particular `stack.yaml` file instead of the one -found in the current directory. +## Questions? -## How to uninstall +For answers to frequently asked questions about Stack, please see the +[FAQ](faq.md). -To uninstall Stack, it should be sufficient to delete: +For general questions please post to the +[Haskell Community](https://discourse.haskell.org/about). -1. the Stack root directory (see `stack path --stack-root`, before you - uninstall); -2. if different, the directory containing Stack's global YAML configuration file - (see `stack path --global-config`, before you uninstall); -3. on Windows, the directory containing Stack's tools (see - `stack path --programs`, before you uninstall), which is located outside of - the Stack root directory; and -4. the `stack` executable file (see `which stack`, on Unix-like operating - systems, or `where.exe stack`, on Windows). +## Get involved! -You may also want to delete ``.stack-work`` directories in any Haskell projects -that you have built using Stack. The `stack uninstall` command provides -information about how to uninstall Stack. +Follow the advice under [get involved](community/index.md) for feedback and +discussion about Stack, or if you want to know how to contribute to its +maintenance or development.
− doc/Stack_and_VS_Code.md
@@ -1,133 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Stack and Visual Studio Code - -[Visual Studio Code](https://code.visualstudio.com/) (VS Code) is a popular -source code editor, and -['Haskell'](https://marketplace.visualstudio.com/items?itemName=haskell.haskell) -is an extension for VS Code that is popular with Haskell coders. - -The 'Haskell' extension can be used with Stack but there are some things to be -aware of, set out below. - -## Haskell Language Server - -The VS Code extension makes use of the Haskell Language Server (HLS). To work, -HLS has to be built with the same version of GHC that it will support. That is, -a version of HLS is required for each version of GHC in use. It is possible that -the most recent versions of GHC are not supported by HLS. - -By default, the VS Code extension uses tools that are in the PATH. However, the -extension's settings (under 'Haskell: Manage HLS') allow a user to specify -that the extension should use a separate application, -[GHCup](https://www.haskell.org/ghcup/), to download and install the versions of -HLS that it needs. GHCup can download and install things other than HLS, -including GHC, MSYS2 (on Windows), Cabal (a build tool), and Stack itself. GHCup -can also update itself. On Windows, GHCup has the capability of using the -Stack-supplied MSYS2 rather than installing a duplicate copy. Cabal (the build -tool), like Stack, depends on the Cabal (the library). Cabal (the tool), unlike -Stack, does not have the capability to automatically install necessary versions -of GHC, and (as well as supporting the extension) GHCup fills a important gap -for users of the Cabal tool. - -If the VS Code extension is set not to use GHCup, its user needs to ensure that -each version of HLS that the extension needs is on the PATH. - -For the most part, the versions of HLS provided by GHCup are built with the same -versions of GHC that Stack downloads from its default `setup-info` dictionary -(see [YAML configuration: setup-info](yaml_configuration.md)). Stack's default -is to mirror the 'official' binary distributions published by GHC. However, in -some cases, it is possible that a GHCup-supplied and GHCup-selected HLS has been -built with a different binary distribution of GHC than the one which Stack has -installed. - -One example of that occurred with the release of GHC 9.0.2. For some Linux users -(Debian 9 and Fedora 27), the version of GHC 9.0.2 linked on GHC’s download -[web page](https://www.haskell.org/ghc/download_ghc_9_0_2.html) was broken. The -GHC developers made alternative ‘9.0.2a’ versions available. For a while, Stack -referred to the versions published by GHC on its download web page while the -GHCup-supplied versions of HLS were built using alternative versions. This -incompatibility led to problems. It was resolved by Stack's default also being -changed to refer to the '9.0.2a' versions. (Where Stack has already installed -GHC 9.0.2, it is necessary to delete GHC 9.0.2 from the `stack path --programs` -directory. This will cause Stack to reinstall the alternative version, when it -first needs GHC 9.0.2. Stack should distinguish what it builds with the -alternative from what it has built, and cached, with the original GHC 9.0.2.) - -### GHCup and Stack >= 2.9.1 - -From Stack 2.9.1, GHCup can configure Stack so that if Stack needs a version of -GHC, GHCup takes over obtaining and installing that version. By default, the -script to install GHCup (which can be run more than once) configures Stack in -that way. For further information about how GHCup configures Stack, see the GHC -installation customisation -[documentation](yaml_configuration.md#ghc-installation-customisation). - -### Workaround #1 - -If GHCup does not configure Stack in the way described above, one workaround is -to allow GHCup to install versions of GHC on the PATH and to cause Stack to use -those versions of GHC, by making use of Stack's `install-ghc` option (which -needs to be disabled) and Stack's `system-ghc` option (which needs to be -enabled). For further information about these options, see the `install-ghc` -[documentation](yaml_configuration.md#install-ghc) and the `system-ghc` -[documentation](yaml_configuration.md#system-ghc). - -For this workaround to work, each time that a snapshot is used that references a -different version of GHC, then GHCup must be used to install it (if GHCup has -not already installed that version). For example, to use `snapshot: lts-22.21` -(GHC 9.6.5), the command `ghcup install ghc 9.6.5` must have been used to -install GHC 9.6.5. That may be a minor inconvenience for some people, as one the -primary benefits of Stack over other Haskell build tools has been that Stack -automatically ensures that the necessary version of GHC is available. - -### Workaround #2 - -If GHCup does not configure Stack, another partial workaround is to install -GHCup so that it is 'empty' except for the current version of HLS, allow the -VS Code extension to use GHCup to manage HLS requirements only, and to ignore -any messages (if any) from the extension on start-up that installation of GHC, -Cabal (the tool) and/or Stack are also necessary (they are not, if only Stack is -being used). - -For this workaround to work, however, there can be no differences between the -version of GHC that the GHCup-supplied HLS was built with and the version that -Stack has installed. A slight inconvenience here is also the possibility of -false messages from the start-up that need to be ignored. In principle, those -messages can be disabled by -[setting the following](https://github.com/haskell/vscode-haskell#setting-a-specific-toolchain) -for the VS Code extension: - -~~~yaml -"haskell.toolchain": { - "ghc": null, - "cabal": null, - "stack": null -} -~~~ - -To install a version of GHCup that is 'empty' is a little more complicated than -a default installation of GHCup. - -On Unix-like operating systems, the following environment variable must be set -before GHCup's installation `sh` script is run: `BOOTSTRAP_HASKELL_MINIMAL`. - -On Windows, the second argument to the PowerShell script must be set to -`$false`, namely: - - Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true,$false - -### Cradle - -HLS may need a 'cradle' - an -[`hie.yaml` file](https://hackage.haskell.org/package/hie-bios#stack) - in the -project's root directory in order to work well. - -The [`gen-hie` tool](https://hackage.haskell.org/package/implicit-hie) can help -generate such a cradle. - -### Tips - -It has been suggested that a project must have been successfully built before -the VS code extension (and HLS) is first activated on the project, for HLS to -work reliably.
− doc/azure_ci.md
@@ -1,174 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Azure CI - -This page documents how to use Stack on [Azure CI](http://dev.azure.com/). - -## Quick Start - -Note that you have to create [azure pipelines](#creating-azure-pipelines) for -your project and then you need to put the relevant configuration files: - -* For simple Azure configuration, copy-paste the - [azure-simple](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-simple.yml) - file into `azure-pipelines.yml`. -* For complex Azure configuration, you need to take the below linked four files - and put all of them into the `.azure` directory. - -For a more detailed explanation, you can read further. - -## Simple and Complex configuration - -We provide two fully baked configuration ready to be used on your projects: - -* [The simple Azure configuration](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-simple.yml) - is intended for applications that do not require multiple GHC support or - cross-platform support. It builds and tests your project with just the - settings present in your `stack.yaml` file. -* The complex Azure configuration is intended for projects that need to support - multiple GHC versions and multiple operating systems, such as open source - libraries to be released to Hackage. It tests against Stack for different - snapshots on Linux, macOS and Windows. These are the files for the complex - configuration: - - [azure-pipelines.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-pipelines.yml) - : This is the starter file used by the Azure CI. - - [azure-linux-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-linux-template.yml) - : Template for Azure Linux build - - [azure-osx-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-osx-template.yml) - : Template for Azure macOS build - - [azure-windows-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-windows-template.yml) - : Template for Azure Windows build - - !!! note - - It is likely going to be necessary to modify this configuration to match - the needs of your project, such as tweaking the build matrix to alter - which GHC versions you test against, or to specify GHC-version-specific - `stack.yaml` files if necessary. Don't be surprised if it doesn't work the - first time around. See the multiple GHC section below for more - information. - -## Creating Azure Pipelines - -Each of these configurations is ready to be used immediately. But before we go -into where to put them, we have to create pipeline for your project in Azure -CI platform: - -* Go to [dev.azure.com](https://dev.azure.com). You have to initially sign-in to - your microsoft account there. -* Once you have logged in to your Microsoft account, you have to sign in to - [Azure devops](https://user-images.githubusercontent.com/737477/52465678-70963080-2ba5-11e9-83d8-84112b140236.png) - from there. -* You will be greeted with a - [dashboard](https://user-images.githubusercontent.com/737477/52465677-70963080-2ba5-11e9-904a-c15c7c0524ef.png) - where you can create your projects. -* Click the "Create Project" button and fill the relevant information in the - [dialog](https://user-images.githubusercontent.com/737477/52465676-70963080-2ba5-11e9-82a4-093ee58f11c9.png) and then click the "Create" button. -* This will lead you to the project - [dashboard](https://user-images.githubusercontent.com/737477/52465675-6ffd9a00-2ba5-11e9-917e-3dec251fcc87.png) - page where you can create pipelines. -* Click on "Pipelines" in the left menu. This will load the - [pipelines page](https://user-images.githubusercontent.com/737477/52465673-6ffd9a00-2ba5-11e9-97a4-04e703ae1fbc.png) - on the right. -* Click on the button "New Pipeline" and you have to follow through the wizard - there. You need to choose your github repository (or Azure repos) and follow - the wizard. Note that in the - [Configure step](https://user-images.githubusercontent.com/737477/52465670-6ffd9a00-2ba5-11e9-83a3-9fffdacbf249.png) - you have to select the "Starter Pipeline". This will open up an - [editor window](https://user-images.githubusercontent.com/737477/52465669-6f650380-2ba5-11e9-9662-e9c6fc2682b5.png). - You can leave the existing YAML configuration there as it is and click the - "Save and run" button. That will popup a - [dialog](https://user-images.githubusercontent.com/737477/52465668-6f650380-2ba5-11e9-9203-6347a609e3c4.png). - Select the relevant option and click "Save and run" button. (Note that this - step would have created `azure-pipelines.yml` in your repository. You have to - replace that with the appropriate configuration file.) - -The rest of this document explains the details of common Azure configurations -for those of you who want to tweak the above configuration files or write your -own. - -*Note:* both Azure and Stack infrastructures are actively developed. We try to -document best practices at the moment. - -## Infrastructure - -Note that you need at least one agent to build your code. You can specify which -virtual image you want to choose using this configuration: - -~~~yaml -pool: - vmImage: ubuntu-latest -~~~ - -The other popular options are `macOS-latest`, `windows-latest` for macOS and -Windows respectively. You can find the -[complete list](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=vsts&tabs=yaml) -here. You also have the option to select a specific supported ubuntu version -like `ubuntu-18.08`. - -## Installing Stack - -Currently there is only one reasonable way to install Stack: fetch a precompiled -binary from GitHub. - -~~~yaml -- script: | - mkdir -p ~/.local/bin - curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' - displayName: Install Stack -~~~ - -## Installing GHC - -There are two ways to install GHC: - -- Let Stack download GHC -- Install GHC using apt package manger. This method is only applicable for - Debian based images. - -But we only use the first method of using Stack to download GHC. - -### Multiple GHC - parametrised builds - -For different GHC versions, you probably want to use different project-level -configuration files (`stack.yaml`, by default). If you don't want to put a -specific `stack.yaml` for a particular snapshot and still want to test it, you -have specify your snapshot argument in `ARGS` environment variable (you will see -an example below). - -~~~yaml -strategy: - matrix: - GHC 8.0: - ARGS: "--snapshot lts-9" - GHC 8.2: - ARGS: "--snapshot lts-11" - GHC 8.4: - ARGS: "--snapshot lts-12" - GHC 8.6: - ARGS: "--snapshot lts-14" - GHC 8.8: - ARGS: "--snapsht lts-15" - nightly: - ARGS: "--snapshot nightly" -~~~ - -## Running tests - -After the environment setup, actual test running is simple. Command: - -~~~text -stack $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps -~~~ - -## Other details - -Some Stack commands will run for long time. To avoid timeouts, use the -[timeoutInMinutes](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?tabs=yaml&view=azdevops#timeouts) -for jobs. - -## Examples - -- [commercialhaskell/stack](https://github.com/commercialhaskell/stack/blob/master/azure-pipelines.yml) -- [psibi/tldr-hs](http://github.com/psibi/tldr-hs) -- [psibi/wai-slack-middleware](https://github.com/psibi/wai-slack-middleware)
− doc/build_command.md
@@ -1,1005 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack build` command and its synonyms - -~~~text -stack build [TARGET] [--dry-run] [--pedantic] [--fast] [--ghc-options OPTIONS] - [--flag PACKAGE:[-]FLAG] [--dependencies-only | --only-snapshot | - --only-dependencies | --only-locals] [--file-watch | - --file-watch-poll] [--watch-all] [--exec COMMAND [ARGUMENT(S)]] - [--only-configure] [--trace] [--profile] [--no-strip] - [--[no-]library-profiling] [--[no-]executable-profiling] - [--[no-]library-stripping] [--[no-]executable-stripping] - [--[no-]haddock] [--haddock-arguments HADDOCK_ARGS] - [--[no-]open] [--[no-]haddock-deps] [--[no-]haddock-internal] - [--[no-]haddock-hyperlink-source] [--[no-]haddock-for-hackage] - [--[no-]copy-bins] [--[no-]copy-compiler-tool] [--[no-]prefetch] - [--[no-]keep-going] [--[no-]keep-tmp-files] [--[no-]force-dirty] - [--[no-]test] [--[no-]rerun-tests] [--ta|--test-arguments TEST_ARGS] - [--coverage] [--no-run-tests] [--test-suite-timeout ARG] - [--[no-]tests-allow-stdin] [--[no-]bench] - [--ba|--benchmark-arguments BENCH_ARGS] [--no-run-benchmarks] - [--[no-]reconfigure] [--cabal-verbosity VERBOSITY | - --[no-]cabal-verbose] [--[no-]split-objs] [--skip ARG] - [--[no-]interleaved-output] [--ddump-dir ARG] -~~~ - -`stack build` and its synonyms (`stack test`, `stack bench`, `stack haddock` and -`stack install`) are Stack's primany command. The command provides a simple -interface for simple tasks and flexibility for more complicated goals. - -See the introductory part of Stack's -[user's guide](GUIDE.md#the-stack-build-command) for an introduction to the -command. - -## Synonyms - -The synonym commands for `stack build` are: - -|Synonym command|Equivalent `stack build` command flag| -|---------------|-------------------------------------| -|`stack test` |`stack build --test` | -|`stack bench` |`stack build --bench` | -|`stack haddock`|`stack build --haddock` | -|`stack install`|`stack build --copy-bins` | - -The advantage of the synonym commands is that they are convenient and short. The -advantage of the flags is that they compose. See the examples below. - -## Components - -Every Cabal package is made up of one or more components. It can have an -optional public library component, one or more optional executable components, -one or more optional test suite components, and one or more optional benchmark -components. - -Stack allows you to identify a specific component to be built. For example, -`stack build mypackage:test:mytests` will build (and run - see further below) -the `mytests` component of the `mypackage` package. `mytests` must be a test -suite component. - -By default, if a test suite component is targeted, the component is built and -run. The running behaviour can be disabled with the `--no-run-tests` flag. -Similarly, if a benchmark component is targeted, it is built and run unless the -running behaviour is disabled with the `--no-run-benchmarks` flag. - -This ability to specify a component applies only to a project package. With -dependencies, Stack will *always* build the library (if present) and all -executables (if any), and ignore test suites and benchmarks. If you want more -control over a package, you must add it to your `packages` setting in your -project-level configuration file (`stack.yaml`, by default). - -## Target syntax - -`stack build` takes a list of one or more optional *targets* to be built. The -supported syntaxes for targets are as follows: - -* no targets specified -* *package* -* *package identifier* -* project package *component* -* *local directory* - -### No targets specified - -Example: `stack build` - -`stack build` with no targets specified will build all project packages. - -### Target: *package* - -Example: `stack build foobar` - -Stack will try to find the package in the following locations: - -* project packages, -* extra-deps, -* the snapshot, and -* the package index (e.g. Hackage). - -If the package is found in the package index, then the latest version of that -package from the index is implicitly added as an extra-dep. - -If the package is a project package, the library and executable components are -selected to be built. If the `--test` and `--bench` flags are set, then all of -the test suite and benchmark components, respectively, are selected to be built. - -If *package* is a GHC boot package (packages that come with GHC and are included -in GHC's global package database), the behaviour can be complex: - -* If the boot package has not been 'replaced', then `stack build` will, - effectively, do nothing. - -* If the boot package has been 'replaced' then `stack build` will specify the - latest version of that package in the package index, which may differ from the - version provided by the version of GHC specified by the snapshot. - -A boot package will be treated as 'replaced' if the package is included directly -in the Stackage snapshot or it depends on a package included directly in the -snapshot. - -!!! note - - Stackage snapshots do not include directly most boot packages but some - snapshots may include directly some boot packages. In particular, some - snapshots include directly `Win32` (which is a boot package on Windows) - while others do not. - - For example, if `Cabal` (a boot package) is not a project package or an - extra-dep, then `stack build Cabal` with Stackage snapshot LTS Haskell 20.25 - will: - - * on Windows, try to build the latest version of `Cabal` in the package - index (because that snapshot includes `Win32` directly, and `Cabal` - depends on `Win32` and so is treated as 'replaced'); and - * on non-Windows, effectively, do nothing (because `Cabal` is not - 'replaced'). - -### Target: *package identifier* - -Example: `stack build foobar-1.2.3` - -If the package name is that of a project package, then Stack fails with an -error. - -If the package version is in the package index (e.g. Hackage) then Stack will -use the latest revision of that version from the package index. - -If the package is an extra-dep or in the snapshot, Stack will behave as if only -the package name had been specified as the target (that is, ignoring the -specified version). - -Otherwise, Stack will fail with an error, reporting that the package name is -unknown. - -### Target: project package *component* - -Examples: - -* `stack build my-package:lib` -* `stack build my-package:exe:my-executable` -* `stack build my-package:test:my-test-suite` -* `stack build my-package:bench:my-benchmark` -* `stack build my-package:my-test-suite` -* `stack build :my-test-suite` - -You can select individual components from inside a project package to be built. -This can be done for more fine-grained control over which test suites to run, or -to have a faster compilation cycle. - -There are multiple ways to refer to a specific component: - -* `<package-name>:lib` or `<package-name>:<comp-type>:<comp-name>` (where the - component type, `<comp-type>`, is one of `exe`, `test`, or `bench`) is the - most explicit. The library component type (`lib`) does not have an - associated component name, `<comp-name>`. - -* `<package-name>:<comp-name>` allows you to leave out the component type, as - that will often be unique for a given component name. - -* `:<comp-name>` is a useful shortcut, saying "find the component`<comp-name>` - in all of the project packages". This will result in an error if more than - one package has a component with the specified name. - -For further information about available targets, see the -[`stack ide targets` command](ide_command.md). - -### Target: *local directory* - -Examples: - -* `stack build foo/bar` -* `stack build ./foo` -* `stack build .` - -Stack will find all project packages that exist in the given directory hierarchy -and then follow the same procedure as passing in package names as mentioned -above. - -`stack build .` will target project packages in the current working directory or -its subdirectories. - -!!! note - - If the directory name is parsed as one of the other target types, it will - be treated as that. Explicitly starting the target with `./` can avoid that. - For example, `stack build ./foo`. - -## Controlling what gets built - -Stack will automatically build the necessary dependencies. See the introductory -part of Stack's [user's guide](GUIDE.md#the-stack-build-command) for information -about how these dependencies get specified. - -In addition to specifying targets, you can also control what gets built, or -retained, with the flags and options listed below. You can also affect what gets -built by specifying Cabal (the library) options for the configure step -of the Cabal build process (for further information, see the documentation for -the [configure-options](yaml_configuration.md#configure-options) configuration -option). - -### `--bench` flag - -Pass the flag to add benchmark components to the targets, if specific components -are not identified. The `stack bench` synonym sets this flag. - -### `--dependencies-only` flag - -Pass the flag to skip building the targets. The flag `--only-dependencies` has -the same effect. - -### `--[no-]dry-run` flag - -Default: Disabled - -Set the flag to build nothing and output information about the build plan. - -### `--flag` option - -The option can be specified multiple times. It has two forms: - -* `--flag <package_name>:[-]<flag_name>`; and - -* `--flag *:[-]<flag_name>`. - -`stack build --flag <package_name>:[-]<flag_name>` sets (or unsets) the -specified Cabal flag for the specified package. Stack will report an error if: - -* a package of that name is not known to Stack; or - -* a flag of that name is not a flag of that package. - -This overrides: - -* any Cabal flag specifications for the package in the snapshot; - -* any Cabal flag specifications for the package in Stack's project-level - configuration file (`stack.yaml`); and - -* any use of `--flag *` (see below). - -`stack build --flag *:[-]<flag_name>` sets (or unsets) the specified Cabal flag -for all packages (project packages and dependencies) (whether or not a flag of -that name is a flag of the package). - -This overrides: - -* any Cabal flag specifications for packages in the snapshot; and - -* any Cabal flag specifications for packages in Stack's project-level - configuration file (`stack.yaml`). - -!!! note - - For a package included directly in the snapshot, if the Cabal flag - specifications differ from the Cabal flag specifications (if any) in the - snapshot, then the package will automatically be promoted to be an - [extra-dep](#extra-deps). - -!!! note - - In order to set a Cabal flag for a GHC boot package, the package must be - specified as an [extra-dep](yaml_configuration.md#extra-deps). - -### `--[no-]force-dirty` flag - -Default: Disabled - -Set the flag to force rebuild of packages even when it doesn't seem necessary -based on file dirtiness. - -### `--[no-]haddock` flag - -Default: Disabled - -Set the flag to build Haddock documentation. This may cause a lot of packages to -get re-built, so that the documentation links work. The `stack haddock` synonym -sets this flag. - -Stack applies Haddock's `--gen-contents` and `--gen-index` flags to generate a -single HTML contents and index for multiple sets of Haddock documentation. - -!!! warning - - On Windows, the values for the `haddock-interfaces` and `haddock-html` keys - in the `*.conf` files for boot packages provided with certain versions of - GHC (in its `lib\package.conf.d` directory) can be corrupt and refer to - non-existent files and directories. For example, in the case of GHC 9.0.1 - to GHC 9.8.1 the references are to - `${pkgroot}/../../docs/html/libraries/...` or - `${pkgroot}/../../doc/html/libraries/...` instead of - `${pkgroot}/../docs/html/libraries/...` or - `${pkgroot}/../doc/html/libraries/...`. Until those values are corrected, - Haddock documentation will be missing links to what those packages expose. - -### `--haddock-arguments` option - -`stack haddock --haddock-arguments <haddock_argument(s)>` passes the specified -arguments to the Haddock tool. - -Specified arguments are separated by spaces. Arguments can be unquoted (if they -do not contain space or `"` characters) or quoted (`""`). Quoted arguments can -include 'escaped' characters, escaped with an initial `\` character. - -!!! note - - Haddock's `--latex` flag is incompatible with the Haddock flags used by - Stack to generate a single HTML contents and index. - -### `--[no-]haddock-deps` flag - -Default: Enabled (if building Haddock documnentation) - -Unset the flag to disable building Haddock documentation for dependencies. - -### `--[no-]haddock-for-hackage` flag - -:octicons-beaker-24: Experimental - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -Default: Disabled - -Set the flag to build project packages with flags to generate Haddock -documentation suitable for upload to Hackage. The form of the Haddock -documentation generated for other packages is unaffected. - -For each project package: - -* the generated Haddock documentation files are in directory - `doc\html\<package_version>-docs\`, relative to Stack's dist work directory - (see [`stack path --dist-dir`](path_command.md)); and -* an archive of the `<package_version>-docs` directory and its contents is in - Stack's dist work directory. - -If the flag is set: - -* the [`--[no-]haddock-hyperlink-source`](#-no-haddock-hyperlink-source-flag) - flag is ignored and `--haddock-hyperlink-source` is implied; -* the [`--[no-]haddock-deps`](#-no-haddock-deps-flag) flag is ignored and the - default value for the flag is implied; -* the [`--[no-]haddock-internal`](#-no-haddock-hyperlink-internal-flag) flag is - ignored and `--no-haddock-internal` is implied; -* the [`--[no-]open`](#-no-open-flag) flag is ignored and `--no-open` is - implied; and -* the [`--[no-]force-dirty`](#-no-force-dirty-flag) flag is ignored and - `--force-dirty` is implied. - -!!! info - - Stack does not distinguish the building of Haddock documentation for Hackage - from the building of Haddock documentation generally, which is why the - `--force-dirty` flag is implied. - -!!! note - - If set, Haddock will warn that `-source-*` options are ignored when - `--hyperlinked-source` is enabled. That is due to a known bug in Cabal - (the libiary). - -!!! note - - If set, Cabal (the library) will report that documentation has been created - in `index.html` and `<package_name>.txt` files. Those files do not exist. - That false report is due to a known bug in Cabal (the library). - -### `--[no-]haddock-hyperlink-source` flag - -Default: Enabled - -Unset the flag to disable building building hyperlinked source for Haddock. - -If the [`--haddock-for-hackage`](#-no-haddock-for-hackage-flag) flag is passed, -this flag is ignored. - -### `--[no-]haddock-internal` flag - -Default: Disabled - -Set the flag to enable building Haddock documentation for internal modules. - -If the [`--haddock-for-hackage`](#-no-haddock-for-hackage-flag) flag is passed, -this flag is ignored. - -### `--[no-]keep-going` flag - -Default (`stack build`): Disabled - -Default (`stack test` or `stack bench`): Enabled - -Set the flag to continue building packages even after some build step fails. -The packages which depend upon the failed build won't get built. - -### `--[no-]keep-tmp-files` flag - -Default: Disabled - -Set the flag to keep intermediate files and build directories that would -otherwise be considered temporary and deleted. It may be useful to inspect -these, if a build fails. By default, they are not kept. - -### `--only-configure` flag - -[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) - -Pass the flag to perform only the configure step, not any builds. This is -intended for tool usage. It may break when used on multiple packages at once. - -!!! note - - If there are downstream actions that require a package to be built then a - full build will occur, even if the flag is passed. - -### `--only-dependencies` flag - -Pass the flag to skip building the targets. The flag `--dependencies-only` has -the same effect. - -### `--only-locals` flag - -Pass the flag to build only packages in the local database. Fails if the build -plan includes packages in the snapshot database. - -### `--only-snapshot` flag - -Pass the flag to build only snapshot dependencies, which are cached and shared -with other projects. - -### `--[no-]reconfigure` flag - -Default: Disabled - -Set the flag to force reconfiguration even when it doesn't seem necessary based -on file dirtiness. This is sometimes useful with custom `Setup.hs` files, in -particular when they depend on external data files. - -### `--skip` option - -`stack build --skip <component>` skips building the specified components of a -project package. It allows you to skip test suites and benchmark without -specifying other components (e.g. `stack test --skip long-test-suite` will run -the tests without the `long-test-suite` test suite). Be aware that skipping -executables won't work the first time the package is built due to an issue in -[Cabal](https://github.com/commercialhaskell/stack/issues/3229). - -This option can be specified multiple times to skip multiple components. - -### `--test` flag - -Pass the flag to add test suite components to the targets, if specific -components are not identified. The `stack test` synonym sets this flag. - -## Controlling when building occurs - -### `--file-watch` flag - -Pass the flag to rebuild your project every time a file changes. By default it -will take into account all files belonging to the targets you specify. See also -the `--watch-all` flag. - -### `--file-watch-poll` flag - -Like the `--file-watch` flag, but based on polling the file system instead of -using events to determine if a file has changed. - -### `--watch-all` flag - -[:octicons-tag-24: 2.5.1](https://github.com/commercialhaskell/stack/releases/tag/v2.5.1) - -Pass the flag to rebuild your project every time any local file changes (from -project packages or from dependencies located locally). See also the -`--file-watch` flag. - -## Controlling what happens after building - -### `--benchmark-arguments`, `--ba` option - -`stack build --bench --benchmark-arguments=<argument(s)>` will pass the -specified argument, or arguments, to each benchmark when it is run. - -Specified arguments are separated by spaces. Arguments can be unquoted (if they -do not contain space or `"` characters) or quoted (`""`). Quoted arguments can -include 'escaped' characters, escaped with an initial `\` character. - -Account may need to be taken of the shell's approach to the processing of -command line arguments. For example, to pass `'a single quoted string'`: - -=== "Unix-like (Bash or Zsh)" - - In Bash, or Zsh (if `RC_QUOTES` option not set): - - `stack bench --benchmark-arguments \"\''a single quoted string'\'\"` - - Outside of single quotes, `\"` escapes a double quote and `\'` escapes a - single quote. The content of single quotes is taken literally, but cannot - contain a single quote. - - In Zsh (if `RC_QUOTES` option set): - - `stack bench --benchmark-arguments '"''a single quoted string''"'` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -=== "Windows (PowerShell)" - - `stack bench --benchmark-arguments '"''a single quoted string''"'` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -### `--exec` option - -`stack build --exec '<command> [<argument(s)>]'` will run the specified command -after a successful build. - -Specified arguments are separated by spaces. Arguments can be unquoted (if they -do not contain space or `"` characters) or quoted (`""`). Quoted arguments can -include 'escaped' characters, escaped with an initial `\` character. - -Account may need to be taken of the shell's approach to the processing of -command line arguments. For example, to pass `'a single quoted string'`: - -=== "Unix-like (Bash or Zsh)" - - In Bash, or Zsh (if `RC_QUOTES` option not set): - - `stack build --exec '<command> '\"\''a single quoted string'\'\"` - - Outside of single quotes, `\"` escapes a double quote and `\'` escapes a - single quote. The content of single quotes is taken literally, but cannot - contain a single quote. - - In Zsh (if `RC_QUOTES` option set): - - `stack build --exec '<command> "''a single quoted string''"'` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -=== "Windows (PowerShell)" - - `stack build --exec '<command> "''a single quoted string''"'` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -### `--test-arguments`, `--ta` option - -`stack build --test --test-arguments=<argument(s)>` will pass the specified -argument, or arguments, to each test when it is run. This option can be -specified multiple times. - -Specified arguments are separated by spaces. Arguments can be unquoted (if they -do not contain space or `"` characters) or quoted (`""`). Quoted arguments can -include 'escaped' characters, escaped with an initial `\` character. - -Account may need to be taken of the shell's approach to the processing of -command line arguments. For example, to pass `'a single quoted string'`: - -=== "Unix-like (Bash or Zsh)" - - In Bash, or Zsh (if `RC_QUOTES` option not set): - - `stack test --test-arguments \"\''a single quoted string'\'\"` - - Outside of single quotes, `\"` escapes a double quote and `\'` escapes a - single quote. The content of single quotes is taken literally, but cannot - contain a single quote. - - In Zsh (if `RC_QUOTES` option set): - - `stack bench --benchmark-arguments '"''a single quoted string''"'` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -=== "Windows (PowerShell)" - - `stack test --test-arguments '"''a single quoted string''"'` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -## Flags affecting GHC's behaviour - -### `--[no-]executable-profiling` flag - -Default: Disabled - -Set the flag to enable executable profiling for TARGETs and all its -dependencies. - -The flag affects the location of the local project installation directory. See -the [`stack path --local-install-root`](path_command.md) command. - -### `--[no-]executable-stripping` flag - -Default: Enabled - -Unset the flag to disable executable stripping for TARGETs and all its -dependencies. - -The flag may affect the location of the local project installation directory. -See the [`stack path --local-install-root`](path_command.md) command. - -### `--fast` flag - -GHC has many flags that specify individual optimisations of the compiler. GHC -also uses its `-O*` flags to specify convenient 'packages' of GHC optimisation -flags. GHC's flags are evaluated from left to right and later flags can override -the effect of earlier ones. - -If no GHC `-O*` type flag is specified, GHC takes that to mean "Please -compile quickly; I'm not over-bothered about compiled-code quality." GHC's `-O0` -flag reverts to the same settings as if no `-O*` flags had been specified. - -Pass Stack's `--fast` flag to add `-O0` to the flags and options passed to GHC. -The effect of `--fast` can be overriden with Stack's -[`--ghc-options`](#-ghc-options-option) command line options. - -!!! note - - With one exception, GHC's `-O` flag is always passed to GHC first (being - Cabal's default behaviour). The exception is if Cabal's - `--disable-optimization` flag or `--enable-optimization[=n]`, `-O[n]` - options are used during the configure step of the Cabal build process; see - Stack's [`configure-options`](yaml_configuration.md#configure-options) YAML - configuration option. - -### `--ghc-options` option - -GHC command line options can be specified for a package in its Cabal file -(including one created from a `package.yaml` file). This option augments and, if -applicable (see below), overrides any such GHC command line options and those -specified in Stack's YAML configuration files - see the -[`ghc-options`](yaml_configuration.md#ghc-options) configuration option. - -`stack build --ghc-options <ghc_options>` passes the specified command line -options to GHC, depending on Stack's -[`apply-ghc-options`](yaml_configuration.md#apply-ghc-options) YAML -configuration option. This option can be specified multiple times. - -GHC's command line options are _order-dependent_ and evaluated from left to -right. Later options can override the effect of earlier ones. Any GHC command -line options for a package specified at Stack's command line are applied after -those specified in Stack's YAML configuration files. - -### `--[no-]library-profiling` flag - -Default: Disabled - -Set the flag to enable library profiling for TARGETs and all its dependencies. - -The flag affects the location of the local project installation directory. See -the [`stack path --local-install-root`](path_command.md) command. - -### `--[no-]library-stripping` flag - -Default: Enabled - -Unset the flag to disable library stripping for TARGETs and all its -dependencies. - -The flag may affect the location of the local project installation directory. -See the [`stack path --local-install-root`](path_command.md) command. - -### `--pedantic` flag - -Pass the flag to build your project with the GHC options `-Wall` and `-Werror`. -`-Wall` turns on all warning options that indicate potentially suspicious code. -`-Werror` makes any warning into a fatal error. - -### `--profile` flag - -Pass the flag to enable profiling in libraries, executables, etc. for all -expressions, and generate a profiling report in tests or benchmarks. - -The flag affects the location of the local project installation directory. See -the [`stack path --local-install-root`](path_command.md) command. - -### `--[no-]split-objs` flag - -:octicons-beaker-24: Experimental - -Default: Disabled - -Set the flag to enable the GHC option `-split-objs`. This will reduce output -size (at the cost of build time). - -!!! note - - The behaviour of this feature may be changed and improved. You will need to - clean your project's Stack working directory before use. If you want to - compile all dependencies with split-objs, you will need to delete the - snapshot (and all snapshots that could reference that snapshot). - -!!! note - - GHC's `-split-objs` flag was deprecated in favour of `-split-sections` in - GHC 8.2.1 and was not supported by GHC on any platform from GHC 8.10.1. - -### `--no-strip` flag - -Pass the flag to disable DWARF debugging symbol stripping in libraries, -executables, etc. for all expressions, producing larger executables but allowing -the use of standard debuggers/profiling tools/other utilities that use debugging -symbols. - -The flag affects the location of the local project installation directory. See -the [`stack path --local-install-root`](path_command.md) command. - -### `--trace` flag - -Pass the flag to enable profiling in libraries, executables, etc. for all -expressions, and generate a backtrace on exception. - -The flag affects the location of the local project installation directory. See -the [`stack path --local-install-root`](path_command.md) command. - -## Flags affecting other tools' behaviour - -### `--PROG-option` options - -[:octicons-tag-24: 2.11.1](https://github.com/commercialhaskell/stack/releases/tag/v2.11.1) - -`PROG` is a program recognised by Cabal (the library) and one of `alex`, `ar`, -`c2hs`, `cpphs`, `gcc`, `greencard`, `happy`, `hsc2hs`, `hscolour`, `ld`, -`pkg-config`, `strip` and `tar`. - -`stack build --PROG-option <PROG_argument>` passes the specified command line -argument to `PROG`, if it used by Cabal during the configuration step. This -option can be specified multiple times. For example, if the program `happy` is -used by Cabal during the configuration step, you could command -`stack build --happy-option=--ghc` or `stack build --happy-option --ghc` to pass -to `happy` its `--ghc` flag. - -By default, all and any `--PROG-option` options on Stack's command line are -applied to all project packages (targets or otherwise). This behaviour can be -changed. See the -[`apply-prog-options`](yaml_configuration.md#apply-prog-options) configuration -option. - -Stack can also be configured to pass Cabal's `--PROG-option`, `--PROG-options` -or other options to Cabal during the configuration step. For further -information, see the documentation for the -[configure-options](yaml_configuration.md#configure-options) configuration -option. - -## Flags relating to build outputs - -### `--[no]-cabal-verbose` flag - -Default: Disabled - -Set the flag to enable verbose output from Cabal (the library). This flag is an -alternative to the `--cabal-verbosity` option. - -### `--[no]-cabal-verbosity` option - -`stack build --cabal-verbosity <verbosity_level>` sets the specified verbosity -level for output from Cabal (the library). It accepts Cabal's numerical and -extended syntax. This option is an alternative to setting the `--cabal-verbose` -flag. - -### `--[no-]copy-bins` flag - -[:octicons-tag-24: 0.1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.3.0) - -Default: Disabled - -Set the flag to enable copying of built executable files (binaries) of targets -to Stack's local binary directory (see `stack path --local-bin`). The -`stack install` synonym sets this flag. - -### `--[no-]copy-compiler-tool` flag - -[:octicons-tag-24: 1.6.1](https://github.com/commercialhaskell/stack/releases/tag/v1.6.1) - -Default: Disabled - -Set the flag to enable copying of built executable files (binaries) of targets -to Stack's compiler tools binary directory (see -`stack path --compiler-tools-bin`). - -### `--coverage` flag - -Pass the flag to generate a code coverage report. For further information, see -the [code coverage](hpc_command.md) documentation. - -### `--ddump-dir` option - -GHC has a number of `ddump-*` flags and options to allow dumping out of -intermediate structures produced by the compiler. They include the -`-ddump-to-file` flag that causes the output from other flags to be dumped to a -file or files. - -`stack build --ddump_dir <relative_directory>` causes Stack to copy `*.dump-*` -files to subdirectories of the specified directory, which is relative to Stack's -working directory for the project. - -For example: - -~~~text -stack build --ghc-options "-ddump-to-file -ddump-timings" --ddump-dir my-ddump-dir -~~~ - -### `--[no-]interleaved-output` flag - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -Default: Enabled - -Set the flag for interleaved output. With interleaved output, each line of -output from each package being built (targets and dependencies) is sent to the -console as it happens and output relating to different packages can be -interleaved. Each line will be prefixed with the name of the relevant package. -The spacing between the prefix and the output will be set based on the longest -relevant package name, so that the start of the output itself aligns. For -example (extract): - -~~~text -hpack > build -mustache > configure -hpack > Preprocessing library for hpack-0.35.0.. -hpack > Building library for hpack-0.35.0.. -mustache > Configuring mustache-2.4.1... -hpack > [ 1 of 29] Compiling Data.Aeson.Config.Key -hpack > [ 2 of 29] Compiling Data.Aeson.Config.KeyMap -mustache > build -hpack > [ 3 of 29] Compiling Data.Aeson.Config.Util -mustache > Preprocessing library for mustache-2.4.1.. -mustache > Building library for mustache-2.4.1.. -hpack > [ 4 of 29] Compiling Hpack.Haskell -hpack > [ 5 of 29] Compiling Hpack.Utf8 -mustache > [1 of 8] Compiling Paths_mustache -hpack > [ 6 of 29] Compiling Imports -hpack > [ 7 of 29] Compiling Hpack.Util -mustache > [2 of 8] Compiling Text.Mustache.Internal -~~~ - -Unset the flag for non-interleaved output. With non-interleaved output, the -build output from GHC (as opposed to from Stack) in respect of dependencies is -ignored. The behaviour then depends whether there is one target package or more -than one. There can be one target if the project has a single package or if one -package is targetted in a multi-package project (for example, using -`stack build <package_name>`). - -* **One target package:** The build output for the target package is sent to the - standard error stream of the console as it happens. - -* **More than one target package:** The build output from GHC (as opposed to - from Stack) for each target package is sent to a log file for that package, - unless an error occurs that prevents that. If color in output is in use, there - will be two files, one with extension `.log` without color codes and one with - extension `.log-color` with color codes. At the end of the build, the location - of the directory containing the log files is reported. To also output the - contents of the log files to the standard error output stream of the console - at the end of the build, use Stack's `dump-logs` option. For further - information about that option, see the - [YAML configuration](yaml_configuration.md#dump-logs) documentation. The - default `dump-logs` mode is to output the contents of any log files that - include GHC warnings. - -### `--[no]-open` flag - -Default: Disabled - -Set the flag to enable opening the local Haddock documentation in the browser. - -## Other flags and options - -### `--[no]-prefetch` flag - -Default: Disabled - -Set the flag to enable fetching packages necessary for the build immediately. -This can be useful with `stack build --dry-run`. - -### `--progress-bar` option - -[:octicons-tag-24: 2.13.1](https://github.com/commercialhaskell/stack/releases/tag/v2.13.1) - -Default: `capped` - -`stack build --progress-bar <format>` sets the format of the progress bar, where -`<format>` is one of `none` (no bar), `count-only` (only the package count is -displayed), `capped` (the bar showing package builds in progress is capped to a -length equal to the terminal width), and `full` (the bar is uncapped). On -terminals where 'backspace' has no effect if the cursor is in the first column, -bars longer than the terminal width will not be 'sticky' at the bottom of the -screen. - -### `--tests-allow-stdin` flag - -[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) - -Default: Enabled - -Cabal defines a test suite interface -['exitcode-stdio-1.0'](https://hackage.haskell.org/package/Cabal-syntax-3.8.1.0/docs/Distribution-Types-TestSuiteInterface.html#v:TestSuiteExeV1.0) -where the test suite takes the form of an executable and the executable takes -nothing on the standard input stream (`stdin`). Pass this flag to override that -specification and allow the executable to receive input on that stream. If you -pass `--no-tests-allow-stdin` and the executable seeks input on the standard -input stream, an exception will be thown. - -## Examples - -All the following examples assume that: - -* if `stack build` is commanded outside of a project directory, there is no - `stack.yaml` file in the current directory or ancestor directory and, - consequently, the project-level configuration will be determined by a - `stack.yaml` file in the `global-project` directory in the - [Stack root](stack_root.md) (for further information, see the - [YAML configuration](yaml_configuration.md) documentation); and - -* if `stack build` is commanded in a project directory, there is a - `stack.yaml` file in that directory. - -Examples: - -* In the project directory, `stack build --test --copy-bins` or, equivalently, - `stack test --copy-bins` or `stack install --test`, will build libraries, - executables, and test suites, run the test suites, and then copy the - executables to Stack's local binary directory (see - `stack path --local-bin`). This is an example of the flags composing. - -* The following example uses a clone of the - `wai` [repository](https://github.com/yesodweb/wai/). The `wai` project - comprises a number of packages, including `wai-extra` and `warp`. In the - `wai` project directory, the command: - - ~~~text - stack build --file-watch --test --copy-bins --haddock wai-extra :warp warp:doctest --exec 'echo Yay, it worked!' - ~~~ - - will start Stack up in file watch mode, waiting for files in your project to - change. When first starting, and each time a file changes, it will do all of - the following. - - * Build the `wai-extra` package and its test suites - * Build the `warp` executable - * Build the `warp` package's `doctest` component (which is a test site) - * Run all of the `wai-extra` package's test suite components and the - `doctest` test suite component - * If all of that succeeds: - * Copy generated executables to Stack's local binary directory (see - `stack path --local-bin`) - * Run the command `echo Yay, it worked!` - -* The following example uses the `Adga` package and assumes that `Adga-2.6.3` - is the latest version in the package index (e.g. Hackage) and is not a - version in the snapshot specified by the `stack.yaml` in the - `global-project` directory in the Stack root. - - Outside a project directory, `stack build Adga-2.6.3 --copy-bins` or, - equivalently, `stack install Agda-2.6.3`, will attempt to build the - libraries and executables of the identified version of the package in the - package index (using the `stack.yaml` file in the `global-project` - directory in the Stack root), and then copy the executables to Stack's local - binary directory (see `stack path --local-bin`). - - If a different snapshot is required to build the identified version of the - package, then that can be specified at the command line. For example, to use - the most recent Stackage Nightly snapshot: - - ~~~text - stack --snapshot nightly install Agda-2.6.3 - ~~~ - - Alternatively, Stack can be used to unpack the package from the package - index into a local project directory named after the package identifier (for - further infomation, see the [`stack unpack` command](unpack_command.md) - documentation) and, if the package does not provide its own Stack - configuration file (`stack.yaml`, by default), to attempt to initialise that - configuration (for further information, see the - [`stack init` command](init_command.md) documentation). For example: - - ~~~text - stack unpack Agda-2.6.3 - cd Agda-2.6.3 # Change to the project directory - stack init # Attempt to create a project stack.yaml file - stack install # Equivalent to stack build --copy-bins - ~~~
doc/build_overview.md view
@@ -230,8 +230,9 @@ * Apply flags, platform, and actual GHC version to resolve dependencies in any package analyzed * Include all library dependencies for all enabled components -* Include all build tool dependencies for all enabled components - (using the fun backwards compat logic for `build-tools`) +* Include all dependencies for tools used during building ('build tools') for + all enabled components (using the fun backwards compat logic for + `build-tools`) * Apply the logic recursively to come up with a full build plan * If a task depends exclusively on immutable packages, mark it as immutable. Otherwise, it's mutable. The former go into the snapshot
− doc/clean_command.md
@@ -1,21 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack clean` command - -Either - -~~~text -stack clean [PACKAGE] -~~~ - -or - -~~~text -stack clean --full -~~~ - -`stack clean` deletes build artefacts for one or more project packages specified -as arguments. If no project packages are specified, all project packages are -cleaned. - -`stack clean --full` deletes the project's Stack working directory.
+ doc/commands/bench_command.md view
@@ -0,0 +1,28 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack bench` command + +~~~text +stack bench [TARGET] [--dry-run] [--pedantic] [--fast] [--ghc-options OPTIONS] + [--flag PACKAGE:[-]FLAG] [--dependencies-only | --only-snapshot | + --only-dependencies | --only-locals] [--file-watch | + --file-watch-poll] [--watch-all] [--exec COMMAND [ARGUMENT(S)]] + [--only-configure] [--trace] [--profile] [--no-strip] + [--[no-]library-profiling] [--[no-]executable-profiling] + [--[no-]library-stripping] [--[no-]executable-stripping] + [--[no-]haddock] [--haddock-arguments HADDOCK_ARGS] + [--[no-]open] [--[no-]haddock-deps] [--[no-]haddock-internal] + [--[no-]haddock-hyperlink-source] [--[no-]haddock-for-hackage] + [--[no-]copy-bins] [--[no-]copy-compiler-tool] [--[no-]prefetch] + [--[no-]keep-going] [--[no-]keep-tmp-files] [--[no-]force-dirty] + [--[no-]test] [--[no-]rerun-tests] [--ta|--test-arguments TEST_ARGS] + [--coverage] [--no-run-tests] [--test-suite-timeout ARG] + [--[no-]tests-allow-stdin] [--[no-]bench] + [--ba|--benchmark-arguments BENCH_ARGS] [--no-run-benchmarks] + [--[no-]reconfigure] [--cabal-verbosity VERBOSITY | + --[no-]cabal-verbose] [--[no-]split-objs] [--skip ARG] + [--[no-]interleaved-output] [--ddump-dir ARG] +~~~ + +`stack bench` is a synonym for `stack build --bench`. For further information, +see the documentation for the [`stack build`](build_command.md) command.
+ doc/commands/build_command.md view
@@ -0,0 +1,1101 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack build` command and its synonyms + +~~~text +stack build [TARGET] [--dry-run] [--pedantic] [--fast] [--ghc-options OPTIONS] + [--flag PACKAGE:[-]FLAG] [--dependencies-only | --only-snapshot | + --only-dependencies | --only-locals] [--file-watch | + --file-watch-poll] [--watch-all] [--exec COMMAND [ARGUMENT(S)]] + [--only-configure] [--trace] [--profile] [--no-strip] + [--[no-]library-profiling] [--[no-]executable-profiling] + [--[no-]library-stripping] [--[no-]executable-stripping] + [--[no-]haddock] [--haddock-arguments HADDOCK_ARGS] + [--[no-]open] [--[no-]haddock-deps] [--[no-]haddock-internal] + [--[no-]haddock-hyperlink-source] [--[no-]haddock-for-hackage] + [--[no-]copy-bins] [--[no-]copy-compiler-tool] [--[no-]prefetch] + [--[no-]keep-going] [--[no-]keep-tmp-files] [--[no-]force-dirty] + [--[no-]test] [--[no-]rerun-tests] [--ta|--test-arguments TEST_ARGS] + [--coverage] [--no-run-tests] [--test-suite-timeout ARG] + [--[no-]tests-allow-stdin] [--[no-]bench] + [--ba|--benchmark-arguments BENCH_ARGS] [--no-run-benchmarks] + [--[no-]reconfigure] [--cabal-verbosity VERBOSITY | + --[no-]cabal-verbose] [--[no-]split-objs] [--skip ARG] + [--[no-]interleaved-output] [--ddump-dir ARG] +~~~ + +`stack build` and its synonyms (`stack test`, `stack bench`, `stack haddock` and +`stack install`) are Stack's primany command. The command provides a simple +interface for simple tasks and flexibility for more complicated goals. + +See the introductory part of Stack's +[user's guide](../tutorial/hello_world_example.md#the-stack-build-command) for +an introduction to the command. + +## Synonyms + +The synonym commands for `stack build` are: + +|Synonym command|Equivalent `stack build` command flag| +|---------------|-------------------------------------| +|`stack test` |`stack build --test` | +|`stack bench` |`stack build --bench` | +|`stack haddock`|`stack build --haddock` | +|`stack install`|`stack build --copy-bins` | + +The advantage of the synonym commands is that they are convenient and short. The +advantage of the flags is that they compose. See the examples below. + +## Components + +Every Cabal package is made up of one or more components. It can have an +optional public library component, one or more optional executable components, +one or more optional test suite components, and one or more optional benchmark +components. + +Stack allows you to identify a specific component to be built. For example, +`stack build mypackage:test:mytests` will build (and run - see further below) +the `mytests` component of the `mypackage` package. `mytests` must be a test +suite component. + +By default, if a test suite component is targeted, the component is built and +run. The running behaviour can be disabled with the `--no-run-tests` flag. +Similarly, if a benchmark component is targeted, it is built and run unless the +running behaviour is disabled with the `--no-run-benchmarks` flag. + +This ability to specify a component applies only to a project package. With +dependencies, Stack will *always* build the library (if present) and all +executables (if any), and ignore test suites and benchmarks. If you want more +control over a package, you must add it to your `packages` setting in your +project-level configuration file (`stack.yaml`, by default). + +## Target syntax + +`stack build` takes a list of one or more optional *targets* to be built. The +supported syntaxes for targets are as follows: + +* no targets specified +* *package* +* *package identifier* +* project package *component* +* *local directory* + +### No targets specified + +Example: `stack build` + +`stack build` with no targets specified will build all project packages. + +### Target: *package* + +Example: `stack build foobar` + +Stack will try to find the package in the following locations: + +* project packages, +* extra-deps, +* the snapshot, and +* the package index (e.g. Hackage). + +If the package is found in the package index, then the latest version of that +package from the index is implicitly added as an extra-dep. + +If the package is a project package, the library and executable components are +selected to be built. If the `--test` and `--bench` flags are set, then all of +the test suite and benchmark components, respectively, are selected to be built. + +If *package* is a GHC boot package (packages that come with GHC and are included +in GHC's global package database), the behaviour can be complex: + +* If the boot package has not been 'replaced', then `stack build` will, + effectively, do nothing. + +* If the boot package has been 'replaced' then `stack build` will specify the + latest version of that package in the package index, which may differ from the + version provided by the version of GHC specified by the snapshot. + +A boot package will be treated as 'replaced' if the package is included directly +in the Stackage snapshot or it depends on a package included directly in the +snapshot. + +!!! note + + Stackage snapshots do not include directly most boot packages but some + snapshots may include directly some boot packages. In particular, some + snapshots include directly `Win32` (which is a boot package on Windows) + while others do not. + + For example, if `Cabal` (a boot package) is not a project package or an + extra-dep, then `stack build Cabal` with Stackage snapshot LTS Haskell 20.25 + will: + + * on Windows, try to build the latest version of `Cabal` in the package + index (because that snapshot includes `Win32` directly, and `Cabal` + depends on `Win32` and so is treated as 'replaced'); and + * on non-Windows, effectively, do nothing (because `Cabal` is not + 'replaced'). + +### Target: *package identifier* + +Example: `stack build foobar-1.2.3` + +If the package name is that of a project package, then Stack fails with an +error. + +If the package version is an extra-dep or in the snapshot, then Stack will use +that version. + +If the package version is in the package index (e.g. Hackage) then Stack will +use the latest revision of that version from the package index. + +Otherwise, Stack will fail with an error. + +### Target: project package *component* + +Examples: + +* `stack build my-package:lib` +* `stack build my-package:exe:my-executable` +* `stack build my-package:test:my-test-suite` +* `stack build my-package:bench:my-benchmark` +* `stack build my-package:my-test-suite` +* `stack build :my-test-suite` + +You can select individual components from inside a project package to be built. +This can be done for more fine-grained control over which test suites to run, or +to have a faster compilation cycle. + +There are multiple ways to refer to a specific component: + +* `<package-name>:lib` or `<package-name>:<comp-type>:<comp-name>` (where the + component type, `<comp-type>`, is one of `exe`, `test`, or `bench`) is the + most explicit. The library component type (`lib`) does not have an + associated component name, `<comp-name>`. + +* `<package-name>:<comp-name>` allows you to leave out the component type, as + that will often be unique for a given component name. + +* `:<comp-name>` is a useful shortcut, saying "find the component`<comp-name>` + in all of the project packages". This will result in an error if more than + one package has a component with the specified name. + +For further information about available targets, see the +[`stack ide targets` command](ide_command.md). + +### Target: *local directory* + +Examples: + +* `stack build foo/bar` +* `stack build ./foo` +* `stack build .` + +Stack will find all project packages that exist in the given directory hierarchy +and then follow the same procedure as passing in package names as mentioned +above. + +`stack build .` will target project packages in the current working directory or +its subdirectories. + +!!! note + + If the directory name is parsed as one of the other target types, it will + be treated as that. Explicitly starting the target with `./` can avoid that. + For example, `stack build ./foo`. + +## Controlling what gets built + +Stack will automatically build the necessary dependencies. See the introductory +part of Stack's +[user's guide](../tutorial/building_your_project.md#adding-dependencies) for +information about how these dependencies get specified. + +In addition to specifying targets, you can also control what gets built, or +retained, with the flags and options listed below. You can also affect what gets +built by specifying Cabal (the library) options for the configure step +of the Cabal build process (for further information, see the documentation for +the [configure-options](../configure/yaml/non-project.md#configure-options) +configuration option). + +### `--[no-]allow-newer` flag + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +Overrides: [`allow-newer`](../configure/yaml/non-project.md#allow-newer) +non-project specific configuration option + +Pass the flag to enable or disable the ignoring of lower and upper version +bounds in Cabal files. + +!!! info + + The name `allow-newer` was chosen to match a commonly-used Cabal option + which ignored only upper version bounds. + +### `--bench` flag + +Pass the flag to add benchmark components to the targets, if specific components +are not identified. The `stack bench` synonym sets this flag. + +### `--dependencies-only` flag + +Pass the flag to skip building the targets. The flag `--only-dependencies` has +the same effect. + +### `--[no-]dry-run` flag + +Default: Disabled + +Set the flag to build nothing and output information about the build plan. + +### `--flag` option + +The option can be specified multiple times. It has two forms: + +* `--flag <package_name>:[-]<flag_name>`; and + +* `--flag *:[-]<flag_name>`. + +`stack build --flag <package_name>:[-]<flag_name>` sets (or unsets) the +specified Cabal flag for the specified package. Stack will report an error if: + +* a package of that name is not known to Stack; or + +* a flag of that name is not a flag of that package. + +This overrides: + +* any Cabal flag specifications for the package in the snapshot; + +* any Cabal flag specifications for the package in Stack's project-level + configuration file (`stack.yaml`); and + +* any use of `--flag *` (see below). + +`stack build --flag *:[-]<flag_name>` sets (or unsets) the specified Cabal flag +for all packages (project packages and dependencies) for which the flag is +defined. + +This overrides: + +* any Cabal flag specifications for the relevant packages in the snapshot; and + +* any Cabal flag specifications for the relevant packages in Stack's + project-level configuration file (`stack.yaml`). + +!!! info + + `flag *:[-]<flag_name> inspects the Cabal file of each package in the + snapshot. Consequently, its use will add a few seconds to the duration of + a build. + +!!! note + + For a package included directly in the snapshot, if the Cabal flag + specifications differ from the Cabal flag specifications (if any) in the + snapshot, then the package will automatically be promoted to be an + [extra-dep](#extra-deps). + +!!! note + + In order to set a Cabal flag for a GHC boot package, the package must be + specified as an [extra-dep](../configure/yaml/project.md#extra-deps). + +### `--[no-]force-dirty` flag + +Default: Disabled + +Set the flag to force rebuild of packages even when it doesn't seem necessary +based on file dirtiness. + +### `--[no-]haddock` flag + +Default: Disabled + +Set the flag to build Haddock documentation. This may cause a lot of packages to +get re-built, so that the documentation links work. The `stack haddock` synonym +sets this flag. + +Stack applies Haddock's `--gen-contents` and `--gen-index` flags to generate a +single HTML contents and index for multiple sets of Haddock documentation. + +!!! warning + + On Windows, the values for the `haddock-interfaces` and `haddock-html` keys + in the `*.conf` files for boot packages provided with certain versions of + GHC (in its `lib\package.conf.d` directory) can be corrupt and refer to + non-existent files and directories. For example, in the case of GHC 9.0.1 + to GHC 9.8.1 the references are to + `${pkgroot}/../../docs/html/libraries/...` or + `${pkgroot}/../../doc/html/libraries/...` instead of + `${pkgroot}/../docs/html/libraries/...` or + `${pkgroot}/../doc/html/libraries/...`. Until those values are corrected, + Haddock documentation will be missing links to what those packages expose. + +### `--haddock-arguments` option + +`stack haddock --haddock-arguments <haddock_argument(s)>` passes the specified +arguments to the Haddock tool. + +Specified arguments are separated by spaces. Arguments can be unquoted (if they +do not contain space or `"` characters) or quoted (`""`). Quoted arguments can +include 'escaped' characters, escaped with an initial `\` character. + +!!! note + + Haddock's `--latex` flag is incompatible with the Haddock flags used by + Stack to generate a single HTML contents and index. + +### `--[no-]haddock-deps` flag + +Default: Enabled (if building Haddock documnentation) + +Unset the flag to disable building Haddock documentation for dependencies. + +### `--[no-]haddock-for-hackage` flag + +:octicons-beaker-24: Experimental + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +Default: Disabled + +Set the flag to build project packages with flags to generate Haddock +documentation suitable for upload to Hackage. The form of the Haddock +documentation generated for other packages is unaffected. + +For each project package, the generated Haddock documentation files are in +directory `doc\html\<package_version>-docs\`, relative to Stack's dist work +directory (see [`stack path --dist-dir`](path_command.md)). + +Unless flags are set to exclude the building of project packages, for each +targetted project package with generated documentation, an archive of the +`<package_version>-docs` directory and its contents is in Stack's dist work +directory. (The flags that exclude project packages are +[`--only-dependencies`](#-only-dependencies-flag), +[`--dependencies-only`](#-dependencies-only-flag), or +[`--only-snapshot`](#-only-snapshot-flag).) + +If the flag is set: + +* the [`--[no-]haddock-hyperlink-source`](#-no-haddock-hyperlink-source-flag) + flag is ignored and `--haddock-hyperlink-source` is implied; +* the [`--[no-]haddock-deps`](#-no-haddock-deps-flag) flag is ignored and the + default value for the flag is implied; +* the [`--[no-]haddock-internal`](#-no-haddock-hyperlink-internal-flag) flag is + ignored and `--no-haddock-internal` is implied; +* the [`--[no-]open`](#-no-open-flag) flag is ignored and `--no-open` is + implied; and +* the [`--[no-]force-dirty`](#-no-force-dirty-flag) flag is ignored and + `--force-dirty` is implied. + +!!! info + + Stack does not distinguish the building of Haddock documentation for Hackage + from the building of Haddock documentation generally, which is why the + `--force-dirty` flag is implied. + +!!! note + + If set, Haddock will warn that `-source-*` options are ignored when + `--hyperlinked-source` is enabled. That is due to a known bug in Cabal + (the libiary). + +!!! note + + If set, Cabal (the library) will report that documentation has been created + in `index.html` and `<package_name>.txt` files. Those files do not exist. + That false report is due to a known bug in Cabal (the library). + +### `--[no-]haddock-hyperlink-source` flag + +Default: Enabled + +Unset the flag to disable building building hyperlinked source for Haddock. + +If the [`--haddock-for-hackage`](#-no-haddock-for-hackage-flag) flag is passed, +this flag is ignored. + +### `--[no-]haddock-benchmarks` flag + +Default: Disabled + +Set the flag to enable building Haddock documentation for benchmark components +of packages. + +If the [`--haddock-for-hackage`](#-no-haddock-for-hackage-flag) flag is passed, +this flag is ignored. + +!!! note + + This feature is not supported by versions of Cabal (the library) provided + with GHC 9.2.8 and earlier. + +!!! warning + + Due to a bug in versions of Cabal (the library) provided with GHC 9.8.2 and + earlier, if there is more than one executable (including test suites and + benchmarks) in a project package or more than one project package with an + executable, the Haddock documentation for the `Main` module of one + executable will overwrite the Haddock documentation for others. + +### `--[no-]haddock-executables` flag + +Default: Disabled + +Set the flag to enable building Haddock documentation for executable components +of packages. + +If the [`--haddock-for-hackage`](#-no-haddock-for-hackage-flag) flag is passed, +this flag is ignored. + +!!! note + + This feature is not supported by versions of Cabal (the library) provided + with GHC 9.2.8 and earlier. + +!!! warning + + Due to a bug in versions of Cabal (the library) provided with GHC 9.8.2 and + earlier, if there is more than one executable (including test suites and + benchmarks) in a project package or more than one project package with an + executable, the Haddock documentation for the `Main` module of one + executable will overwrite the Haddock documentation for others. + +### `--[no-]haddock-internal` flag + +Default: Disabled + +Set the flag to enable building Haddock documentation for internal modules. + +If the [`--haddock-for-hackage`](#-no-haddock-for-hackage-flag) flag is passed, +this flag is ignored. + +### `--[no-]haddock-tests` flag + +Default: Disabled + +Set the flag to enable building Haddock documentation for test suite components +of packages. + +If the [`--haddock-for-hackage`](#-no-haddock-for-hackage-flag) flag is passed, +this flag is ignored. + +!!! note + + This feature is not supported by versions of Cabal (the library) provided + with GHC 9.2.8 and earlier. + +!!! warning + + Due to a bug in versions of Cabal (the library) provided with GHC 9.8.2 and + earlier, if there is more than one executable (including test suites and + benchmarks) in a project package or more than one project package with an + executable, the Haddock documentation for the `Main` module of one + executable will overwrite the Haddock documentation for others. + +### `--[no-]keep-going` flag + +Default (`stack build`): Disabled + +Default (`stack test` or `stack bench`): Enabled + +Set the flag to continue building packages even after some build step fails. +The packages which depend upon the failed build won't get built. + +### `--[no-]keep-tmp-files` flag + +Default: Disabled + +Set the flag to keep intermediate files and build directories that would +otherwise be considered temporary and deleted. It may be useful to inspect +these, if a build fails. By default, they are not kept. + +### `--only-configure` flag + +[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) + +Pass the flag to perform only the configure step, not any builds. This is +intended for tool usage. It may break when used on multiple packages at once. + +!!! note + + If there are downstream actions that require a package to be built then a + full build will occur, even if the flag is passed. + +### `--only-dependencies` flag + +Pass the flag to skip building the targets. The flag `--dependencies-only` has +the same effect. + +### `--only-locals` flag + +Pass the flag to build only packages in the local database. Fails if the build +plan includes packages in the snapshot database. + +### `--only-snapshot` flag + +Pass the flag to build only snapshot dependencies, which are cached and shared +with other projects. + +### `--[no-]reconfigure` flag + +Default: Disabled + +Set the flag to force reconfiguration even when it doesn't seem necessary based +on file dirtiness. This is sometimes useful with custom `Setup.hs` files, in +particular when they depend on external data files. + +### `--skip` option + +`stack build --skip <component>` skips building the specified components of a +project package. It allows you to skip test suites and benchmark without +specifying other components (e.g. `stack test --skip long-test-suite` will run +the tests without the `long-test-suite` test suite). Be aware that skipping +executables won't work the first time the package is built due to an issue in +[Cabal](https://github.com/commercialhaskell/stack/issues/3229). + +This option can be specified multiple times to skip multiple components. + +### `--test` flag + +Pass the flag to add test suite components to the targets, if specific +components are not identified. The `stack test` synonym sets this flag. + +## Controlling when building occurs + +### `--file-watch` flag + +Pass the flag to rebuild your project every time a file changes. By default it +will take into account all files belonging to the targets you specify. See also +the `--watch-all` flag. + +### `--file-watch-poll` flag + +Like the `--file-watch` flag, but based on polling the file system instead of +using events to determine if a file has changed. + +### `--watch-all` flag + +[:octicons-tag-24: 2.5.1](https://github.com/commercialhaskell/stack/releases/tag/v2.5.1) + +Pass the flag to rebuild your project every time any local file changes (from +project packages or from dependencies located locally). See also the +`--file-watch` flag. + +## Controlling what happens after building + +### `--benchmark-arguments`, `--ba` option + +`stack build --bench --benchmark-arguments=<argument(s)>` will pass the +specified argument, or arguments, to each benchmark when it is run. + +Specified arguments are separated by spaces. Arguments can be unquoted (if they +do not contain space or `"` characters) or quoted (`""`). Quoted arguments can +include 'escaped' characters, escaped with an initial `\` character. + +Account may need to be taken of the shell's approach to the processing of +command line arguments. For example, to pass `'a single quoted string'`: + +=== "Unix-like (Bash or Zsh)" + + In Bash, or Zsh (if `RC_QUOTES` option not set): + + `stack bench --benchmark-arguments \"\''a single quoted string'\'\"` + + Outside of single quotes, `\"` escapes a double quote and `\'` escapes a + single quote. The content of single quotes is taken literally, but cannot + contain a single quote. + + In Zsh (if `RC_QUOTES` option set): + + `stack bench --benchmark-arguments '"''a single quoted string''"'` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +=== "Windows (PowerShell)" + + `stack bench --benchmark-arguments '"''a single quoted string''"'` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +### `--exec` option + +`stack build --exec '<command> [<argument(s)>]'` will run the specified command +after a successful build. + +Specified arguments are separated by spaces. Arguments can be unquoted (if they +do not contain space or `"` characters) or quoted (`""`). Quoted arguments can +include 'escaped' characters, escaped with an initial `\` character. + +Account may need to be taken of the shell's approach to the processing of +command line arguments. For example, to pass `'a single quoted string'`: + +=== "Unix-like (Bash or Zsh)" + + In Bash, or Zsh (if `RC_QUOTES` option not set): + + `stack build --exec '<command> '\"\''a single quoted string'\'\"` + + Outside of single quotes, `\"` escapes a double quote and `\'` escapes a + single quote. The content of single quotes is taken literally, but cannot + contain a single quote. + + In Zsh (if `RC_QUOTES` option set): + + `stack build --exec '<command> "''a single quoted string''"'` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +=== "Windows (PowerShell)" + + `stack build --exec '<command> "''a single quoted string''"'` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +### `--test-arguments`, `--ta` option + +`stack build --test --test-arguments=<argument(s)>` will pass the specified +argument, or arguments, to each test when it is run. This option can be +specified multiple times. + +Specified arguments are separated by spaces. Arguments can be unquoted (if they +do not contain space or `"` characters) or quoted (`""`). Quoted arguments can +include 'escaped' characters, escaped with an initial `\` character. + +Account may need to be taken of the shell's approach to the processing of +command line arguments. For example, to pass `'a single quoted string'`: + +=== "Unix-like (Bash or Zsh)" + + In Bash, or Zsh (if `RC_QUOTES` option not set): + + `stack test --test-arguments \"\''a single quoted string'\'\"` + + Outside of single quotes, `\"` escapes a double quote and `\'` escapes a + single quote. The content of single quotes is taken literally, but cannot + contain a single quote. + + In Zsh (if `RC_QUOTES` option set): + + `stack bench --benchmark-arguments '"''a single quoted string''"'` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +=== "Windows (PowerShell)" + + `stack test --test-arguments '"''a single quoted string''"'` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +## Flags affecting GHC's behaviour + +### `--[no-]executable-profiling` flag + +Default: Disabled + +Set the flag to enable executable profiling for TARGETs and all its +dependencies. + +The flag affects the location of the local project installation directory. See +the [`stack path --local-install-root`](path_command.md) command. + +### `--[no-]executable-stripping` flag + +Default: Enabled + +Unset the flag to disable executable stripping for TARGETs and all its +dependencies. + +The flag may affect the location of the local project installation directory. +See the [`stack path --local-install-root`](path_command.md) command. + +### `--fast` flag + +GHC has many flags that specify individual optimisations of the compiler. GHC +also uses its `-O*` flags to specify convenient 'packages' of GHC optimisation +flags. GHC's flags are evaluated from left to right and later flags can override +the effect of earlier ones. + +If no GHC `-O*` type flag is specified, GHC takes that to mean "Please +compile quickly; I'm not over-bothered about compiled-code quality." GHC's `-O0` +flag reverts to the same settings as if no `-O*` flags had been specified. + +Pass Stack's `--fast` flag to add `-O0` to the flags and options passed to GHC. +The effect of `--fast` can be overriden with Stack's +[`--ghc-options`](#-ghc-options-option) command line options. + +!!! note + + With one exception, GHC's `-O` flag is always passed to GHC first (being + Cabal's default behaviour). The exception is if Cabal's + `--disable-optimization` flag or `--enable-optimization[=n]`, `-O[n]` + options are used during the configure step of the Cabal build process; see + Stack's + [`configure-options`](../configure/yaml/non-project.md#configure-options) + non-project specific configuration option. + +### `--ghc-options` option + +GHC command line options can be specified for a package in its Cabal file +(including one created from a `package.yaml` file). This option augments and, if +applicable (see below), overrides any such GHC command line options and those +specified in Stack's configuration files - see the +[`ghc-options`](../configure/yaml/non-project.md#ghc-options) non-project +specific configuration option. + +`stack build --ghc-options <ghc_options>` passes the specified command line +options to GHC, depending on Stack's +[`apply-ghc-options`](../configure/yaml/non-project.md#apply-ghc-options) +non-project specific configuration option. This option can be specified multiple +times. + +GHC's command line options are _order-dependent_ and evaluated from left to +right. Later options can override the effect of earlier ones. Any GHC command +line options for a package specified at Stack's command line are applied after +those specified in Stack's configuration files. + +### `--[no-]library-profiling` flag + +Default: Disabled + +Set the flag to enable library profiling for TARGETs and all its dependencies. + +The flag affects the location of the local project installation directory. See +the [`stack path --local-install-root`](path_command.md) command. + +### `--[no-]library-stripping` flag + +Default: Enabled + +Unset the flag to disable library stripping for TARGETs and all its +dependencies. + +The flag may affect the location of the local project installation directory. +See the [`stack path --local-install-root`](path_command.md) command. + +### `--pedantic` flag + +Pass the flag to build your project with the GHC options `-Wall` and `-Werror`. +`-Wall` turns on all warning options that indicate potentially suspicious code. +`-Werror` makes any warning into a fatal error. + +### `--profile` flag + +Pass the flag to enable profiling in libraries, executables, etc. for all +expressions, and generate a profiling report in tests or benchmarks. + +The flag affects the location of the local project installation directory. See +the [`stack path --local-install-root`](path_command.md) command. + +### `--[no-]split-objs` flag + +:octicons-beaker-24: Experimental + +Default: Disabled + +Set the flag to enable the GHC option `-split-objs`. This will reduce output +size (at the cost of build time). + +!!! note + + The behaviour of this feature may be changed and improved. You will need to + clean your project's Stack working directory before use. If you want to + compile all dependencies with split-objs, you will need to delete the + snapshot (and all snapshots that could reference that snapshot). + +!!! note + + GHC's `-split-objs` flag was deprecated in favour of `-split-sections` in + GHC 8.2.1 and was not supported by GHC on any platform from GHC 8.10.1. + +### `--no-strip` flag + +Pass the flag to disable DWARF debugging symbol stripping in libraries, +executables, etc. for all expressions, producing larger executables but allowing +the use of standard debuggers/profiling tools/other utilities that use debugging +symbols. + +The flag affects the location of the local project installation directory. See +the [`stack path --local-install-root`](path_command.md) command. + +### `--trace` flag + +Pass the flag to enable profiling in libraries, executables, etc. for all +expressions, and generate a backtrace on exception. + +The flag affects the location of the local project installation directory. See +the [`stack path --local-install-root`](path_command.md) command. + +## Flags affecting other tools' behaviour + +### `--PROG-option` options + +[:octicons-tag-24: 2.11.1](https://github.com/commercialhaskell/stack/releases/tag/v2.11.1) + +`PROG` is a program recognised by Cabal (the library) and one of `alex`, `ar`, +`c2hs`, `cpphs`, `gcc`, `greencard`, `happy`, `hsc2hs`, `hscolour`, `ld`, +`pkg-config`, `strip` and `tar`. + +`stack build --PROG-option <PROG_argument>` passes the specified command line +argument to `PROG`, if it used by Cabal during the configuration step. This +option can be specified multiple times. For example, if the program `happy` is +used by Cabal during the configuration step, you could command +`stack build --happy-option=--ghc` or `stack build --happy-option --ghc` to pass +to `happy` its `--ghc` flag. + +By default, all and any `--PROG-option` options on Stack's command line are +applied to all project packages (targets or otherwise). This behaviour can be +changed. See the +[`apply-prog-options`](../configure/yaml/non-project.md#apply-prog-options) +configuration option. + +Stack can also be configured to pass Cabal's `--PROG-option`, `--PROG-options` +or other options to Cabal during the configuration step. For further +information, see the documentation for the +[configure-options](../configure/yaml/non-project.md#configure-options) +configuration option. + +## Flags relating to build outputs + +### `--[no]-cabal-verbose` flag + +Default: Disabled + +Set the flag to enable verbose output from Cabal (the library). This flag is an +alternative to the `--cabal-verbosity` option. + +### `--[no]-cabal-verbosity` option + +`stack build --cabal-verbosity <verbosity_level>` sets the specified verbosity +level for output from Cabal (the library). It accepts Cabal's numerical and +extended syntax. This option is an alternative to setting the `--cabal-verbose` +flag. + +### `--[no-]copy-bins` flag + +[:octicons-tag-24: 0.1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.3.0) + +Default: Disabled + +Set the flag to enable copying of built executable files (binaries) of targets +to Stack's local binary directory (see `stack path --local-bin`). The +`stack install` synonym sets this flag. + +### `--[no-]copy-compiler-tool` flag + +[:octicons-tag-24: 1.6.1](https://github.com/commercialhaskell/stack/releases/tag/v1.6.1) + +Default: Disabled + +Set the flag to enable copying of built executable files (binaries) of targets +to Stack's compiler tools binary directory (see +`stack path --compiler-tools-bin`). + +### `--coverage` flag + +Pass the flag to generate a code coverage report. For further information, see +the [code coverage](hpc_command.md) documentation. + +### `--ddump-dir` option + +GHC has a number of `ddump-*` flags and options to allow dumping out of +intermediate structures produced by the compiler. They include the +`-ddump-to-file` flag that causes the output from other flags to be dumped to a +file or files. + +`stack build --ddump_dir <relative_directory>` causes Stack to copy `*.dump-*` +files to subdirectories of the specified directory, which is relative to Stack's +working directory for the project. + +For example: + +~~~text +stack build --ghc-options "-ddump-to-file -ddump-timings" --ddump-dir my-ddump-dir +~~~ + +### `--[no-]interleaved-output` flag + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +Default: Enabled + +Set the flag for interleaved output. With interleaved output, each line of +output from each package being built (targets and dependencies) is sent to the +console as it happens and output relating to different packages can be +interleaved. Each line will be prefixed with the name of the relevant package. +The spacing between the prefix and the output will be set based on the longest +relevant package name, so that the start of the output itself aligns. For +example (extract): + +~~~text +hpack > build +mustache > configure +hpack > Preprocessing library for hpack-0.35.0.. +hpack > Building library for hpack-0.35.0.. +mustache > Configuring mustache-2.4.1... +hpack > [ 1 of 29] Compiling Data.Aeson.Config.Key +hpack > [ 2 of 29] Compiling Data.Aeson.Config.KeyMap +mustache > build +hpack > [ 3 of 29] Compiling Data.Aeson.Config.Util +mustache > Preprocessing library for mustache-2.4.1.. +mustache > Building library for mustache-2.4.1.. +hpack > [ 4 of 29] Compiling Hpack.Haskell +hpack > [ 5 of 29] Compiling Hpack.Utf8 +mustache > [1 of 8] Compiling Paths_mustache +hpack > [ 6 of 29] Compiling Imports +hpack > [ 7 of 29] Compiling Hpack.Util +mustache > [2 of 8] Compiling Text.Mustache.Internal +~~~ + +Unset the flag for non-interleaved output. With non-interleaved output, the +build output from GHC (as opposed to from Stack) in respect of dependencies is +ignored. The behaviour then depends whether there is one target package or more +than one. There can be one target if the project has a single package or if one +package is targetted in a multi-package project (for example, using +`stack build <package_name>`). + +* **One target package:** The build output for the target package is sent to the + standard error stream of the console as it happens. + +* **More than one target package:** The build output from GHC (as opposed to + from Stack) for each target package is sent to a log file for that package, + unless an error occurs that prevents that. If color in output is in use, there + will be two files, one with extension `.log` without color codes and one with + extension `.log-color` with color codes. At the end of the build, the location + of the directory containing the log files is reported. To also output the + contents of the log files to the standard error output stream of the console + at the end of the build, use Stack's `dump-logs` option. For further + information about that option, see the + [`dump-logs](../configure/yaml/non-project.md#dump-logs) non-project + specific configuration option documentation. The default `dump-logs` mode is + to output the contents of any log files that include GHC warnings. + +### `--[no]-open` flag + +Default: Disabled + +Set the flag to enable opening the local Haddock documentation in the browser. + +## Other flags and options + +### `--[no]-prefetch` flag + +Default: Disabled + +Set the flag to enable fetching packages necessary for the build immediately. +This can be useful with `stack build --dry-run`. + +### `--progress-bar` option + +[:octicons-tag-24: 2.13.1](https://github.com/commercialhaskell/stack/releases/tag/v2.13.1) + +Default: `capped` + +`stack build --progress-bar <format>` sets the format of the progress bar, where +`<format>` is one of `none` (no bar), `count-only` (only the package count is +displayed), `capped` (the bar showing package builds in progress is capped to a +length equal to the terminal width), and `full` (the bar is uncapped). On +terminals where 'backspace' has no effect if the cursor is in the first column, +bars longer than the terminal width will not be 'sticky' at the bottom of the +screen. + +### `--tests-allow-stdin` flag + +[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) + +Default: Enabled + +Cabal defines a test suite interface +['exitcode-stdio-1.0'](https://hackage.haskell.org/package/Cabal-syntax-3.8.1.0/docs/Distribution-Types-TestSuiteInterface.html#v:TestSuiteExeV1.0) +where the test suite takes the form of an executable and the executable takes +nothing on the standard input stream (`stdin`). Pass this flag to override that +specification and allow the executable to receive input on that stream. If you +pass `--no-tests-allow-stdin` and the executable seeks input on the standard +input stream, an exception will be thown. + +## Examples + +All the following examples assume that: + +* if `stack build` is commanded outside of a project directory, there is no + `stack.yaml` file in the current directory or ancestor directory and, + consequently, the project-level configuration will be determined by a + `stack.yaml` file in the `global-project` directory in the + [Stack root](../topics/stack_root.md) (for further information, see the + [configuration](../configure/yaml/index.md) documentation); and + +* if `stack build` is commanded in a project directory, there is a + `stack.yaml` file in that directory. + +Examples: + +* In the project directory, `stack build --test --copy-bins` or, equivalently, + `stack test --copy-bins` or `stack install --test`, will build libraries, + executables, and test suites, run the test suites, and then copy the + executables to Stack's local binary directory (see + `stack path --local-bin`). This is an example of the flags composing. + +* The following example uses a clone of the + `wai` [repository](https://github.com/yesodweb/wai/). The `wai` project + comprises a number of packages, including `wai-extra` and `warp`. In the + `wai` project directory, the command: + + ~~~text + stack build --file-watch --test --copy-bins --haddock wai-extra :warp warp:doctest --exec 'echo Yay, it worked!' + ~~~ + + will start Stack up in file watch mode, waiting for files in your project to + change. When first starting, and each time a file changes, it will do all of + the following. + + * Build the `wai-extra` package and its test suites + * Build the `warp` executable + * Build the `warp` package's `doctest` component (which is a test site) + * Run all of the `wai-extra` package's test suite components and the + `doctest` test suite component + * If all of that succeeds: + * Copy generated executables to Stack's local binary directory (see + `stack path --local-bin`) + * Run the command `echo Yay, it worked!` + +* The following example uses the `Adga` package and assumes that `Adga-2.6.3` + is the latest version in the package index (e.g. Hackage) and is not a + version in the snapshot specified by the `stack.yaml` in the + `global-project` directory in the Stack root. + + Outside a project directory, `stack build Adga-2.6.3 --copy-bins` or, + equivalently, `stack install Agda-2.6.3`, will attempt to build the + libraries and executables of the identified version of the package in the + package index (using the `stack.yaml` file in the `global-project` + directory in the Stack root), and then copy the executables to Stack's local + binary directory (see `stack path --local-bin`). + + If a different snapshot is required to build the identified version of the + package, then that can be specified at the command line. For example, to use + the most recent Stackage Nightly snapshot: + + ~~~text + stack --snapshot nightly install Agda-2.6.3 + ~~~ + + Alternatively, Stack can be used to unpack the package from the package + index into a local project directory named after the package identifier (for + further infomation, see the [`stack unpack` command](unpack_command.md) + documentation) and, if the package does not provide its own Stack + configuration file (`stack.yaml`, by default), to attempt to initialise that + configuration (for further information, see the + [`stack init` command](init_command.md) documentation). For example: + + ~~~text + stack unpack Agda-2.6.3 + cd Agda-2.6.3 # Change to the project directory + stack init # Attempt to create a project stack.yaml file + stack install # Equivalent to stack build --copy-bins + ~~~
+ doc/commands/clean_command.md view
@@ -0,0 +1,21 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack clean` command + +Either + +~~~text +stack clean [PACKAGE] +~~~ + +or + +~~~text +stack clean --full +~~~ + +`stack clean` deletes build artefacts for one or more project packages specified +as arguments. If no project packages are specified, all project packages are +cleaned. + +`stack clean --full` deletes the project's Stack working directory.
+ doc/commands/config_command.md view
@@ -0,0 +1,151 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack config` commands + +~~~text +stack config COMMAND + +Available commands: + env Print environment variables for use in a shell + set Sets a key in configuration file to value +~~~ + +The `stack config` commands provide assistance with accessing or modifying +Stack's configuration. See `stack config` for the available commands. + +## The `stack config env` command + +~~~text +stack config env [--[no-]locals] [--[no-]ghc-package-path] [--[no-]stack-exe] + [--[no-]locale-utf8] [--[no-]keep-ghc-rts] +~~~ + +`stack config env` outputs a script that sets or unsets environment variables +for a Stack environment. Flags modify the script that is output: + +* `--[no-]locals` (enabled by default) include/exclude project package + information +* `--[no-]ghc-package-path` (enabled by default) set `GHC_PACKAGE_PATH` + environment variable or not +* `--[no-]stack-exe` (enabled by default) set `STACK_EXE` environment variable + or not +* `--[no-]locale-utf8` (disabled by default) set the `GHC_CHARENC` + environment variable to `UTF-8` or not +* `--[no-]keep-ghc-rts` (disabled by default) keep/discard any `GHCRTS` + environment variable + +The command also accepts flags and options of the +[`stack build`](build_command.md#flags-affecting-ghcs-behaviour) command that +affect the location of the local project installation directory, such as +`--profile` and `--no-strip`. For further information, see the documentation of +the [project Stack work directory](../topics/stack_work.md). + +## The `stack config set` commands + +~~~text +stack config set COMMAND + +Available commands: + install-ghc Configure whether or not Stack should automatically + install GHC when necessary. + package-index Configure Stack's package index + recommend-stack-upgrade Configure whether or not Stack should notify the user + if it identifes a new version of Stack is available. + resolver Change the snapshot of the current project, using the + resolver key. + snapshot Change the snapshot of the current project. + system-ghc Configure whether or not Stack should use a system + GHC installation. +~~~ + +The `stack config set` commands allow the values of keys in configuration files +to be set. See `stack config set` for the available keys. + +!!! note + + The `config set` commands support an existing key only in the form + `key: value` on a single line. + +## The `stack config set install-ghc` command + +~~~text +stack config set install-ghc [--global] true|false +~~~ + +`stack config set install-ghc true` or `false` sets the +[`install-ghc`](../configure/yaml/non-project.md#install-ghc) non-project +specific configuration option in a configuration file, accordingly. By default, +the project-level configuration file (`stack.yaml`, by default) is altered. The +`--global` flag specifies the user-specific global configuration file +(`config.yaml`). + +## The `stack config set package-index download-prefix` command + +[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) + +~~~text +stack config set package-index download-prefix [--global] [URL] +~~~ + +`stack config set package-index download-prefix <url>` sets the +`download-prefix` key of the +[`package-index`](../configure/yaml/non-project.md#package-index) non-project +specific configuration option in a configuration file, accordingly. By default, +the project-level configuration file (`stack.yaml`, by default) is altered. The +`--global` flag specifies the user-specific global configuration file +(`config.yaml`). + +## The `stack config set recommend-stack-upgrade` command + +~~~text +stack config set recommend-stack-upgrade [--project] true|false +~~~ + +`stack config set recommend-stack-upgrade true` or `false` sets the +[`recommend-stack-upgrade`](../configure/yaml/non-project.md#recommend-stack-upgrade) +non-project specific configuration option in a configuration file, accordingly. +By default, the user-specific global configuration file (`config.yaml`) is +altered. The `--project` flag specifies the project-level configuration file +(`stack.yaml`, by default). + +## The `stack config set resolver` command + +~~~text +stack config set resolver SNAPSHOT +~~~ + +A command corresponding to the +[`stack config set snapshot` command](#the-stack-config-set-snapshot-command) +but using the `resolver` key instead of the `snapshot` key. + +## The `stack config set snapshot` command + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +~~~text +stack config set snapshot SNAPSHOT +~~~ + +`stack config set snapshot <snapshot>` sets the +[`snapshot`](../configure/yaml/project.md#snapshot) project-specific +configuration option in the project-level configuration file (`stack.yaml`, by +default) to the specified snapshot. + +A snapshot of `lts` or `nightly` will be translated into the most recent +available. A snapshot of `lts-22` will be translated into the most recent +available in the `lts-22` sequence. + +If a `resolver` key is present, it will be replaced by a `snapshot` key. + +## The `stack config set system-ghc` command + +~~~text +stack config set system-ghc [--global] true|false +~~~ + +`stack config set system-ghc true` or `false` sets the +[`system-ghc`](../configure/yaml/non-project.md#system-ghc) non-project +specific configuration option in a configuration file, accordingly. By default, +the project-level configuration file (`stack.yaml`, by default) is altered. The +`--global` flag specifies the user-specific global configuration file +(`config.yaml`).
+ doc/commands/docker_command.md view
@@ -0,0 +1,37 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack docker` commands + +~~~text +stack docker COMMAND + +Available commands: + pull Pull latest version of Docker image from registry + reset Reset the Docker sandbox +~~~ + +Stack is able to build your code inside a Docker image, which means even more +reproducibility to your builds, since you and the rest of your team will always +have the same system libraries. + +For further information, see the +[Docker integration](../topics/docker_integration.md) documentation. + +## The `stack docker pull` command + +~~~text +stack docker pull +~~~ + +`stack docker pull` pulls the latest version of the Docker image from the +registry. + +## The `stack docker reset` command + +~~~text +stack docker reset [--keep-home] +~~~ + +`stack docker reset` resets the Docker sandbox. + +Pass the flag `--keep-home` to preserve the sandbox's home directory.
+ doc/commands/dot_command.md view
@@ -0,0 +1,103 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack dot` command + +~~~text +stack dot [--[no-]external] [--[no-]include-base] [--depth DEPTH] + [--prune PACKAGES] [TARGET] [--flag PACKAGE:[-]FLAG] + [--test] [--bench] [--global-hints] +~~~ + +A package and its dependencies and the direct dependency relationships between +them form a directed graph. [Graphviz](https://www.graphviz.org/) is open source +software that visualises graphs. It provides the DOT language for defining +graphs and the `dot` executable for drawing directed graphs. Graphviz is +available to [download](https://www.graphviz.org/download/) for Linux, Windows, +macOS and FreeBSD. + +`stack dot` produces output, to the standard output stream, in the DOT language +to represent the relationships between your packages and their dependencies. + +By default: + +* external dependencies are excluded from the output. Pass the flag + `--external` to include external dependencies; +* the `base` package and its dependencies are included in the output. Pass the + flag `--no-include-base` to exclude `base` and its dependencies; +* there is no limit to the depth of the resolution of dependencies. Pass the + `--depth <depth>` option to limit the depth; +* all relevant packages are included in the output. Pass the + `--prune <packages>` option to exclude the specified packages, where + `<packages>` is a list of package names separated by commas; +* all packages in the project are included in the output. However, the target + for the command can be specified as an argument. It uses the same format + as the [`stack build` command](build_command.md); +* test components of the packages in the project are excluded from the output. + Pass the flag `--test` to include test components; and +* benchmark components of the packages in the project are excluded from the + output. Pass the flag `--bench` to include benchmark components.git p + +Pass the option `--flag <package_name>:<flag_name>` or +`--flag <package_name>:-<flag_name>` to set or unset a Cabal flag. This +option can be specified multiple times. + +Pass the flag `--global-hints` to use a hint file for global packages. If a hint +file is used, GHC does not need to be installed. + +## Examples + +The following examples are based on a version of the +[`wreq` package](https://hackage.haskell.org/package/wreq). In each case, the +output from `stack dot` is piped as an input into Graphviz's `dot` executable, +and `dot` produces output in the form of a PNG file named `wreq.png`. + +* A simple example: + + ~~~text + stack dot | dot -Tpng -o wreq.png + ~~~ + + [](https://cloud.githubusercontent.com/assets/591567/8478591/ae10a418-20d2-11e5-8945-55246dcfac62.png) + +* Include external dependencies: + + ~~~text + stack dot --external | dot -Tpng -o wreq.png + ~~~ + + [](https://cloud.githubusercontent.com/assets/591567/8478621/d247247e-20d2-11e5-993d-79096e382abd.png) + +* Include external dependencies, limit the depth and save the output from + `stack dot` as an intermediate file (`wreq.dot`). + + ~~~text + stack dot --external --depth 1 > wreq.dot + dot -Tpng -o wreq.png wreq.dot + ~~~ + +* Include external dependencies, exclude `base` and limit the depth: + + ~~~text + stack dot --no-include-base --external --depth 1 | dot -Tpng -o wreq.png + ~~~ + + [](https://cloud.githubusercontent.com/assets/591567/8484310/45b399a0-20f7-11e5-8068-031c2b352961.png) + +* Include external dependencies and prune `base` and other packages: + + ~~~text + stack dot --external --prune base,lens,wreq-examples,http-client,aeson,tls,http-client-tls,exceptions | dot -Tpng -o wreq.png + ~~~ + + [](https://cloud.githubusercontent.com/assets/591567/8478768/adbad280-20d3-11e5-9992-914dc24fe569.png) + +* Include external dependencies, prune `base` and other packages, and use a + different Graphviz executable to draw the graph: + + Graphviz's `twopi` executable draws graphs in a radial layout. + + ~~~text + stack dot --external --prune base,lens,wreq-examples,http-client,aeson,tls,http-client-tls,exceptions | twopi -Groot=wreq -Goverlap=false -Tpng -o wreq.png + ~~~ + + [](https://cloud.githubusercontent.com/assets/591567/8495538/9fae1184-216e-11e5-9931-99e6147f8aed.png)
+ doc/commands/eval_command.md view
@@ -0,0 +1,20 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack eval` command + +~~~text +stack eval CODE [--[no-]ghc-package-path] [--[no-]stack-exe] + [--package PACKAGE] [--rts-options RTSFLAG] [--cwd DIR] +~~~ + +GHC has an +[expression-evaluation mode](https://downloads.haskell.org/ghc/latest/docs/users_guide/using.html#eval-mode), +set by passing the GHC option +`-e <expression>`. Commanding `stack eval <code>` is equivalent to commanding: + +~~~text +stack exec ghc -- -e <code> +~~~ + +For further information, see the [`stack exec` command](exec_command.md) +documentation.
+ doc/commands/exec_command.md view
@@ -0,0 +1,72 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack exec` command + +~~~text +stack exec COMMAND + [-- ARGUMENT(S) (e.g. stack exec ghc-pkg -- describe base)] + [--[no-]ghc-package-path] [--[no-]stack-exe] [--package PACKAGE] + [--rts-options RTSFLAG] [--cwd DIR] +~~~ + +`stack exec` executes the specified executable as a command in the Stack +environment. If an executable is not specified, the first argument after `--` is +taken to be the executable. Otherwise, all arguments after `--` are taken to be +command line arguments for the specified executable. + +By default: + +* the `GHC_PACKAGE_PATH` environment variable is set for the command's process. + Pass the flag `--no-ghc-package-path` to not set the environment variable; + +* the `STACK_EXE` environment variable is set for the command's process. Pass + the flag `--no-stack-exe` to not set the environment variable; and + +* the specified executable is executed in the current directory. Pass the option + `--cwd <directory>` to execute the executable in the specified directory. + +The option `--package <package>` has no effect for the `stack exec` command. For +further information about its use, see the [`stack ghc` command](ghc_command.md) +documentation or the [`stack runghc` command](runghc_command.md) documentation. + +Pass the option `--rts-option <rts_flag(s)>` to specify a GHC RTS flag or option. +The option can be specified multiple times. All specified GHC RTS flags and +options are added to the arguments for the specified executable between +arguments `+RTS` and `-RTS`. + +Specified GHC RTS flags and options are separated by spaces. Items can be +unquoted (if they do not contain space or `"` characters) or quoted (`""`). +Quoted items can include 'escaped' characters, escaped with an initial `\` +character. + +Account may need to be taken of the shell's approach to the processing of +command line arguments. For example, to pass `'a single quoted string'`: + +=== "Unix-like (Bash or Zsh)" + + In Bash, or Zsh (if `RC_QUOTES` option not set): + + `stack exec <command> -- \''a single quoted string'\'` + + Outside of single quotes, `\'` escapes a single quote. The content of single + quotes is taken literally, but cannot contain a single quote. + + In Zsh (if `RC_QUOTES` option set): + + `stack exec <command> -- '''a single quoted string'''` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +=== "Windows (PowerShell)" + + `stack exec <command> -- '''a single quoted string'''` + + The content of single quotes is taken literally. Within single quotes, `''` + escapes a single quote. + +The command also accepts flags and options of the +[`stack build`](build_command.md#flags-affecting-ghcs-behaviour) command that +affect the location of the local project installation directory, such as +`--profile` and `--no-strip`. For further information, see the documentation of +the [project Stack work directory](../topics/stack_work.md).
+ doc/commands/ghc_command.md view
@@ -0,0 +1,21 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack ghc` command + +~~~text +stack ghc [-- ARGUMENT(S) (e.g. stack ghc -- X.hs -o x)] + [--[no-]ghc-package-path] [--[no-]stack-exe] [--package PACKAGE] + [--rts-options RTSFLAG] [--cwd DIR] +~~~ + +`stack ghc` has the same effect as, and is provided as a shorthand for, +[`stack exec ghc`](exec_command.md), with the exception of the `--package` +option. + +Pass the option `--package <package(s)>` to add the initial GHC argument +`-package-id=<unit_id>`, where `<unit_id>` is the unit ID of the specified +package in the installed package database. The option can be a list of package +names or package identifiers separated by spaces. The option can also be +specified multiple times. The approach taken to these packages is the same as if +they were specified as targets to +[`stack build`](build_command.md#target-syntax).
+ doc/commands/ghci_command.md view
@@ -0,0 +1,161 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack ghci` and `stack repl` commands + +~~~text +stack ghci [TARGET/FILE] [--pedantic] [--ghci-options OPTIONS] + [--ghc-options OPTIONS] [--flag PACKAGE:[-]FLAG] [--with-ghc GHC] + [--[no-]load] [--package PACKAGE] [--main-is TARGET] + [--load-local-deps] [--[no-]package-hiding] [--only-main] [--trace] + [--profile] [--no-strip] [--[no-]test] [--[no-]bench] +~~~ + +A read–evaluate–print loop (REPL) environment takes single user inputs, executes +them, and returns the result to the user. GHCi is GHC's interactive environment. +The `stack ghci` or `stack repl` commands, which are equivalent, allow you to +load components and files of your project into GHCi. + +The command accepts the same TARGET syntax as +[`stack build`](build_command.md#target-syntax). By default: + +* Stack loads up GHCi with all the library and executable components of all the + packages in the project. Pass the flag `--test` to include test suite + components (unlike `stack build`, test suites will not be run). Pass the flag + `--bench` to include benchmark components (unlike `stack build`, benchmarks + will not be run). + +It is also possible to specify a module source code file. For example: + +~~~text +stack ghci src/MyFile.hs +~~~ + +Stack will identify which component the file is associated with, and use the +options from that component. + +Pass the `--package` option to load GHCi with an additional package that is not +a direct dependency of your components. This option can be specified multiple +times. + +Pass the option `--flag <package_name>:<flag_name>` or +`--flag <package_name:-<flag_name>` to set or unset a Cabal flag. This option +can be specified multiple times. The same Cabal flag name can be set (or unset) +for multiple packages with: + +~~~text +--flag *:[-]<flag_name> +~~~ + +!!! note + + In order to set a Cabal flag for a GHC boot package, the package must either + be an extra-dep or the package version must be specified with the + `--package` option. + +By default: + +* Stack uses the GHC specified in Stack's configuration. Pass the `--with-ghc` + option with a file path to the executable to specify a different GHC + executable; + +* Stack performs an inital build step. Pass the `--no-build` flag to skip the + step. Pass the `--ghc-options` option to pass flags or options to GHC. Pass + the `--profile`, `--no-strip`, `--trace` flags for the same behaviour as in + the case of the `stack build` command. + + !!! info + + Not performing the initial build step speeds up the startup of GHCi. It + only works if the dependencies of the loaded packages have already been + built. + +* Stack runs GHCi via `ghc --interactive`. Pass the `--ghc-options` option to + pass flags or options to GHC (during the initial build step) and to GHCi. + Pass the `--pedantic` flag to pass the GHC options `-Wall` and `-Werror` to + GHCi (only). Pass the `--ghci-options` option to pass flags or options to + GHCi (only). + +* Stack configures GHCi to hide unnecessary packages, unless no packages are + targetted and no additional packages are specified. Pass the + `--package-hiding` flag to hide unnecessary packages or + `--no-package-hiding` flag not to hide unnecessary packages. + +* Stack loads and imports all of the modules for each target. Pass the + `--no-load` flag to skip the loading of modules. Pass the `--only-main` flag + to skip the loading of modules other than the main module. Pass the + `--load-local-deps` flag to include all local dependencies of targets. + + !!! info + + Not loading modules speeds up the startup of GHCi. Once in GHCi, you can + use `:load myModule` to load a specific module in your project. + + !!! info + + The `--only-main` flag can be useful if: + + 1. You're loading the project in order to run it in GHCi (e.g. via + `main`), and you intend to reload while developing. Without flag, + you will need to quit and restart GHCi whenever a module gets + deleted. With the flag, reloading should work fine in this case. + + 2. If many of your modules have exports named the same thing, then + you'll need to refer to them using qualified names. To avoid this, + use the `--only-main` flag to start with a blank slate and just + import the modules you are interested in. + +* If there are multiple definitions for the `Main` module, Stack will ask you + to select one from a list of options. Pass the `--main-is <target>` option + to specific which `Main` module to load. + +Stack combines all of the GHC options of components. + +!!! note + + Combining GHC options should work out when packages share similar + conventions. However, conflicts may arise, such as when one component + defines default extensions which aren't assumed by another. For example, + specifying `NoImplicitPrelude` in one component but not another is likely to + cause failures. GHCi will be run with `-XNoImplicitPrelude`, but it is + likely that modules in the other component assume that the `Prelude` is + implicitly imported. + +`stack ghci` configures GHCi by using a GHCi script file. Such files are located +in subdirectories of `<XDG_CACHE_HOME>/stack/ghci-script`, where +`<XDG_CACHE_HOME>` refers to the +[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) +for user-specific non-essential (cached) data. + +=== "Unix-like" + + The default for `<XDG_CACHE_HOME>` is `$HOME/.cache`. + +=== "Windows" + + On Windows, the default for `<XDG_CACHE_HOME>` is `%LOCALAPPDATA%`. + +## Running plain GHCi + +`stack ghci` always runs GHCi configured to load code from packages in your +project. In particular, this means it passes in flags like `-hide-all-packages` +and `-package-id=` in order to configure which packages are visible to GHCi. + +For doing experiments which just involve packages installed in your databases, +it may be useful to run GHCi plainly like: + +~~~text +stack exec ghci +~~~ + +This will run a plain GHCi in an environment which includes `GHC_PACKAGE_PATH`, +and so will have access to your databases. + +!!! note + + Running `stack ghci` on a pristine copy of the code doesn't currently build + libraries + (issue [#2790](https://github.com/commercialhaskell/stack/issues/2790)) or + internal libraries + (issue [#4148](https://github.com/commercialhaskell/stack/issues/4148)). It + is recommended to always use `stack build` before using `stack ghci`, until + these two issues are closed.
+ doc/commands/haddock_command.md view
@@ -0,0 +1,30 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack bench` command + +~~~text +stack haddock [TARGET] [--dry-run] [--pedantic] [--fast] [--ghc-options OPTIONS] + [--flag PACKAGE:[-]FLAG] [--dependencies-only | --only-snapshot | + --only-dependencies | --only-locals] [--file-watch | + --file-watch-poll] [--watch-all] [--exec COMMAND [ARGUMENT(S)]] + [--only-configure] [--trace] [--profile] [--no-strip] + [--[no-]library-profiling] [--[no-]executable-profiling] + [--[no-]library-stripping] [--[no-]executable-stripping] + [--[no-]haddock] [--haddock-arguments HADDOCK_ARGS] + [--[no-]open] [--[no-]haddock-deps] [--[no-]haddock-internal] + [--[no-]haddock-hyperlink-source] [--[no-]haddock-for-hackage] + [--[no-]copy-bins] [--[no-]copy-compiler-tool] [--[no-]prefetch] + [--[no-]keep-going] [--[no-]keep-tmp-files] [--[no-]force-dirty] + [--[no-]test] [--[no-]rerun-tests] + [--ta|--test-arguments TEST_ARGS] [--coverage] [--no-run-tests] + [--test-suite-timeout ARG] [--[no-]tests-allow-stdin] + [--[no-]bench] [--ba|--benchmark-arguments BENCH_ARGS] + [--no-run-benchmarks] [--[no-]reconfigure] + [--cabal-verbosity VERBOSITY | --[no-]cabal-verbose] + [--[no-]split-objs] [--skip ARG] [--[no-]interleaved-output] + [--ddump-dir ARG] +~~~ + +`stack haddock` is a synonym for `stack build --haddock`. For further +information, see the documentation for the [`stack build`](build_command.md) +command.
+ doc/commands/hoogle_command.md view
@@ -0,0 +1,33 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack hoogle` command + +~~~text +stack hoogle [-- ARGUMENT(S) (e.g. 'stack hoogle -- server --local')] + [--[no-]setup] [--rebuild] [--server] +~~~ + +Hoogle is a Haskell API search engine. `stack hoogle` runs Hoogle. Stack needs +Hoogle version 5 or greater. + +Stack will use a Hoogle database (`database.hoo`) specific to the project's +source map and the version of GHC, located in a subdirectory of subdirectory +`hoogle` of Stack's work directory for the project. + +By default: + +* if a `hoogle` executable is found on the `PATH`, Stack will try to use it. + Otherwise, Stack will try to identify an executable as a build target. If + the Hoogle database does not exist, Stack will generate it with + `hoogle generate --local`. `hoogle generate --local` queries `ghc-pkg` and + generates links for all packages which have documentation and Hoogle input + files (`*.txt`) generated. Pass the flag `--no-setup` to skip such setup; + +* the existing Hoogle database is used. Pass the flag `--rebuild` to trigger + the generation of a new Hoogle database (generated as above); and + +* `hoogle` is passed the specified arguments (if any). The arguments are + usually the subject of the search. Pass the flag `--server` to first pass + `server --local --port 8080` before those arguments. + `hoogle server --local --port 8080` starts a local Hoogle web server, using + port 8080, that allows the following of `file://` links.
+ doc/commands/hpc_command.md view
@@ -0,0 +1,167 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack hpc` commands + +~~~text +stack hpc COMMAND + +Available commands: + report Generate unified HPC coverage report from tix files + and project targets +~~~ + +Code coverage is a measure of the degree to which the source code of a program +is executed when a test suite is run. +[Haskell Program Coverage (HPC)](https://ku-fpg.github.io/software/hpc/) is a +code coverage tool for Haskell that is provided with GHC. Code coverage is +enabled by passing the flag `--coverage` to `stack build`. + +`stack hpc` provides commands specific to HPC. Command `stack hpc` for the +available commands. + +The following refers to the local HPC root directory. Its location can be +obtained by command: + +~~~text +stack path --local-hpc-root +~~~ + +## The `stack hpc report` command + +~~~text +stack hpc report [TARGET_OR_TIX] [--all] [--destdir DIR] [--open] +~~~ + +The `stack hpc report` command generates a report for a selection of targets and +`.tix` files. + +Pass the flag `--all` for a report that uses all stored results. + +Pass the flag `--open` to open the HTML report in your browser. + +## The `extra-tix-files` directory + +During the execution of the build, you can place additional tix files in the +`extra-tix-files` subdirectory in the local HPC root directory, in order for +them to be included in the unified report. A couple caveats: + +1. These tix files must be generated by executables that are built against the + exact same library versions. Also note that, on subsequent builds with + coverage, the local HPC root directory will be recursively deleted. It + just stores the most recent coverage data. + +2. These tix files will not be considered by `stack hpc report` unless listed + explicitly by file name. + +## Examples + +If we have three different packages with test suites, packages `A`, `B`, and +`C`, the default unified report will have coverage from all three. If we want a +unified report with just two, we can instead command: + +~~~text +stack hpc report A B +~~~ + +This will output to the standard output stream a summary report for the combined +coverage from `A` and `B`'s test suites. It will also log the path to the HTML +for the corresponding full report. + +This command also supports taking extra `.tix` files. If you've also built an +executable, against exactly the same library versions of `A`, `B`, and `C`, then +you could command the following: + +~~~text +stack exec -- an-exe +stack hpc report A B C an-exe.tix +~~~ + +or, equivalently: + +~~~text +stack exec -- an-exe +stack hpc report --all an-exe.tix +~~~ + +This report will consider all test results as well as the newly generated +`an-exe.tix` file. + +## Usage + +`stack test --coverage` is quite streamlined for the following use-case: + +1. You have test suites which exercise your project packages. + +2. These test suites link against your library, rather than building the + library directly. Coverage information is only given for libraries, ignoring + the modules which get compiled directly into your executable. A common case + where this doesn't happen is when your test suite and library both have + something like `hs-source-dirs: src/`. In this case, when building your test + suite you may also be compiling your library, instead of just linking + against it. + +When your project has these properties, you will get the following: + +1. Summary coverage reports, sent to the standard output stream in the build + output, and a log of the paths to the HTML for the corresponding full + reports. + +2. A summary unified report, sent to the standard output stream, and a log of + the path to the HTML for the corresponding full report. These reports + consider the coverage on all local libraries, based on all of the tests that + were run. + +3. An index of all generated HTML reports, in `index.html` in the local + HPC root directory, and a log of the path to the HTML for that index. + +## Implementation details + +Most users can get away with just understanding the above documentation. +However, advanced users may want to understand exactly how `--coverage` works: + +1. The GHC option `-fhpc` gets passed to all project packages. This tells GHC to + output executables that track coverage information and output them to `.tix` + files. `the-exe-name.tix` files will get written to the working directory of + the executable. + + When switching on this flag, it will usually cause all project packages to be + rebuilt (see issue + [#1940](https://github.com/commercialhaskell/stack/issues/1940)). + +2. Before the build runs with `--coverage`, the contents of the local HPC root + directory gets deleted. This prevents old reports from getting mixed + with new reports. If you want to preserve report information from multiple + runs, copy the contents of this path to a new directory. + +3. Before a test run, if a `test-name.tix` file exists in the package directory, + it will be deleted. + +4. After a test run, it will expect a `test-name.tix` file to exist. This file + will then get loaded, modified, and outputted to + `pkg-name/test-name/test-name.tix` in the local HPC root directory. + + The `.tix` file gets modified to remove coverage file that isn't associated + with a library. So, this means that you won't get coverage information for + the modules compiled in the `executable` or `test-suite` stanza of your Cabal + file. This makes it possible to directly union multiple `*.tix` files from + different executables (assuming they are using the exact same versions of the + project packages). + + If there is enough popular demand, it may be possible in the future to give + coverage information for modules that are compiled directly into the + executable. See issue + [#1359](https://github.com/commercialhaskell/stack/issues/1359). + +5. Once we have a `.tix` file for a test, we also generate a summary report and + a corresponding full report using HTML. The summary report is sent to the + standard output stream. The index of the test-specific HTML report is + available at `pkg-name/test-name/index.html` in the local HPC root directory. + +6. After the build completes, if there are multiple output `*.tix` files, they + get combined into a unified report. The index of this report will be + available at `combined/all/index.html` in the local HPC root directory. + +7. Finally, an index of the resulting coverage reports is generated. It links to + the individual coverage reports (one for each test-suite), as well as the + unified report. This index is available at `index.html` in the local HPC root + directory.
+ doc/commands/ide_command.md view
@@ -0,0 +1,72 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack ide` commands + +~~~text +stack ide COMMAND + +Available commands: + packages List all available local loadable packages + targets List all available Stack targets +~~~ + +The `stack ide` commands provide information that may be of use in an +integrated development environment (IDE). See `stack ide` for the available +commands. + +## The `stack ide packages` command + +~~~text +stack ide packages [--stdout] [--cabal-files] +~~~ + +`stack ide packages` lists all available project packages that are loadable. + +By default: + +* its output is sent to the standard error stream. Pass the flag `--stdout` to + change to the standard output stream; and +* the output is the package name (without its version). Pass the flag + `--cabal-files` to change to the full path to the package's Cabal file. + +## The `stack ide targets` command + +~~~text +stack ide targets [--exes] [--tests] [--benchmarks] [--stdout] +~~~ + +`stack ide targets` lists all available Stack targets. Alternatively, pass one +or more of the flags `--exes`, `--tests` and `--benchmarks` to list only targets +of those component types. + +By default, its output is sent to the standard error stream. Pass the flag +`--stdout` to change to the standard output stream. + +For example, for the Stack project itself, command: + +~~~text +cd stack +stack ide targets +~~~ + +and the output from the second command is: + +~~~text +stack:lib +stack:exe:stack +stack:exe:stack-integration-test +stack:test:stack-unit-test +~~~ + +or command: + +~~~text +stack ide targets --exes +~~~ + +and the output is: + +~~~text +stack:exe:stack +stack:exe:stack-integration-test +~~~
+ doc/commands/index.md view
@@ -0,0 +1,136 @@+--- +title: Commands +--- +<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Commands (advanced) + +Some of Stack's features will not be needed regularly or by all users. This part +of the guide and the part on [configuration](../configure/index.md) provide +information about some of those features, organised as a reference guide. Some +of the features are complex and separate pages are dedicated to them. + +## Stack commands (thematic) + +### Setting up + +* [`setup`](setup_command.md) - get GHC for a Stack project (usually not needed) +* [`update`](update_command.md) - update the package index (usually not needed) +* [`new`](new_command.md) - create a new project with Stack +* [`init`](init_command.md) - initialise Stack's project-level YAML + configuration file for an existing project + +### Building + +* [`build`](build_command.md) - build packages +* [`test`](build_command.md) - a synonym for `stack build --test` +* [`bench`](build_command.md) - a synonym for `stack build --bench` +* [`haddock`](build_command.md) - a synonym for `stack build --haddock` +* [`install`](build_command.md) - a synonym for `stack build --copy-bins` +* [`run`](run_command.md) - build and run an executable + +### Docker-related + +* [`docker`](docker_command.md) - use Stack with Docker + +### Executing in the Stack environment + +* [`exec`](exec_command.md) - executate a command in the Stack environment +* [`ghc`](ghc_command.md) - run `ghc` +* [`eval`](eval_command.md) - evaluate some Haskell code inline +* [`runghc`](runghc_command.md) - run `runghc` +* [`runhaskell`](runghc_command.md) - a synonym for `stack runghc` + +### Using GHC interactively + +* [`ghci`](ghci_command.md) - run GHCi, a REPL environment +* [`repl`](ghci_command.md) - a synonym for `stack ghci` + +### Down/up loading local packages from/to Hackage + +* [`unpack`](unpack_command.md) - unpack one or more packages locally +* [`sdist`](sdist_command.md) - create an archive file for a package, in a form + accepted by Hackage +* [`upload`](upload_command.md) - upload a package to Hackage + +### Cleaning-up + +* [`clean`](clean_command.md) - delete build artefacts for the project packages +* [`purge`](purge_command.md) - delete the Stack working directories + +### Amending Stack's configuration files + +* [`config set`](config_command.md) - modify Stack's configuration + +### Using Haskell code as a script +* [`script`](script_command.md) - run a Haskell source file as a script + +### Getting information + +* [`path`](path_command.md) - information about locations used by Stack +* [`ls`](ls_command.md) - list information about Stack +* [`list`](list_command.md) - list packages on Hackage or in a snapshot +* [`ide`](ide_command.md) - information for an integrated development + environment (IDE) +* [`query`](query_command.md) - information about the build +* [`config env`](config_command.md) - modify Stack's configuration +* [`templates`](templates_command.md) - information about templates for use with + `stack new` +* [`uninstall`](uninstall_command.md) - information about how to uninstall Stack + +### Using tools in Stack's environment + +* [`hoogle`](hoogle_command.md) - run `hoogle` +* [`dot`](dot_command.md) - dependency visualization +* [`hpc`](hpc_command.md) - generate Haskell Program Coverage (HPC) code + coverage reports + +### Managing Stack versions + +* [`upgrade`](upgrade_command.md) - upgrade Stack + +## Stack commands (alphabetical) + +Stack's commands are listed below, in alphabetical order. + +* [`bench`](build_command.md) - a synonym for `stack build --bench` +* [`build`](build_command.md) - build packages +* [`clean`](clean_command.md) - delete build artefacts for the project packages +* [`config`](config_command.md) - access and modify Stack's configuration +* [`docker`](docker_command.md) - use Stack with Docker +* [`dot`](dot_command.md) - dependency visualization +* [`eval`](eval_command.md) - evaluate some Haskell code inline +* [`exec`](exec_command.md) - executate a command in the Stack environment +* [`haddock`](build_command.md) - a synonym for `stack build --haddock` +* [`hoogle`](hoogle_command.md) - run `hoogle` +* [`hpc`](hpc_command.md) - generate Haskell Program Coverage (HPC) code + coverage reports +* [`ghc`](ghc_command.md) - run `ghc` +* [`ghci`](ghci_command.md) - run GHCi, a REPL environment +* [`ide`](ide_command.md) - information for an integrated development + environment (IDE) +* [`init`](init_command.md) - initialise Stack's project-level YAML + configuration file for an existing project +* [`install`](build_command.md) - a synonym for `stack build --copy-bins` +* [`list`](list_command.md) - list packages on Hackage or in a snapshot +* [`ls`](ls_command.md) - list information about Stack +* [`new`](new_command.md) - create a new project with Stack +* [`path`](path_command.md) - information about locations used by Stack +* [`purge`](purge_command.md) - delete the Stack working directories +* [`query`](query_command.md) - information about the build +* [`repl`](ghci_command.md) - a synonym for `stack ghci` +* [`run`](run_command.md) - build and run an executable +* [`runghc`](runghc_command.md) - run `runghc` +* [`runhaskell`](runghc_command.md) - a synonym for `stack runghc` +* [`script`](script_command.md) - run a Haskell source file as a script +* [`sdist`](sdist_command.md) - create an archive file for a package, in a form + accepted by Hackage +* [`setup`](setup_command.md) - get GHC for a Stack project +* [`templates`](templates_command.md) - information about templates for use with + `stack new` +* [`test`](build_command.md) - a synonym for `stack build --test` +* [`uninstall`](uninstall_command.md) - information about how to uninstall Stack +* [`unpack`](unpack_command.md) - unpack one or more packages locally +* [`update`](update_command.md) - update the package index +* [`upgrade`](upgrade_command.md) - upgrade Stack +* [`upload`](upload_command.md) - upload a package to Hackage
+ doc/commands/init_command.md view
@@ -0,0 +1,42 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack init` command + +~~~text +stack init [DIR(S)] [--omit-packages] [--force] [--ignore-subdirs] +~~~ + +`stack init` initialises Stack's default project-level configuration file +(`stack.yaml`) for an existing project, based on the Cabal file or +`package.yaml` file for each of its packages. + +By default: + +* Stack searches for Cabal and `package.yaml` files in the current directory. + Specify one or more directories as arguments to cause Stack to search them; + +* Stack also searches for Cabal and `package.yaml` files in subdirectories. Pass + the flag `--ignore-subdirs` to ignore subdirectories; + +* Stack will not overwrite an existing `stack.yaml` file. Pass the flag + `--force` to allow overwriting; and + +* Stack will not initialise if there are conflicting or incompatable user + packages. Pass the flag `--omit-packages` to cause Stack to ignore such + matters while initialising. + +If a snapshot is specified at the command line, `stack init` will try to use it. +For further information, see the documentation for the +[`--snapshot`](../configure/global_flags.md#-snapshot-option) and +[`--resolver`](../configure/global_flags.md#-resolver-option) options. + +Otherwise, `stack init` will try to use the following Stackage snapshots in +order of preference, using the first that is compatable: the most recent LTS +Haskell, the most recent Stackage Nightly, and other LTS Haskell (most recent +first). + +!!! note + + If Cabal (the tool) has been used in the directory, consider commanding + `cabal clean` before applying `stack init`, in case Cabal has created any + unintended Cabal files.
+ doc/commands/install_command.md view
@@ -0,0 +1,30 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack install` command + +~~~text +stack install [TARGET] [--dry-run] [--pedantic] [--fast] [--ghc-options OPTIONS] + [--flag PACKAGE:[-]FLAG] [--dependencies-only | --only-snapshot | + --only-dependencies | --only-locals] [--file-watch | + --file-watch-poll] [--watch-all] [--exec COMMAND [ARGUMENT(S)]] + [--only-configure] [--trace] [--profile] [--no-strip] + [--[no-]library-profiling] [--[no-]executable-profiling] + [--[no-]library-stripping] [--[no-]executable-stripping] + [--[no-]haddock] [--haddock-arguments HADDOCK_ARGS] + [--[no-]open] [--[no-]haddock-deps] [--[no-]haddock-internal] + [--[no-]haddock-hyperlink-source] [--[no-]haddock-for-hackage] + [--[no-]copy-bins] [--[no-]copy-compiler-tool] [--[no-]prefetch] + [--[no-]keep-going] [--[no-]keep-tmp-files] [--[no-]force-dirty] + [--[no-]test] [--[no-]rerun-tests] + [--ta|--test-arguments TEST_ARGS] [--coverage] [--no-run-tests] + [--test-suite-timeout ARG] [--[no-]tests-allow-stdin] + [--[no-]bench] [--ba|--benchmark-arguments BENCH_ARGS] + [--no-run-benchmarks] [--[no-]reconfigure] + [--cabal-verbosity VERBOSITY | --[no-]cabal-verbose] + [--[no-]split-objs] [--skip ARG] [--[no-]interleaved-output] + [--ddump-dir ARG] +~~~ + +`stack install` is a synonym for `stack build --copybins`. For further +information, see the documentation for the [`stack build`](build_command.md) +command.
+ doc/commands/list_command.md view
@@ -0,0 +1,64 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack list` command + +[:octicons-tag-24: 2.7.1](https://github.com/commercialhaskell/stack/releases/tag/v2.7.1) + +~~~text +stack list [PACKAGE] +~~~ + +`stack list <package_name>` will send to the standard output stream the latest +version of the package from Hackage. If the package name cannot be found on +Hackage, even after updating the package index, suggestions (not necessarily +good ones) will be made about the intended package name. + +`stack --snapshot <snapshot> list <package_name>` will send to the standard +output stream the version of the package included in the specified snapshot +(either directly or indirectly, if a boot package of the compiler specified by +the snapshot). If the package name cannot be found in the snapshot, the command +will fail, identifying only the package(s) that did not appear in the snapshot. + +More than one package name can be specified. + +`stack --snapshot <snapshot> list` will send to the standard output stream a +list of all the packages included directly in the specified snapshot (that is, +excluding those included only indirectly as a boot package of the compiler +specified by the snapshot). + +For example: + +~~~text +stack list base unix Win32 acme-missiles pantry +base-4.20.0.1 +unix-2.8.5.1 +Win32-2.14.0.0 +acme-missiles-0.3 +pantry-0.10.0 + +stack list paltry +Could not find package paltry, updating +... +Package index cache populated +Error: [S-4926] + * Could not find package paltry on Hackage. Perhaps you meant one of: + pantry, pretty, pasty, xattr, alloy, para, pappy, alure, polar and + factory. + +stack --snapshot lts-22.28 list base unix Win32 acme-missiles pantry +Error: [S-4926] + * Package does not appear in snapshot (directly or indirectly): acme-missiles. + +stack --snapshot lts-22.28 list base unix Win32 pantry +base-4.18.2.1 +unix-2.8.4.0 +Win32-2.13.3.0 +pantry-0.9.3.2 + +stack --snapshot lts-22.28 list +AC-Angle-1.0 +ALUT-2.4.0.3 +... +zstd-0.1.3.0 +zxcvbn-hs-0.3.6 +~~~
+ doc/commands/ls_command.md view
@@ -0,0 +1,276 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack ls` commands + +~~~text +stack ls COMMAND + +Available commands: + dependencies View the dependencies + globals View global packages + snapshots View snapshots (local by default) + stack-colors View Stack's output styles + stack-colours View Stack's output styles (alias for 'stack-colors') + tools View Stack's installed tools +~~~ + +The `stack ls` commands list different types of information. Command `stack ls` +for the available commands. + +## The `stack ls dependencies` command + +Either + +~~~text +stack ls dependencies COMMAND + +Available commands: + cabal Print dependencies as exact Cabal constraints + json Print dependencies as JSON + text Print dependencies as text (default) + tree Print dependencies as tree +~~~ + +or + +~~~text +stack ls dependencies [--separator SEP] [--[no-]license] [--filter ITEM] + [--[no-]external] [--[no-]include-base] [--depth DEPTH] + [--prune PACKAGES] [TARGET] [--flag PACKAGE:[-]FLAG] + [--test] [--bench] [--global-hints] +~~~ + +`stack ls dependencies` lists all of the packages and versions used for a +project. All project packages are considered by default, but one or more targets +can be specified as an argument. For further information, see the +[target syntax](build_command.md#target-syntax) documentation. + +!!! note + + If the first target is one of `cabal`, `json`, `text` and `tree`, then a + subcommand must be specified. + +!!! info + + If a specified target is not a project package, then it will not contribute + packages to the command's output. + +Subcommands specify the format of the output, as follows: + +* `cabal` lists the packages in the format of exact Cabal constraints. + + ~~~text + stack ls dependencies cabal [--[no-]external] [--[no-]include-base] + [--depth DEPTH] [--prune PACKAGES] [TARGET] + [--flag PACKAGE:[-]FLAG] [--test] [--bench] + [--global-hints] + ~~~ + + For example (extract): + + ~~~text + constraints: + , Cabal ==3.6.3.0 + , Cabal-syntax ==3.6.0.0 + , Glob ==0.10.2 + ~~~ + +* `json` lists dependencies in JSON format (an array of objects). + + ~~~text + stack ls dependencies json [--[no-]external] [--[no-]include-base] + [--depth DEPTH] [--prune PACKAGES] [TARGET] + [--flag PACKAGE:[-]FLAG] [--test] [--bench] + [--global-hints] + ~~~ + + For example (extract): + + ~~~text + [{"dependencies":["base","bytestring"],"license":"BSD3","location":{"type":"hackage","url":"https://hackage.haskell.org/package/zlib-0.6.3.0"},"name":"zlib","version":"0.6.3.0"}, + ~~~ + + Each object has the following keys: + + ~~~json + name: zlib + version: 0.6.3.0 + location: + type: hackage + url: https://hackage.haskell.org/package/zlib-0.6.3.0 + licence: BSD3 + dependencies: + - base + - bytestring + ~~~ + +* `text` (the default) lists the packages, each on a separate line. + + ~~~text + stack ls dependencies text [--separator SEP] [--[no-]license] [--filter ITEM] + [--[no-]external] [--[no-]include-base] + [--depth DEPTH] [--prune PACKAGES] [TARGET] + [--flag PACKAGE:[-]FLAG] [--test] [--bench] + [--global-hints] + ~~~ + + For example (extract): + + ~~~text + Cabal 3.6.3.0 + Cabal-syntax 3.6.0.0 + Glob 0.10.2 + ~~~ + +* `tree` lists dependencies in the format of a tree. + + ~~~text + stack ls dependencies tree [--separator SEP] [--[no-]license] [--[no-]external] + [--[no-]include-base] [--depth DEPTH] + [--prune PACKAGES] [TARGET] [--flag PACKAGE:[-]FLAG] [--test] [--bench] [--global-hints] + ~~~ + + For example (extract): + + ~~~text + Packages + └─┬ stack 2.10.0 + ├─┬ Cabal 3.6.3.0 + │ ├─┬ Win32 2.12.0.1 + │ │ ├─┬ base 4.16.3.0 + │ │ │ ├─┬ ghc-bignum 1.2 + │ │ │ │ └─┬ ghc-prim 0.8.0 + │ │ │ │ └── rts 1.0.2 + │ │ │ ├─┬ ghc-prim 0.8.0 + ~~~ + +The `--separator` option, with the `text` or `tree` subcommand, specifies the +separator between the package name and its version. The default is a space +character. + +Set the `--license` flag, after the `text` or `tree` subcommand, to replace each +package's version with its licence. (Consistent with the Cabal package +description format specification, only the American English spelling (license) +is accepted.) + +The `--filter` option, with the `text` subcommand, specifies an item to be +filtered out from the results, if present. An item can be `$locals` (for all +project packages) or a package name. It can be specified multiple times. + +!!! note + + The special value `$locals` will need to be enclosed with single quotes to + distinguish it from a shell variable. + +Set the `--no-external` flag to exclude external dependencies. + +Set the `--no-include-base` flag to exclude dependencies on the `base` package. + +The `--depth` option limits the depth of dependency resolution. + +The `--prune <packages>` option prunes the specified packages and their +dependencies from the tree of packages used to generate the output, where +`<packages>` is a comma separated list of package names. + +The `--flag` option allows Cabal flags to be specified. + +Pass the `--test` flag to consider the dependencies of test suite components. + +Pass the `--bench` flag to consider the dependencies of benchmark components. + +Pass the `--global-hints` flag to use a hints file for global packages. The +command then does not require an installed GHC. + +## The `stack ls globals` command + +~~~text +stack ls globals [--[no-]global-hints] +~~~ + +`stack ls globals` will list all the global packages in alphabetical order. + +By default: + +* the global packages are those for the version of GHC specified by the snapshot + according to a hints file. Pass the flag `--no-global-hints` to use the global + package database of an installed GHC. + +!!! note + + For example, on Windows, `stack ls globals` will include a version of the + `Win32` and `unix` packages but `stack ls globals --no-global-hints` will + exclude the `unix` package - and vice versa on Unix-like operating systems. + +## The `stack ls snapshots` command + +~~~text +stack ls snapshots [COMMAND] [-l|--lts] [-n|--nightly] + +Available commands: + local View local snapshots + remote View remote snapshots +~~~ + +`stack ls snapshots` will list all the local snapshots by default. You can also +view the remote snapshots using `stack ls snapshots remote`. It also supports +options for viewing only lts (`-l`) and nightly (`-n`) snapshots. + +## The `stack ls stack-colors` command + +~~~text +stack ls stack-colors [--[no-]basic] [--[no-]sgr] [--[no-]example] +~~~ + +The British English spelling is also accepted (`stack ls stack-colours`). + +`stack ls stack-colors` will list all of Stack's output styles. A number of +different formats for the output are available, see +`stack ls stack-colors --help`. + +The default is a full report, with the equivalent SGR instructions and an +example of the applied style. The latter can be disabled with flags `--no-sgr` +and `--no-example`. + +The flag `--basic` specifies a more basic report, in the format that is accepted +by Stack's command line option `--stack-colors` and the +[`stack-colors`](../configure/yaml/non-project.md#stack-colors) non-project +specific configuration option. + +## The `stack ls tools` command + +~~~text +stack ls tools [--filter TOOL_NAME] +~~~ + +`stack ls tools` will list Stack's installed tools. On Unix-like operating +systems, they will be one or more versions of GHC. On Windows, they will include +MSYS2. For example, on Windows the command: + +~~~text +stack ls tools +~~~ + +yields output like: + +~~~text +ghc-9.4.1 +ghc-9.2.4 +ghc-9.0.2 +msys2-20210604 +~~~ + +The `--filter <tool_name>` option will filter the output by a tool name (e.g. +'ghc', 'ghc-git' or 'msys2'). The tool name is case sensitive. For example the +command: + +~~~text +stack ls tools --filter ghc +~~~ + +yields output like: + +~~~text +ghc-9.4.1 +ghc-9.2.4 +ghc-9.0.2 +~~~
+ doc/commands/new_command.md view
@@ -0,0 +1,138 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack new` command + +~~~text +stack new PACKAGE_NAME [--bare] [--[no-]init] [TEMPLATE_NAME] + [-p|--param KEY:VALUE] [DIR(S)] [--omit-packages] [--force] + [--ignore-subdirs] +~~~ + +`stack new` creates a new project using a project template. + +By default: + +* the project is created in a new directory named after the package. Pass the + `--bare` flag to create the project in the current directory; + +* the project is initialised for use with Stack. Pass the `--no-init` flag to + skip such initialisation; and + +* the project template is the one specified by the +[default-template](../configure/yaml/non-project.md#default-template) option. + +A package name acceptable to Cabal comprises an alphanumeric 'word'; or two or +more such words, with the words separated by a hyphen/minus character (`-`). A +word cannot be comprised only of the characters `0` to `9`. + +An alphanumeric character is one in one of the Unicode Letter categories +(Lu (uppercase), Ll (lowercase), Lt (titlecase), Lm (modifier), or Lo (other)) +or Number categories (Nd (decimal), Nl (letter), or No (other)). + +!!! note + + In the case of Hackage and acceptable package names, an alphanumeric + character is limited to one of `A` to `Z`, `a` to `z`, and `0` to `9`. + +!!! note + + The name of a project is not constrained to be an acceptable package name. A + single-package project can be renamed to differ from the name of its + package. + +The `--param <key>:<value>` option specifies a key-value pair to populate a key +in a template. The option can be specified multiple times. + +The arguments specifying directories and the `--ignore-subdirs`, `--force` and +`--omit-packages` flags are as for the [`stack init` command](init_command.md). +These arguments are ignored if the `--no-init` flag is passed. + +If a snapshot is specified at the command line and the project is initialised +for use with Stack, `stack new` will try to use it. For further information, see +the documentation for the +[`--snapshot`](../configre/global_flags.md#-snapshot-option) and +[`--resolver`](../configure/global_flags.md#-resolver-option) options. + +## Project templates + +A project template file can be located in a repository named `stack-templates` +on GitHub, GitLab or Bitbucket; at a URL; or on the local file system. + +Project template file names have the extension `.hsfiles`. The extension does +not need to be specified with `stack new`. + +A project template file `my-template.hsfiles` in a repository +`username/stack-templates` on GitHub, GitLab or Bitbucket can be specified +with `stack new` as: + +~~~test +<service>:username/my-template +~~~ + +where `<service>` is one of `github` for [GitHub](https://github.com/), +`gitlab` for [GitLab](https://gitlab.com), or `bitbucket` for +[Bitbucket](https://bitbucket.com). + +The default service is GitHub, the default username is `commercialhaskell` and +the default project template name is `new-template`. + +## Examples + +Create a project for package `my-project` in new directory `my-project` with the +default project template file and initialise it for use with Stack: + +~~~text +stack new my-project +~~~ + +Create a project for package `my-package` in the current directory with the +default project template file and initialise it for use with Stack: + +~~~text +stack new my-package --bare +~~~ + +Create a project with the `rio` project template at the default repository and +initialise it for use with Stack: + +~~~text +stack new my-project rio +~~~ + +Create a project with the `mysql` project template provided by the +`yesodweb/stack-templates` repository on GitHub and initialise it for use with +Stack: + +~~~text +stack new my-project yesodweb/mysql +~~~ + +Create a project with the `my-template` project template provided by the +`username/stack-templates` repository on Bitbucket and initialise it for use +with Stack: + +~~~text +stack new my-project bitbucket:username/my-template +~~~ + +Create a project with the `my-template.hsfiles` project template file at +`https://example.com` and initialise it for use with Stack: + +~~~text +stack new my-project https://example.com/my-template +~~~ + +Create a project with the local project template file +`<path_to_template>/my-template.hsfiles` and initialise it for use with Stack: + +~~~text +stack new my-project <path_to_template_file>/my-template +~~~ + +Create a project with the `simple` project template file at the default +repository (which does not use Hpack and a `package.yaml` file) and do not +initialise it for use with Stack (`stack init` could be used subsequently): + +~~~text +stack new my-project --no-init simple +~~~
+ doc/commands/path_command.md view
@@ -0,0 +1,49 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack path` command + +~~~text +stack path [--stack-root] [--global-config] [--programs] [--local-bin] + [--project-root] [--config-location] [--bin-path] [--compiler-exe] + [--compiler-bin] [--compiler-tools-bin] [--extra-include-dirs] + [--extra-library-dirs] [--snapshot-pkg-db] [--local-pkg-db] + [--global-pkg-db] [--ghc-package-path] [--snapshot-install-root] + [--local-install-root] [--snapshot-doc-root] [--local-doc-root] + [--local-hoogle-root] [--dist-dir] [--local-hpc-root] +~~~ + +`stack path` provides information about files and locations used by Stack. + +Pass the following flags for information about specific files or locations: + +|Flag |File or location | +|-----------------------|------------------------------------------------------| +|--bin-path |The PATH in the Stack environment. | +|--compiler-bin |The directory containing the GHC executable. | +|--compiler-exe |The GHC executable. | +|--compiler-tools-bin |The directory containing binaries specific to a particular compiler.| +|--config-location |Stack's project-level configuration file (`stack.yaml`, by default).| +|--dist-dir |The dist work directory, relative to the package directory.| +|--extra-include-dirs |Extra include directories. | +|--extra-library-dirs |Extra library directories. | +|--ghc-package-path |The `GHC_PACKAGE_PATH` environment variable. | +|--global-config |Stack's user-specific global configuration file (`config.yaml`).| +|--global-pkg-db |The global package database. | +|--local-bin |The directory in which Stack installs executables. | +|--local-doc-root |The root directory for local project documentation. | +|--local-hoogle-root |The root directory for local project documentation. | +|--local-hpc-root |The root directory for .tix files and HPC reports. | +|--local-install-root |The root directory for local project installation. | +|--local-pkg-db |The local package database. | +|--programs |The root directory for GHC and other Stack-supplied tools.| +|--project-root |The project root directory.| +|--snapshot-doc-root |The root directory for snapshot documentation. | +|--snapshot-install-root|The root directory for snapshot installation. | +|--snapshot-pkg-db |The snapshot package database. | +|--stack-root |The Stack root. | + +The command also accepts flags and options of the +[`stack build`](build_command.md#flags-affecting-ghcs-behaviour) command that +affect the location of the local project installation directory, such as +`--profile` and `--no-strip`. For further information, see the documentation of +the [project Stack work directory](../topics/stack_work.md).
+ doc/commands/purge_command.md view
@@ -0,0 +1,10 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack purge` command + +~~~text +stack purge +~~~ + +`stack purge` has the same effect as, and is provided as a shorthand for, +[`stack clean --full`](clean_command.md).
+ doc/commands/query_command.md view
@@ -0,0 +1,44 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack query` command + +:octicons-beaker-24: Experimental + +[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) + +~~~text +stack query [SELECTOR...] +~~~ + +`stack query` outputs certain build information. For example, for a +multi-package project `multi` specifying snapshot `lts-19.25` (GHC 9.0.2) and +with two project packages, `my-package-A` (version 0.1.0.0) and `my-package-B` +(version 0.2.0.0), command `stack query` outputs: + +~~~text +compiler: + actual: ghc-9.0.2 + wanted: ghc-9.0.2 +locals: + my-package-A: + path: <absolute_path_to>\multi\my-package-A\ + version: 0.1.0.0 + my-package-B: + path: <absolute_path_to>\multi\my-package-B\ + version: 0.2.0.0 +~~~ + +The component parts of the information can be specified using 'selectors' with +the command. In the example above the selectors include `compiler`, +`compiler actual`, `locals`, `locals my-package-A`, and +`locals my-package-A version`. For example, commanding: + +~~~text +stack query locals my-package-B path +~~~ + +results in output: + +~~~text +<absolute_path_to>\multi\my-package-B\ +~~~
+ doc/commands/repl_command.md view
@@ -0,0 +1,14 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack repl` command + +~~~text +stack repl [TARGET/FILE] [--pedantic] [--ghci-options OPTIONS] + [--ghc-options OPTIONS] [--flag PACKAGE:[-]FLAG] [--with-ghc GHC] + [--[no-]load] [--package PACKAGE] [--main-is TARGET] + [--load-local-deps] [--[no-]package-hiding] [--only-main] [--trace] + [--profile] [--no-strip] [--[no-]test] [--[no-]bench] +~~~ + +The `stack repl` command is equivalent to the `stack ghci` command. For further +information, see the [`stack ghci`](ghci_command.md) documentation.
+ doc/commands/run_command.md view
@@ -0,0 +1,46 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack run` command + +~~~text +stack run [-- ARGUMENT(S) (e.g. stack run -- file.txt)] + [--[no-]ghc-package-path] [--[no-]stack-exe] + [--package PACKAGE] [--rts-options RTSFLAG] [--cwd DIR] +~~~ + +`stack run` builds a project executable and runs it. If the command has a first +argument and it is recognised as the name of an executable component of a +project package then that is built. Otherwise, the project's first executable is +built. If the project has no executables Stack reports no executables found as +an error. + +!!! note + + To identify a project's first executable, and search for the name of an + executable component, Stack lists the executable components, in order, for + each package, listed in order. For example: + + `packageA:a-exe` < `packageA:b-exe` < `packageB:a-exe` < `packageB:b-exe` + +Everything after `--` on the command line is interpreted as a command line +argument to be passed to what is run, other than a first argument recognised as +the name of an executable component of a project package. + +By default: + +* the `GHC_PACKAGE_PATH` environment variable is set for the subprocess. Pass + the `--no-ghc-package-path` flag to not set the variable; and + +* the `STACK_EXE` environment variable is set with the path to Stack. Pass the + `--no-stack-exe` flag to not set the variable. + +The `--cwd` option can be used to set the working directory before the +executable is run. + +The `--package` option (which can be specified multiple times) can be used to +add a package name to build targets. + +The `--rts-options` option (which can be specified multiple times) can be used +to pass a list of GHC's +[runtime system (RTS) options](https://downloads.haskell.org/~ghc/latest/docs/users_guide/runtime_control.html#) +to the executable when it is run. (The `+RTS` and `-RTS` must not be included.)
+ doc/commands/runghc_command.md view
@@ -0,0 +1,22 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack runghc` and `stack runhaskell` commands + +~~~text +stack runghc [-- ARGUMENT(S) (e.g. stack runghc -- X.hs)] + [--[no-]ghc-package-path] [--[no-]stack-exe] [--package PACKAGE] + [--rts-options RTSFLAG] [--cwd DIR] +~~~ + +`stack runhaskell` has the same effect as `stack runghc`. `stack runghc` has the +same effect as, and is provided as a shorthand for, +[`stack exec runghc`](exec_command.md), with the exception of the `--package` +option. + +Pass the option `--package <package(s)>` to add the initial GHC argument +`-package-id=<unit_id>`, where `<unit_id>` is the unit ID of the specified +package in the installed package database. The option can be a list of package +names or package identifiers separated by spaces. The option can also be +specified multiple times. The approach taken to these packages is the same as if +they were specified as targets to +[`stack build`](build_command.md#target-syntax).
+ doc/commands/runhaskell_command.md view
@@ -0,0 +1,12 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack runhaskell` command + +~~~text +stack runhaskell [-- ARGUMENT(S) (e.g. stack runghc -- X.hs)] + [--[no-]ghc-package-path] [--[no-]stack-exe] + [--package PACKAGE] [--rts-options RTSFLAG] [--cwd DIR] +~~~ + +The `stack runhaskell` command is equivalent to the `stack runghc` command. For +further information, see the [`stack runghc`](runghc_command.md) documentation.
+ doc/commands/script_command.md view
@@ -0,0 +1,329 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack script` command + +~~~text +stack script [--package PACKAGE] FILE + [-- ARGUMENT(S) (e.g. stack script X.hs -- argument(s) to program).] + [--compile | --optimize] [--[no-]use-root] [--ghc-options OPTIONS] + [--extra-dep PACKAGE-VERSION] [--no-run] +~~~ + +The `stack script` command either runs a specified Haskell source file (using +GHC's `runghc`) or, optionally, compiles such a file (using GHC) and, by +default, runs it. + +## Global configuration files + +Non-project level configuration options in global configuration files +(`config.yaml`) are not ignored by the `stack script` command. + +!!! info + + Non-project level configuration options may be useful if + [`allow-newer`](../configure/yaml/non-project.md#allow-newer) and/or + [`allow-newer-deps`](../configure/yaml/non-project.md#allow-newer-deps) are + required. + +## Project-level configuration file + +The `stack script` command ignores any project-level configuration file +(`stack.yaml`, by default), including in the `global-project` directory in the +Stack root. + +!!! info + + The `stack script` command can be contrasted with the + [`stack ghc`](ghc_command.md) and [`stack runghc`](runghc_command.md) + commands, which do not ignore any project-level configuration file. + +## GHC + +The `stack script` command behaves as if the +[`--install-ghc`](../configure/global_flags.md#--no-install-ghc-flag) flag had +been passed at the command line. + +## Snapshot and extra-deps + +A snapshot must be specified on the command line, using the `--snapshot` option. +For example: + +~~~text +stack script --snapshot lts-22.28 MyScript.hs +~~~ + +A package version can be added to the snapshot on the command line with the +`--extra-dep` option (which can be specified multiple times). + +GHC boot packages that have been 'replaced' (see further below) can be specified +as an `--extra-dep`. + +## Required packages + +The names of required packages can be either deduced or specified. + +The `base` package associated with the version of GHC specified by the snapshot +is always available. + +If no packages are specified, all the required packages that are in the snapshot +or are a GHC boot package (packages that come with GHC and are included in GHC's +global package database), will be deduced by reference to the `import` +statements in the source file. In that regard, Stack assumes that: + +* a line that begins `import` is an `import` statement; +* `import` may be followed by `qualified` on the same line; +* consistent with GHC's + [`PackageImports`](https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/package_qualified_imports.html) + language extension, that if `import` or `import qualified` is followed by + `"<name>"` on the same line, that `<name>` is the name of a required package; +* otherwise, `import` or `import qualified` is followed by the module name on + the same line. Stack will not deduce the names of hidden packages from + module names or the names of blacklisted packages. + +!!! note + + The first time that Stack deduces package names from module names can take + some time. Use the `--verbose` option to understand Stack's progress. + +!!! info + + Certain packages are blacklisted because they expose one or more modules + with names that are the same as modules exposed by more popular packages. + The blacklisted packages are `Glob`, `HTF`, `async-dejafu`, + `binary-ieee754`, `cipher-aes`, `cipher-blowfish`, `cipher-camellia`, + `cipher-des`, `cipher-rc4`, `control-monad-free`, `courier`, `crypto-api`, + `crypto-cipher-types`, `crypto-numbers`, `crypto-pubkey`, `crypto-random`, + `cryptohash`, `cryptohash-conduit`, `cryptohash-md5`, `cryptohash-sha1`, + `cryptohash-sha256`, `fay-base`, `gl`, `gtk3`, `hashmap`, `hledger-web`, + `hxt-unicode`, `kawhi`, `language-c`, `log`, `monad-extras`, `monads-tf`, + `nanospec`, `newtype-generics`, `objective`, `plot-gtk3`, `prompt`, + `regex-compat-tdfa`, `regex-pcre-builtin`, `rerebase`, `svg-tree` and `zip`. + +Alternatively, each required package can be specified by name on the command +line with the `--package` option (which can be specified multiple times). A +single `--package` option can also refer to a list of package names, separated +by a space or comma character. If the package is not in the snapshot, the most +recent version in the package index (e.g. Hackage) will be obtained. + +If a required package is a GHC boot package, the behaviour can be complex. If +the boot package has not been 'replaced', then it will be used in Stack's build +plan. However, if the boot package has been 'replaced', the latest version of +that package in the package index will be used in Stack's build plan, which may +differ from the version provided by the version of GHC specified by the +snapshot. A boot package will be treated as 'replaced' if the package is +included directly in the Stackage snapshot or it depends on a package included +directly in the snapshot. Stackage snapshots do not include directly most boot +packages but some snapshots may include directly some boot packages. In +particular, some snapshots include directly `Win32` (which is a boot package on +Windows) while others do not. + +!!! warning + + GHC has the concept of 'installed packages' (which differ from 'Cabal + packages') in package databases. An installed package has a name. An + installed package corresponding to the main (unnamed) library of a Cabal + package has the same name as the Cabal package. An installed package + corresponding to a sub-library of a Cabal package has a 'munged' name that + reflects the name of the Cabal package and the name of the sub-library. An + installed package corresponding to a sub-library also has a `package-name`, + which is the name of the Cabal package. + + The `--package` option of `stack script` makes use of GHC's `-package` + option to expose an installed package. Unfortunately, the latter treats + `package-name` (if it exists) as if it were also the name of the installed + package. That means, for a Cabal package with one or more sub-libraries, the + GHC option `-package=<name>` cannot distinguish between (a) the installed + package `<name>` corresponding to the main library of Cabal package `<name>` + and (b) an installed package corresponding to a sub-library of that Cabal + package. The installed package that GHC picks to expose is indeterminate. + This can cause GHC to pick the wrong installed package and to report that it + cannot load a module because it is a member of a hidden package. + +## Compilation + +The source file can be compiled by passing either the `--compile` flag (no +optimization) or the `--optimize` flag (compilation with optimization). If the +file is compiled, passing the `--no-run` flag will mean the compiled code is not +run. + +By default, all the compilation outputs (including the executable) are written +to the directory of the source file. Pass the `--use-root` flag to write such +outputs to a script-specific location in the `scripts` directory of the Stack +root. The location reflects the absolute path to the source file, but ignoring +the drive. This can avoid clutter in the source file directory. + +## GHC options + +Additional options can be passed to GHC using the `--ghc-options` option. + +## Script arguments + +Everything after `--` on the command line is interpreted as a command line +argument to be passed to what is run. + +## Examples + +### Example 1 + +A Haskell source file `MyScript.hs` at location +`<drive>Users/jane/my-project` (where `<drive>` could be `/` on Unix-like +operating systems or `C:/` or similar on Windows): + +~~~haskell +module Main (main) where + +import Data.List (intercalate) +import System.Environment (getArgs) + +import Acme.Missiles (launchMissiles) + +main :: IO () +main = do + advices <- getArgs + launchMissiles + putStrLn $ intercalate "\n" advices +~~~ + +can be compiled and run, with arguments, with: + +~~~text +stack --snapshot lts-22.28 script --package acme-missiles --compile MyScript.hs -- "Don't panic!" "Duck and cover!" +~~~ + +`acme-missiles-0.3` (the most recent version in the package index) will be used. + +All the compilation outputs (like `Main.hi`, `Main.o`, and the executable +`MyScript`) will be written to the `my-project` directory. + +If compiled and run with the additional flag `--use-root`, all the compilation +outputs will be written to a directory named `MyScript.hs` at +`Users/jane/my-project/` in the `scripts` directory of the Stack root. + +### Example 2 + +As for Example 1, but `acme-missiles-0.2` is specified by adding it to the +snapshot as an extra-dep. The `stack script` command is specified using Stack's +[script interpreter](../topics/scripts.md). + +~~~haskell +{- stack script + -- snapshot lts-22.28 + -- extra-dep acme-missiles-0.2 + -- package acme-missiles +-} +module Main (main) where + +import Data.List (intercalate) +import System.Environment (getArgs) + +import Acme.Missiles (launchMissiles) + +main :: IO () +main = do + advices <- getArgs + launchMissiles + putStrLn $ intercalate "\n" advices +~~~ + +~~~text +stack MyScript.hs "Don't panic!" "Duck and cover!" +~~~ + +### Example 3 + +Stackage snapshot LTS Haskell 20.25 includes GHC boot package `Win32` directly. +On Windows only, GHC boot packages `Cabal`, `directory`, `process` and `time` +all depend on `Win32` and, consequently, are all treated as 'replaced'. +Consequently, for example, Stack will: + +* on Windows, try to construct a build plan based on the latest version of + `Cabal` in the package index; and +* on non-Windows, use the boot package in the build plan (because `Cabal` is not + 'replaced'). + +Consider also the following script extract, based on snapshot Stackage + LTS Haskell 20.25, where considerations on Windows differ from non-Windows. The +`stack script` command is specified using Stack's +[script interpreter](../topics/scripts.md). + +=== "Windows" + + ~~~haskell + {- stack script + --snapshot lts-20.25 + --extra-dep acme-missiles-0.3 + --extra-dep directory-1.3.6.2 + --extra-dep process-1.6.16.0 + --extra-dep time-1.11.1.1 + -} + + import Acme.Missiles -- from acme-missiles + import Data.Time.Clock.System -- from time + import System.Time.Extra -- from extra + + ... + ~~~ + + `acme-missiles` is not in the snapshot and so needs to be specified as an + extra-dep. + + Stack can deduce that the module imports imply that the required packages + are `acme-missiles`, `time` and `extra` (which is in the snapshot). + + `extra` depends on `directory` and `process`. If `directory` and `process` + are not specified as extra-deps, Stack will complain that they have been + 'pruned'. + + `directory-1.3.6.2` depends on `time < 1.12`. If `time` is not specified as + an extra-dep, Stack will try to construct a build plan based on the latest + version in the package index (which will fail, as the latest version is + `>= 1.12`) + +=== "Unix-like" + + ~~~haskell + {- stack script + --snapshot lts-20.25 + --extra-dep acme-missiles-0.3 + -} + + import Acme.Missiles -- from acme-missiles + import Data.Time.Clock.System -- from time + import System.Time.Extra -- from extra + + ... + ~~~ + + `acme-missiles` is not in the snapshot and so needs to be specified as an + extra-dep. + + Stack can deduce that the module imports imply that the required packages + are `acme-missiles`, `time` and `extra` (which is in the snapshot). + + All the other dependencies required are either GHC boot packages (which have + not been 'replaced') or in the snapshot. + +### Example 4 + +A Haskell source file `MyScript.hs`, as follows: + +~~~haskell +{- stack script + --snapshot lts-22.28 +-} + +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE PackageImports #-} + +module Main (main) where + +import "text" Data.Text (Text (..), unpack) + +main :: IO () +main = putStrLn $ unpack "This is text." +~~~ + +As module `Data.Text` is exposed by a number of packages that are included, +directly or indirectly, in the specified snapshot (`incipit-base`, +`incipit-core`, `relude` and `text`), `PackageImports` and `"text"` are required +to specify which module is being imported.
+ doc/commands/sdist_command.md view
@@ -0,0 +1,43 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack sdist` command + +~~~text +stack sdist [DIR] [--pvp-bounds PVP-BOUNDS] [--ignore-check] + [--[no-]test-tarball] [--tar-dir ARG] +~~~ + +Hackage only accepts packages for uploading in a standard form, a compressed +archive ('tarball') in the format produced by Cabal's `sdist` action. + +`stack sdist` generates a file for your package, in the format accepted by +Hackage for uploads. The command will report the location of the generated file. + +## `--ignore-check` flag + +Pass the flag to disable checks of the package for common mistakes. By default, +the command will check the package for common mistakes. + +## `--pvp-bounds` option + +The `--pvp-bounds <pvp_bounds_mode>` option determines whether and, if so, how +PVP version bounds should be added to the Cabal file of the package. The +available modes for basic use are: `none`, `lower`, `upper`, and `both`. The +available modes for use with Cabal file revisions are `lower-revision`, +`upper-revision` and `both-revision`. + +For futher information, see the +[`pvp-bounds`](../configure/yaml/non-project.md#pvp-bounds) non-project specific +configuration option documentation. + +## `--tar-dir` option + +The `--tar-dir <path_to_directory>` option determines whether the package +archive should be copied to the specified directory. + +## `--[no-]test-tarball` flag + +Default: Disabled + +Set the flag to cause Stack to test the resulting package archive, by attempting +to build it.
+ doc/commands/setup_command.md view
@@ -0,0 +1,95 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack setup` command + +~~~text +stack setup [GHC_VERSION] [--[no-]reinstall] [--ghc-bindist URL] + [--ghcjs-boot-options GHCJS_BOOT] [--[no-]ghcjs-boot-clean] +~~~ + +`stack setup` attempts to install a version of GHC. + +By default: + +* the version of GHC is the one required by the project. Specify the version of + GHC as an argument to attempt to install a different version of GHC. For + example `stack setup 9.6.6` will attempt to install GHC 9.6.6; and + +* an attempt to install is made only if the version of GHC is not already + available to Stack. Pass the flag `--reinstall` (disabled by default) to + attempt to install the version of GHC regardless of whether it is already + available to Stack. + +Pass the option `--ghc-bindist <url>` to specify the URL of the GHC to be +downloaded and installed. This option requires the use of the `--ghc-variant` +option specifying a custom GHC variant. For further information about the +`--ghc-variant` option, see the +[`ghc-variant`](../configure/yaml/non-project.md#ghc-variant) non-project +specific configuration option documentation. + +If Stack is configured not to install GHC (`install-ghc: false` or passing the +`--no-install-ghc` flag) then `stack setup` will warn that the flag and the +command are inconsistent and take no action. + +=== "Linux" + + A particular binary distribution of GHC will depend on certain libraries, + which need to be available. + + There are many different Linux distributions and different versions of a + particular Linux distribution. One Linux distribution/version may make + available different libraries to another Linux distribution/version. + + In attempting to identify the particular binary distribution of GHC that is + required on Linux, Stack will refer to the presence or absence of certain + libraries or the versions of those libraries. + + For example, Stack 3.1.1 considers: + + * If `libc.musl-x86_64.so.1` is present. This file is provided by the + [musl libc](https://musl.libc.org/). + + [:octicons-tag-24: 2.13.1](https://github.com/commercialhaskell/stack/releases/tag/v2.13.1) + + * The version of `libc6` (if musl libc is not applicable), the + [GNU C Library](https://www.gnu.org/software/libc/) (glibc), that is + present. The GNU C Library is designed to be backwards compatible. + + [:octicons-tag-24: 2.11.1](https://github.com/commercialhaskell/stack/releases/tag/v2.11.1) + + * If `libgmp.so.3` or `libgmp.so.10` is present. These files are provided + by different versions of the + [GNU Multiple Precision Arithmetic Library](https://gmplib.org/). + + * If `libncursesw.so.6` is present. This file is provided by a shared + library for terminal handling with wide character support. + + * If `libtinfo.so.5` or `libtinfo.so.6` is present. These files are + provided by different versions of a shared low-level terminfo library + for terminal handling. + + Stack 3.1.1 uses `ghc-build`: + + * `musl` to indicate `libc.musl-x86_64.so.1` is present and Stack should use + the GHC binary distribution for Alpine Linux. + * `tinfo6` to indicate `libgmp.so.10` and `libtinfo.so.6` are present and + `libc6` is compatible with `libc6` 2.32. + * `tinfo6-libc6-pre232` to indicate `libgmp.so.10` and `libtinfo.so.6` are + present and `libc6` is not compatible with `libc6` 2.32. + * `ncurses6` to indicate `libgmp.so.10` and `libncursesw.so.6` are present + * `gmp4` to indicate `libgmp.so.3` is present + + By default, Stack associates: + + * the `tinfo6` build with the 'Fedora 33' binary distribution of GHC 9.4.1 + to 9.4.3 and 9.6.1 and later. Those binary distributions require versions + of `libc6` that are compatible with `libc6` 2.32; + + * the `tinfo6-libc6-pre232` build with the 'Debian 10' binary distribution + of GHC 9.4.1 to 9.4.3 and the 'Rocky 8' binary distribution of GHC 9.6.1 + and later. Those binary distributions require versions of `libc6` that are + compatible with `libc6` 2.28; and + + * the `tinfo6` and `tinfo6-libc6-pre232` builds with the 'Fedora 27' binary + distribution of GHC 9.4.4 to 9.4.8. Those binary distributions require + versions of `libc6` that are compatible with `libc6` 2.26.
+ doc/commands/templates_command.md view
@@ -0,0 +1,34 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack templates` command + +~~~text +stack templates +~~~ + +`stack templates` provides information to the standard output stream about +project templates used with the [`stack new` command](new_command.md). + +Project templates are specified in `.hsfiles` files. The format of those files +is documented at the +[`commercialhaskell/stack-templates`](https://github.com/commercialhaskell/stack-templates#project-template-format) +repository on GitHub. + +Any GitHub, GitLab or Bitbucket repository named `stack-templates` can provide +project template files. For example, a template file +`username/stack-templates/my-template.hsfiles` on GitHub can be identified as +`username/my-template` when using `stack new`. The relevant service can be +specified by a prefix: `github:` for [GitHub](https://github.com/) (the default +service), `gitlab:` for [GitLab](https://gitlab.com), or `bitbucket:` for +[Bitbucket](https://bitbucket.com). + +[`commercialhaskell/stack-templates`](https://github.com/commercialhaskell/stack-templates#project-template-format) +on GitHub is the default repository for project templates. Its username +(`commercialhaskell`) does not need to be specified when using `stack new`. + +The project template that `stack new` uses by default is named `new-template` +and provided at the default repository. + +The default repository provides 24 other project templates. Its Wiki provides +a description of some of those templates and information about the location of +other templates.
+ doc/commands/test_command.md view
@@ -0,0 +1,28 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack test` command + +~~~text +stack test [TARGET] [--dry-run] [--pedantic] [--fast] [--ghc-options OPTIONS] + [--flag PACKAGE:[-]FLAG] [--dependencies-only | --only-snapshot | + --only-dependencies | --only-locals] [--file-watch | + --file-watch-poll] [--watch-all] [--exec COMMAND [ARGUMENT(S)]] + [--only-configure] [--trace] [--profile] [--no-strip] + [--[no-]library-profiling] [--[no-]executable-profiling] + [--[no-]library-stripping] [--[no-]executable-stripping] + [--[no-]haddock] [--haddock-arguments HADDOCK_ARGS] + [--[no-]open] [--[no-]haddock-deps] [--[no-]haddock-internal] + [--[no-]haddock-hyperlink-source] [--[no-]haddock-for-hackage] + [--[no-]copy-bins] [--[no-]copy-compiler-tool] [--[no-]prefetch] + [--[no-]keep-going] [--[no-]keep-tmp-files] [--[no-]force-dirty] + [--[no-]test] [--[no-]rerun-tests] [--ta|--test-arguments TEST_ARGS] + [--coverage] [--no-run-tests] [--test-suite-timeout ARG] + [--[no-]tests-allow-stdin] [--[no-]bench] + [--ba|--benchmark-arguments BENCH_ARGS] [--no-run-benchmarks] + [--[no-]reconfigure] [--cabal-verbosity VERBOSITY | + --[no-]cabal-verbose] [--[no-]split-objs] [--skip ARG] + [--[no-]interleaved-output] [--ddump-dir ARG] +~~~ + +`stack test` is a synonym for `stack build --test`. For further information, +see the documentation for the [`stack build`](build_command.md) command.
+ doc/commands/uninstall_command.md view
@@ -0,0 +1,11 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack uninstall` command + +~~~text +stack uninstall +~~~ + +`stack uninstall` provides information to the standard output stream about how +to uninstall Stack or a Stack-supplied tool (such as GHC or, on Windows, MSYS2). +It does not itself uninstall Stack or a Stack-supplied tool.
+ doc/commands/unpack_command.md view
@@ -0,0 +1,51 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack unpack` command + +~~~text +stack unpack TARGET [--candidate] [--to DIR] +~~~ + +`stack unpack` downloads an archive file for one or more specified target +packages from the package index (e.g. Hackage), or one or more specified target +package candidates, and unpacks each archive into a subdirectory named after the +package version. + +In the case of packages from the package index, a target can be a package +name only. In that case, by default: + +* if Stack's `--snapshot` option is not specified, the download is for the + most recent version of the package in the package index. Stack will first + seek to update the index; and + +* if Stack's `--snapshot` option is specified, the download is for the version + of the package included directly in the specified snapshot. + +!!! note + + Stackage snapshots do not include directly most GHC boot packages (packages + that come with GHC and are included in GHC's global package database) but + some snapshots may include directly some boot packages. In particular, some + snapshots include directly `Win32` (which is a boot package on Windows) + while others do not. + +Otherwise, a target should specify a package name and version (for example, +`acme-missiles-0.3`). In the case of package versions from the package index, +optionally, a revision in the package index can be specified by appending +`@rev:<number>` or `@sha256:<sha>` (for example, `acme-missiles-0.3@rev:0`). + +By default: + +* the download is from the package index. Pass the flag `--candidate` to + specify package candidates; and + + !!! note + + Stack assumes that a package candidate archive is a `.tar.gz` file named + after the package version and located at endpoint + `package\<package_version>\candidate\`. This is true of Hackage. + +* the target is unpacked into a subdirectory of the current directory. Pass + the option `--to <directory>` to specify an alternative destination + directory to the current directory. The destination directory can be an + absolute one or relative to the current directory.
+ doc/commands/update_command.md view
@@ -0,0 +1,12 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack update` command + +~~~text +stack update +~~~ + +Generally, Stack automatically updates the package index when necessary. + +`stack update` will download the most recent set of packages from your package +indices (e.g. Hackage).
+ doc/commands/upgrade_command.md view
@@ -0,0 +1,103 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack upgrade` command + +Either: + +~~~text +stack upgrade [--binary-only] [--binary-platform ARG] [--force-download] + [--[no-]only-local-bin] [--binary-version ARG] [--github-org ARG] + [--github-repo ARG] +~~~ + +or: + +~~~text +stack upgrade [--source-only] [--git] [--git-repo ARG] [--git-branch ARG] +~~~ + +`stack upgrade` will get a new version of Stack. It can also get a version +before the current version (downgrade). + +!!! warning + + If you use GHCup to install Stack, use only GHCup to upgrade Stack. + +By default: + +* the new version will be from an existing binary distribution. Pass the + `--source-only` flag to specify compiling from source code. The + `--binary-only` and `--source-only` flags are alternatives; + +* the new version will not overwrite the existing version unless it is newer. + Pass the `--force-download` flag to force a download; + +* when an existing binary distribution is applicable, it will be put in Stack's + local binary directory (see `stack path --local-bin`) and named `stack` + (replacing any existing executable named `stack` there); + +* if the current running Stack executable is named `stack` (or, on Windows, + `stack.exe`) (this is case insensitive), an existing binary distribution will + replace it. If the executable is located outside of Stack's local binary + directory, pass the `--only-local-bin` flag to skip that step; + +* if the current running Stack executable is named other than `stack` (and, on + Windows, `stack.exe`), an existing binary distribution will only be put in + Stack's local binary directory and named `stack`. Pass the + `--no-only-local-bin` flag to replace also the current running executable; + +* the new version will be the latest available. Pass the + `--binary-version <version>` option to specify the version (this implies + `--force-download`); + +* the binary distribution will be sought from the GitHub organisation/user + `commercialhaskell`. Pass the `--github-org <user>` option to specify a + different GitHub user; + +* the binary distribution will be sought from the GitHub repository `stack`. + Pass the `--github-repo <repository>` option to specify a different + repository; and + +* the binary distribution will be sought for the current platform. Pass the + `--binary-platform <platform>` option to specify a different platform + (`<operating_system>-<architecture>-<suffix>`). + +When compiling from source code, by default: + +* Stack will obtain the source code for the most recent version in the package + index (eg Hackage). Pass the flag `--git` to specify the most recent version + from the `master` branch of Stack's repository (pass the option + `--git-branch <branch>` to specify a different branch and the option + `--git-repo <repo_url>` to specify a different repository). + +!!! note + + An earlier version of Stack could be inconsistent with some of the current + contents of the Stack root. For further information about the contents of + the Stack root and configuring its location, see the documentation about the + [Stack root](../topics/stack_root.md). + +## Examples + +* `stack upgrade` seeks an upgrade to the latest version of Stack available as a + binary distribution for the platform, if newer. + +* `stack upgrade --force-download` seeks an upgrade to the latest version of + Stack available as a binary distribution for the platform, even if not newer. + +* If the Stack executable is named `my-stack`, `my-stack upgrade` seeks only to + put the latest version of Stack available as a binary distribution for the + platform, if newer, in Stack's local binary directory and name it `stack`. + `my-stack upgrade --no-only-local-bin` seeks also to upgrade `my-stack` to the + latest version of Stack available. + +* `stack upgrade --binary-version 2.15.1` seeks an upgrade to Stack 2.15.1 if + available as a binary distribution for the platform, even if not newer. + +* `stack upgrade --source-only` seeks an upgrade by building Stack with + Stack from the latest version of the source code in the package index + (i.e. Hackage). + +* `stack upgrade --source-only --git` seeks an upgrade by building Stack with + Stack from the latest version of the source code in the `master` branch of + Stack's repository.
+ doc/commands/upload_command.md view
@@ -0,0 +1,135 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# The `stack upload` command + +~~~text +stack upload [ITEM] [-d|--documentation] [--pvp-bounds PVP-BOUNDS] + [--ignore-check] [--[no-]test-tarball] [--tar-dir ARG] + [--candidate] [--[no-]save-hackage-creds] [--setup-info-yaml URL] + [--snapshot-location-base URL] +~~~ + +By default: + +* the command uploads one or more packages. Pass the flag `--documentation` + (`-d` for short) to upload documentation for one or more packages; + +* the upload is a package to be published or documentation for a published + package. Pass the flag `--candidate` to upload a + [package candidate](http://hackage.haskell.org/upload#candidates) or + documentation for a package candidate; and + +* the command prompts to save the user's Hackage username and password in a + local file. Pass the flag `--no-save-hackage-creds` to avoid the prompt. + +At least one `ITEM` must be specified. For example, if the current working +directory is a package directory: + +~~~text +stack upload . +~~~ + +## Upload one or more packages + +Hackage accepts packages for uploading in a standard form, a compressed archive +('tarball') in the format produced by Cabal's `sdist` action. + +If `ITEM` is a relative path to an sdist tarball, `stack upload` uploads the +package to Hackage. + +If `ITEM` is a relative path to a package directory, `stack upload` generates a +file for your package, in the format accepted by Hackage for uploads, and +uploads the package to Hackage. + +By default: + +* the command will check each package for common mistakes. Pass the flag + `--ignore-check` to disable such checks; + +* Stack will not test the resulting package archive. Pass the flag + `--test-tarball` to cause Stack to test each resulting package archive, by + attempting to build it. + +The `--pvp-bounds <pvp_bounds_mode>` option determines whether and, if so, how +PVP version bounds should be added to the Cabal file of the package. The +available modes for basic use are: `none`, `lower`, `upper`, and `both`. The +available modes for use with Cabal file revisions are `lower-revision`, +`upper-revision` and `both-revision`. + +For futher information, see the +[`pvp-bounds`](../configure/yaml/non-project.md#pvp-bounds) non-project +specific configuration option documentation. + +The `--tar-dir <path_to_directory>` option determines whether the package +archive should be copied to the specified directory. + +## Upload documentation for a package + +:octicons-beaker-24: Experimental + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +Hackage accepts documentation for a package for uploading in a standard form and +in a compressed archive ('tarball') in the `.tar.gz` format. + +For further information about how to create such an archive file, see the +documentation for the +[`stack haddock --haddock-for-hackage`](build_command.md#-no-haddock-for-hackage-flag) +command. + +If `ITEM` is a relative path to a package directory, +`stack upload <package_directory> --documentation` uploads an existing archive +file of documentation for the specified package to Hackage. + +If the `--documentation` flag is passed then flags specific to package upload +are ignored. + +## The `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` environment variables + +[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) + +`stack upload` will request a Hackage username and password to authenticate. +This can be avoided by setting the `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` +environment variables. For +example: + +=== "Unix-like" + + ~~~text + export $HACKAGE_USERNAME="<username>" + export $HACKAGE_PASSWORD="<password>" + stack upload . + ~~~ + +=== "Windows (with PowerShell)" + + ~~~text + $Env:HACKAGE_USERNAME='<username>' + $Env:HACKAGE_PASSWORD='<password>' + stack upload . + ~~~ + +## The `HACKAGE_KEY` environment variable + +[:octicons-tag-24: 2.7.5](https://github.com/commercialhaskell/stack/releases/tag/v2.7.5) + +Hackage allows its members to register an API authentification token and to +authenticate using the token. + +A Hackage API authentification token can be used with `stack upload` instead of +username and password, by setting the `HACKAGE_KEY` environment variable. For +example: + +=== "Unix-like" + + ~~~text + HACKAGE_KEY=<api_authentification_token> + stack upload . + ~~~ + +=== "Windows (with PowerShell)" + + ~~~text + $Env:HACKAGE_KEY=<api_authentification_token> + stack upload . + ~~~
+ doc/community/index.md view
@@ -0,0 +1,75 @@+--- +title: Get involved +--- +<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Get involved + +## Feedback and discussion + +* For general comments, feedback and support, please post to the + [Haskell Community](https://discourse.haskell.org/about). +* For bugs, issues, or requests, please + [open an issue](https://github.com/commercialhaskell/stack/issues/new). +* When using Stack Overflow, please use the + [haskell-stack](http://stackoverflow.com/questions/tagged/haskell-stack) tag. + +## How to contribute to the maintenance or development of Stack + +A [guide](../CONTRIBUTING.md) is provided to help potential contributors to the +Stack project. + +If you have already installed a version of Stack and the +[Git application](https://git-scm.com/) the followings steps should get you +started with building Stack from source with Stack: + +1. Clone the `stack` repository from GitHub with the command: + + ~~~text + git clone https://github.com/commercialhaskell/stack.git + ~~~ + +2. Change the current working directory to the cloned `stack` directory with + the command: + + ~~~text + cd stack + ~~~ + +3. Build the `stack` executable using a preexisting installation of Stack with + the command: + + ~~~text + stack build + ~~~ + +4. Once the `stack` executable has been built, check its version with the + command: + + ~~~text + stack exec -- stack --version + ~~~ + + Make sure the version is the latest one. + +5. In the GitHub repository's issue tracker, look for issues tagged with + [newcomer friendly](https://github.com/commercialhaskell/stack/issues?q=is%3Aopen+is%3Aissue+label%3a%22newcomer+friendly%22) + and + [awaiting pull request](https://github.com/commercialhaskell/stack/issues?q=is%3Aopen+is%3Aissue+label%3A%22awaiting+pull+request%22) + labels. + +If you need to check your changes quickly command: + +~~~text +stack repl +~~~ + +and then, at the REPL's prompt, command: + +~~~text +:main --stack-root=<path_to_root> --stack-yaml=<path_to_stack.yaml> <COMMAND> +~~~ + +This allows you to set a special Stack root (instead of the default Stack root) +and to target your commands at a particular `stack.yaml` file instead of the one +found in the current directory.
− doc/config_command.md
@@ -1,136 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack config` commands - -~~~text -stack config COMMAND - -Available commands: - env Print environment variables for use in a shell - set Sets a key in YAML configuration file to value -~~~ - -The `stack config` commands provide assistance with accessing or modifying -Stack's configuration. See `stack config` for the available commands. - -## The `stack config env` command - -~~~text -stack config env [--[no-]locals] [--[no-]ghc-package-path] [--[no-]stack-exe] - [--[no-]locale-utf8] [--[no-]keep-ghc-rts] -~~~ - -`stack config env` outputs a script that sets or unsets environment variables -for a Stack environment. Flags modify the script that is output: - -* `--[no-]locals` (enabled by default) include/exclude project package - information -* `--[no-]ghc-package-path` (enabled by default) set `GHC_PACKAGE_PATH` - environment variable or not -* `--[no-]stack-exe` (enabled by default) set `STACK_EXE` environment variable - or not -* `--[no-]locale-utf8` (disabled by default) set the `GHC_CHARENC` - environment variable to `UTF-8` or not -* `--[no-]keep-ghc-rts` (disabled by default) keep/discard any `GHCRTS` - environment variable - -The command also accepts flags and options of the -[`stack build`](build_command.md#flags-affecting-ghcs-behaviour) command that -affect the location of the local project installation directory, such as -`--profile` and `--no-strip`. For further information, see the documentation of -the [project Stack work directory](stack_work.md#project-stack-work-directory). - -## The `stack config set` commands - -~~~text -stack config set COMMAND - -Available commands: - install-ghc Configure whether Stack should automatically install - GHC when necessary. - package-index Configure Stack's package index - resolver Change the resolver key of the current project. - snapshot Change the snapshot of the current project. - system-ghc Configure whether Stack should use a system GHC - installation or not. -~~~ - -The `stack config set` commands allow the values of keys in YAML configuration -files to be set. See `stack config set` for the available keys. - -!!! note - - The `config set` commands support an existing key only in the form - `key: value` on a single line. - -## The `stack config set install-ghc` command - -~~~text -stack config set install-ghc [--global] true|false -~~~ - -`stack config set install-ghc true` or `false` sets the `install-ghc` key in a -YAML configuration file, accordingly. By default, the project-level -configuration file (`stack.yaml`, by default) is altered. The `--global` flag -specifies the user-specific global configuration file (`config.yaml`). - -## The `stack config set package-index download-prefix` command - -[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) - -~~~text -stack config set package-index download-prefix [--global] [URL] -~~~ - -`stack config set package-index download-prefix <url>` sets the -`download-prefix` key of the `package-index` key in a YAML configuration file, -accordingly. By default, the project-level configuration file (`stack.yaml`, by -default) is altered. The `--global` flag specifies the user-specific global -configuration file (`config.yaml`). - -## The `stack config set resolver` command - -~~~text -stack config set resolver SNAPSHOT -~~~ - -`stack config set resolver <snapshot>` sets the `resolver` key in the -project-level configuration file (`stack.yaml`, by default). - -A snapshot of `lts` or `nightly` will be translated into the most recent -available. A snapshot of `lts-22` will be translated into the most recent -available in the `lts-22` sequence. - -Known bug: - -* The command does not respect the presence of a `snapshot` key. - -## The `stack config set snapshot` command - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -~~~text -stack config set snapshot SNAPSHOT -~~~ - -`stack config set snapshot <snapshot>` sets the `snapshot` key in the -project-level configuration file (`stack.yaml`, by default). - -A snapshot of `lts` or `nightly` will be translated into the most recent -available. A snapshot of `lts-22` will be translated into the most recent -available in the `lts-22` sequence. - -Known bug: - -* The command does not respect the presence of a `resolver` key. - -## The `stack config set system-ghc` command - -~~~text -stack config set system-ghc [--global] true|false -~~~ - -`stack config set system-ghc true` or `false` sets the `system-ghc` key in a -YAML configuration file, accordingly. By default, the project-level -configuration file (`stack.yaml`, by default) is altered. The `--global` flag -specifies the user-specific global configuration file (`config.yaml`).
+ doc/configure/customisation_scripts.md view
@@ -0,0 +1,133 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Customisation scripts + +## GHC installation customisation + +[:octicons-tag-24: 2.9.1](https://github.com/commercialhaskell/stack/releases/tag/v2.9.1) + +On Unix-like operating systems and Windows, Stack's installation procedure can +be fully customised by placing a `sh` shell script (a 'hook') in the +[Stack root](../topics/stack_root.md) directory at `hooks/ghc-install.sh`. On +Unix-like operating systems, the script file must be made executable. The script +is run by the `sh` application (which is provided by MSYS2 on Windows). + +The script **must** return an exit code of `0` and the standard output **must** +be the absolute path to the GHC binary that was installed. Otherwise Stack will +ignore the script and possibly fall back to its own installation procedure. + +When `system-ghc: true`, the script is not run. That is because the two +mechanisms reflect distinct concepts, namely: + +* `system-ghc: true` causes Stack to search the PATH for a version of GHC; and + +* `hooks/ghc-install.sh` causes Stack to execute a script that is intended to + send to standard output a path to a version of GHC. The path in question may + or may not be in the PATH. The script may also do other things, including + installation. + +When `install-ghc: false`, the script is still run. That allows you to ensure +that only your script will install GHC and Stack won't default to its own +installation logic, even when the script fails. + +The following environment variables are always available to the script: + +* `HOOK_GHC_TYPE = "bindist" | "git" | "ghcjs"` + +For "bindist", additional variables are: + +* `HOOK_GHC_VERSION = <ver>` + +For "git", additional variables are: + +* `HOOK_GHC_COMMIT = <commit>` +* `HOOK_GHC_FLAVOR = <flavor>` + +For "ghcjs", additional variables are: + +* `HOOK_GHC_VERSION = <ver>` +* `HOOK_GHCJS_VERSION = <ver>` + +An example script is: + +~~~sh +#!/bin/sh + +set -eu + +case $HOOK_GHC_TYPE in + bindist) + # install GHC here, not printing to stdout, e.g.: + # command install $HOOK_GHC_VERSION >/dev/null + ;; + git) + >&2 echo "Hook doesn't support installing from source" + exit 1 + ;; + *) + >&2 echo "Unsupported GHC installation type: $HOOK_GHC_TYPE" + exit 2 + ;; +esac + +echo "location/to/ghc/executable" +~~~ + +If the following script is installed by GHCup, GHCup makes use of it, so that if +Stack needs a version of GHC, GHCup takes over obtaining and installing that +version: + +~~~sh +#!/bin/sh + +set -eu + +case $HOOK_GHC_TYPE in + bindist) + ghcdir=$(ghcup whereis --directory ghc "$HOOK_GHC_VERSION" || ghcup run --ghc "$HOOK_GHC_VERSION" --install) || exit 3 + printf "%s/ghc" "${ghcdir}" + ;; + git) + # TODO: should be somewhat possible + >&2 echo "Hook doesn't support installing from source" + exit 1 + ;; + *) + >&2 echo "Unsupported GHC installation type: $HOOK_GHC_TYPE" + exit 2 + ;; +esac +~~~ + +## `--file-watch` post-processing + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +On Unix-like operating systems and Windows, Stack's `build --file-watch` +post-processing can be fully customised by specifying an executable or a `sh` +shell script (a 'hook') using the +[`file-watch-hook`](yaml/non-project.md#file-watch-hook) +non-project specific configuration option. On Unix-like operating systems, the +script file must be made executable. A script is run by the `sh` application +(which is provided by MSYS2 on Windows). + +The following environment variables are always available to the executable or +script: + +* `HOOK_FW_RESULT` (Equal to `""` if the build did not fail. Equal to the result + of `displayException e`, if exception `e` thown during the build.) + +An example script is: + +~~~sh +#!/bin/sh + +set -eu + +if [ -z "$HOOK_FW_RESULT" ]; then + echo "Success! Waiting for next file change." +else + echo "Build failed with exception:" + echo $HOOK_FW_RESULT +fi +~~~
+ doc/configure/environment_variables.md view
@@ -0,0 +1,152 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Stack's environment variables + +The environment variables listed in alphabetal order below can affect how Stack +behaves. + +## `GH_TOKEN` or `GITHUB_TOKEN` + +[:octicons-tag-24: 2.11.1](https://github.com/commercialhaskell/stack/releases/tag/v2.11.1) + +Stack will use the value of the `GH_TOKEN` or, in the alternative, +`GITHUB_TOKEN` environment variable (if not an empty string) as credentials to +authenticate its requests of the GitHub REST API, using HTTP 'Basic' +authentication. + +GitHub limits the rate of unauthenticated requests to its API, although most +users of Stack will not experience that limit from the use of Stack alone. The +limit for authenticated requests is significantly higher. + +For more information about authentication of requests of the GitHub REST API, +see GitHub's REST API documentation. + +## `HACKAGE_KEY` + +[:octicons-tag-24: 2.7.5](https://github.com/commercialhaskell/stack/releases/tag/v2.7.5) + +Related command: [`stack upload`](../commands/upload_command.md) + +Hackage allows its members to register an API authentification token and to +authenticate using the token. + +A Hackage API authentification token can be used with `stack upload` instead of +username and password, by setting the `HACKAGE_KEY` environment variable. For +example: + +=== "Unix-like" + + ~~~text + HACKAGE_KEY=<api_authentification_token> + stack upload . + ~~~ + +=== "Windows (with PowerShell)" + + ~~~text + $Env:HACKAGE_KEY=<api_authentification_token> + stack upload . + ~~~ + +## `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` + +[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) + +Related command: [`stack upload`](../commands/upload_command.md) + +`stack upload` will request a Hackage username and password to authenticate. +This can be avoided by setting the `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` +environment variables. For +example: + +=== "Unix-like" + + ~~~text + export $HACKAGE_USERNAME="<username>" + export $HACKAGE_PASSWORD="<password>" + stack upload . + ~~~ + +=== "Windows (with PowerShell)" + + ~~~text + $Env:HACKAGE_USERNAME='<username>' + $Env:HACKAGE_PASSWORD='<password>' + stack upload . + ~~~ + +## `NO_COLOR` + +Related command: all commands that can produce colored output using control +character sequences. + +Stack follows the standard at http://no-color.org/. Stack checks for a +`NO_COLOR` environment variable. When it is present and not an empty string +(regardless of its value), Stack prevents the addition of control character +sequences for color to its output. + +## `STACK_CONFIG` + +Related command: all commands that make use of Stack's +[global configuration](yaml/index.md) files (`config.yaml`). + +The environment variable `STACK_CONFIG` can be used to specify an absolute path +to the user-specific global configuration file, overriding the default. + +## `STACK_GLOBAL_CONFIG` + +Related command: all commands that make use of Stack's +[global configuration](yaml/index.md) files (`config.yaml`). + +The environment variable `STACK_GLOBAL_CONFIG` can be used to specify an +absolute path to the system-wide global configuration file, overriding the +default. + +## `STACK_ROOT` + +Related command: all commands that make use of Stack's +[user-specific global configuration](yaml/index.md) file (`config.yaml`). + +Overridden by: Stack's global +[`--stack-root`](global_flags.md#-stack-root-option) option. + +The environment variable `STACK_ROOT` can be used to specify the +[Stack root](../topics/stack_root.md) directory. + +## `STACK_WORK` + +Related command: all commands that make use of Stack's work directories. + +Overridden by: Stack's [`work-dir`](yaml/non-project.md#work-dir) non-project +specific configuration option, or global +[`--work-dir`](global_flags.md#-work-dir-option) option. + +The environment variable `STACK_WORK` can be used to specify the path of Stack's +work directory, within a local project or package directory, and override +Stack's default of `.stack-work`. The path must be a relative one, relative to +the root directory of the project or package. The relative path cannot include a +`..` (parent directory) component. + +## `STACK_XDG` + +Related command: all commands that make use of Stack's +[user-specific global configuration](yaml/index.md) file (`config.yaml`). + +Overridden by: the use of Stack's `STACK_ROOT` environment variable, or the use +of Stack's global +[`--stack-root`](global_flags.md#-stack-root-option) option. + +On Unix-like operating systems and Windows, Stack can be configured to follow +the XDG Base Directory Specification if the environment variable `STACK_XDG` is +set to any non-empty value. + +## `STACK_YAML` + +Related command: all commands that make use of Stack's +[project-level configuration](yaml/index.md). + +Overridden by: Stack's global +[`--stack-yaml`](global_flags.md#-stack-yaml-option) option. + +The environment variable `STACK_YAML` can be used to specify Stack's +project-level configuration file.
+ doc/configure/global_flags.md view
@@ -0,0 +1,362 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Stack's global flags and options + +Stack can also be configured by flags and options on the command line. Global +flags and options apply to all of Stack's commands. In addition, all of Stack's +commands accept the `--setup-info-yaml` and `--snapshot-location-base` options +and the `--help` flag. + +## `--allow-different-user` flag + +Restrictions: POSIX systems only + +Default: True, if inside Docker; false otherwise + +Enable/disable permitting users other than the owner of the +[Stack root](../topics/stack_root.md) directory to use a Stack installation. For +further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#allow-different-user). + +## `--arch` option + +Pass the option `--arch <architecture>` to specify the relevant machine +architecture. For further information, see the documentation for the +corresponding non-project specific configuration +[option](yaml/non-project.md#arch). + +## `--color` or `-colour` options + +Pass the option `stack --color <when>` to specify when to use color in output. +For further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#color). + +## `--compiler` option + +Pass the option `--compiler <compiler>` to specify the compiler. For further +information, see the [`compiler`](yaml/non-project.md#compiler) non-project +specific configuration option documentation. + +## `--custom-preprocessor-extensions` option + +Pass the option `--custom-preprocessor-extensions <extension>` to specify an +extension used for a custom preprocessor. For further information, see the +documentation for the corresponding project specific configuration +[option](yaml/project.md#custom-preprocessor-extensions). + +## `--docker*` flags and options + +Stack supports automatically performing builds inside a Docker container. For +further information see `stack --docker-help` or the +[Docker integration](../topics/docker_integration.md) documentation. + +## `--[no-]dump-logs` flag + +Default: Dump warning logs + +Enables/disables the dumping of the build output logs for project packages to +the console. For further information, see the documentation for the +corresponding non-project specific configuration +[option](yaml/non-project.md#dump-logs). + +## `--extra-include-dirs` option + +Pass the option `--extra-include-dirs <director>` to specify an extra directory +to check for C header files. The option can be specified multiple times. For +further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#extra-include-dirs). + +## `--extra-lib-dirs` option + +Pass the option `--extra-lib-dirs <director>` to specify an extra directory +to check for libraries. The option can be specified multiple times. For further +information, see the documentation for the corresponding non-project specific +configuration [option](yaml/non-project.md#extra-lib-dirs). + +## `--ghc-build` option + +Pass the option `--ghc-build <build>` to specify the relevant specialised GHC +build. For further information, see the documentation for the corresponding +non-project specific configuration [option](yaml/non-project.md#ghc-build). + +## `--ghc-variant` option + +Pass the option `--ghc-variant <variant>` to specify the relevant GHC variant. +For further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#ghc-variant). + +## `--[no-]hpack-force` flag + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +Default: Disabled + +By default, Hpack 0.20.0 or later will decline to overwrite a Cabal file that +has been modified manually. Pass the flag `--hpack-force` to allow Hpack to +overwrite such a Cabal file. + +## `--hpack-numeric-version` flag + +Pass the flag `--hpack-numeric-version` to cause Stack to report the numeric +version of its built-in Hpack library to the standard output stream (e.g. +`0.35.0`) and quit. + +## `--[no-]install-ghc` flag + +Default: Enabled + +Enables/disables the download and instalation of GHC if necessary. For further +information, see the documentation for the corresponding non-project specific +configuration [option](yaml/non-project.md#install-ghc). + +## `--jobs` or `-j` option + +Pass the option `--jobs <number_of_jobs>` to specify the number of concurrent +jobs (Stack actions during building) to run. + +When [building GHC from source](yaml/non-project.md#building-ghc-from-source), +specifies the `-j[<n>]` flag of GHC's Hadrian build system. + +By default, Stack specifies a number of concurrent jobs equal to the number of +CPUs (cores) that the machine has. In some circumstances, that default can cause +some machines to run out of memory during building. If those circumstances +arise, specify `--jobs 1`. + +This configuration option is distinct from GHC's own `-j[<n>]` flag, which +relates to parallel compilation of modules within a package. + +For further information, see the documentation for the corresponding non-project +specific configuration option: [`jobs`](yaml/non-project.md#jobs). + +## `--local-bin-path` option + +Pass the option `--local-bin-path <directory>` to set the target directory for +[`stack build --copy-bins`](../commands/build_command.md#-no-copy-bins-flag) and +`stack install`. An absolute or relative path can be specified. A relative path +at the command line is always assumed to be relative to the current directory. + +For further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#local-bin-path). + +## `--lock-file` option + +Default: `read-write`, if snapshot specified in the project-level configuration +file; `read-only`, if a different snapshot is specified on the command line. + +Pass the option `--lock-file <mode>` to specify how Stack interacts with lock +files. Valid modes are: + +* `error-on-write`: Stack reports an error, rather than write a lock file; +* `ignore`: Stack ignores lock files; +* `read-only`: Stack only reads lock files; and +* `read-write`: Stack reads and writes lock files. + +## `--[no-]modify-code-page` flag + +Restrictions: Windows systems only + +Default: Enabled + +Enables/disables setting the codepage to support UTF-8. For further information, +see the documentation for the corresponding non-project specific configuration +[option](yaml/non-project.md#modify-code-page). + +## `--nix*` flags and options + +Stack can be configured to integrate with Nix. For further information, see +`stack --nix-help` or the [Nix integration](../topics/nix_integration.md) +documentation. + +## `--numeric-version` flag + +Pass the flag `--numeric-version` to cause Stack to report its numeric version +to the standard output stream (e.g. `2.9.1`) and quit. + +## `--[no-]plan-in-log` flag + +[:octicons-tag-24: 2.13.1](https://github.com/commercialhaskell/stack/releases/tag/v2.13.1) + +Default: Disabled + +Enables/disables the logging of build plan construction in debug output. +Information about the build plan construction can be lengthy. If you do not need +it, it is best omitted from the debug output. + +## `--resolver` option + +A synonym for the [`--snapshot` option](#-snapshot-option) to specify the +snapshot resolver. + +## `--[no-]rsl-in-log` flag + +[:octicons-tag-24: 2.9.1](https://github.com/commercialhaskell/stack/releases/tag/v2.9.1) + +Default: Disabled + +Enables/disables the logging of the raw snapshot layer (rsl) in debug output. +Information about the raw snapshot layer can be lengthy. If you do not need it, +it is best omitted from the debug output. + +## `--[no-]script-no-run-compile` flag + +Default: Disabled + +Enables/disables the use of options `--no-run --compile` with the +[`stack script` command](../commands/script_command.md). + +## `--silent` flag + +Equivalent to the `--verbosity silent` option. + +## `--[no-]skip-ghc-check` option + +Default: Disabled + +Enables/disables the skipping of checking the GHC version and architecture. For +further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#skip-ghc-check). + +## `--[no-]skip-msys` option + +Restrictions: Windows systems only + +Default: Disabled + +Enables/disables the skipping of checking for the Stack-supplied MSYS2 (and +installing that MSYS2, if it is not installed) when Stack is setting up the +environment. For further information, see the documentation for the +corresponding non-project specific configuration +[option](yaml/non-project.md#skip-msys). + +## `--snapshot` option + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +Pass the option `--snapshot <snapshot>` to specify the snapshot. For further +information, see the [`snapshot`](yaml/project.md#snapshot) project-specific +configuration option documentation. + +At the command line (only): + +* `--snapshot lts-<major_version>` specifies the latest Stackage LTS Haskell + snapshot with the specified major version; +* `--snapshot lts` specifies, from those with the greatest major version, the + latest Stackage LTS Haskell snapshot; +* `--snapshot nightly` specifies the most recent Stackage Nightly snapshot; + and +* `--snapshot global` specifies the snapshot specified by the project-level + configuration file in the `global-project` directory in the + [Stack root](../topics/stack_root.md#global-project-directory). + +## `--stack-colors` or `--stack-colours` options + +Pass the option `--stack-colors <styles>` to specify Stack's output styles. For +further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#stack-colors). + +## `--stack-root` option + +Overrides: `STACK_ROOT` environment variable + +Pass the option `--stack-root <absolute_path_to_the_Stack_root>` to specify the +path to the [Stack root](../topics/stack_root.md) directory. The path must be an +absolute one. + +## `--stack-yaml` option + +Default: `stack.yaml` + +Overrides: `STACK_YAML` enviroment variable + +Pass the option `--stack-yaml <file>` to specify Stack's project-level YAML +configuration file. + +## `--[no-]system-ghc` flag + +Default: Disabled + +Enables/disables the use of a GHC executable on the PATH, if one is available +and its version matches. + +## `--[no-]terminal` flag + +Default: Stack is running in a terminal (as detected) + +Enables/disables whether Stack is running in a terminal. + +## `--terminal-width` option + +Default: the terminal width (if detected); otherwise `100` + +Pass the option `--terminal-width <width>` to specify the width of the terminal, +used by Stack's pretty printed messages. + +## `--[no-]time-in-logs` flag + +Default: Enabled + +Enables/disables the inclusion of time stamps against logging entries when the +verbosity level is 'debug'. + +## `--verbose` or `-v` flags + +Equivalent to the `--verbosity debug` option. + +## `--verbosity` option + +Default: `info` + +Pass the option `--verbosity <log_level>` to specify the level for logging. +Possible levels are `silent`, `error`, `warn`, `info` and `debug`, in order of +increasing amounts of information provided by logging. + +## `--version` flag + +Pass the flag `--version` to cause Stack to report its version to standard +output and quit. For versions that are release candidates, the report will list +the dependencies that Stack has been compiled with. + +## `--with-gcc` option + +Pass the option `--with-gcc <path_to_gcc>` to specify use of a GCC executable. +For further information, see the documentation for the corresponding non-project +specific configuration [option](yaml/non-project.md#with-gcc). + +## `--with-hpack` option + +Pass the option `--with-hpack <hpack>` to specify use of an Hpack executable. +For further information, see the documentation for the corresponding +non-project specific configuration [option](yaml/non-project.md#with-hpack). + +## `--work-dir` option + +Default: `.stack-work` + +Overrides: [`STACK_WORK`](environment_variables.md#stack_work) environment +variable, and [`work-dir`](yaml/non-project.md#work-dir) non-project specific +configuration option. + +Pass the option `--work-dir <relative_path_to_the_Stack_root>` to specify the +path to Stack's work directory, within a local project or package directory. The +path must be a relative one, relative to the the root directory of the project +or package. The relative path cannot include a `..` (parent directory) +component. + +## `--setup-info-yaml` command option + +Default: `https://raw.githubusercontent.com/commercialhaskell/stackage-content/master/stack/stack-setup-2.yaml` + +The `--setup-info-yaml <url>` command option specifies the location of a +`setup-info` dictionary. The option can be specified multiple times. + +## `--snapshot-location-base` command option + +Default: `https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master` + +The `--snapshot-location-base <url>` command option specifies the base location +of snapshots. + +## `--help` or `-h` command flags + +If Stack is passed the `--help` (or `-h`) command flag, it will output help for +the command.
+ doc/configure/index.md view
@@ -0,0 +1,41 @@+--- +Title: Configure +--- +<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Configuration (advanced) + +Some of Stack's features will not be needed regularly or by all users. This part +of the guide and the part on Stack's [commands](../commands/index.md) provide +information about those features, organised as a reference guide. Some of the +features are complex and separate pages are dedicated to them. + +The behaviour of Stack is configurable using environment variables, YAML +configuration files, global flags and options on the command line and +customisation scripts. + +## Environment variables + +The existence or content of certain environment variables can affect how Stack +behaves. For further information, see the +[environment variables](environment_variables.md) documentation. + +## Configuration files + +Stack is configured by the content of files in the YAML formal. A global +configuration file contains non-project specific options. A project-level +configuration file contains project-specific options and may contain non-project +specific options. For further information, see the +[configuration](yaml/index.md) documentation. + +## Global flags and options + +Stack can also be configured by flags and options on the command line. Global +flags and options apply to all of Stack's commands. For further information, see +the [global flags and options](global_flags.md) documentation. + +## Customisation scripts + +Stack's behaviour can also be affected by customisation scripts. For further +information, see the [customisation scripts](customisation_scripts.md) +documentation.
+ doc/configure/yaml/index.md view
@@ -0,0 +1,126 @@+--- +title: Configuration files +--- +<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Configuration files + +Stack is configured by the content of files in the [YAML](https://yaml.org/) +format. + +## Project-specific and non-project specific options + +Stack's configuration options are each of one of two types: + +<div class="grid cards" markdown> + +- :material-account:{ .lg .middle } __Project-specific__ + + Configured at the project level + + --- + + [:octicons-arrow-right-24: Learn more](project.md) + +- :material-account-multiple:{ .lg .middle } __Non-project specific__ + + Configured globally or at the project level. + + --- + + [:octicons-arrow-right-24: Learn more](non-project.md) + +</div> + +## Project-level and global configuration files + +Stack's configuration files are each of one of two types: + +<div class="grid cards" markdown> + +- :material-language-haskell:{ .lg .middle } __Project-level__ + + Named `stack.yaml` by default. + + --- + + Contains [project-specific](project.md) options and may contain + [non-project-specific](non-project.md) options. + + Non-project-specific options in the project-level configuration file in the + `global-project` directory (see below) are ignored by Stack. + +- :octicons-globe-24:{ .lg .middle } __Global__ + + Named `config.yaml`. + + There is a user-specific file and there may be a system-wide one. If a + user-specific file does not exist, then Stack will create one. + + --- + + Contains [non-project-specific](non-project.md) options. + + An option set in the user-specific file will override a corresponding option + set in the system-wide file (if it exists). + +</div> + +## Location of project-level configuration + +Stack obtains project-level configuration from one of the following (in order of +preference): + +1. A file specified by the `--stack-yaml` command line option. +2. A file specified by the `STACK_YAML` environment variable. +3. A file named `stack.yaml` in the current directory or an ancestor directory. +4. A file name `stack.yaml` in the `global-project` directory in the + [Stack root](../../topics/stack_root.md). + +## Location of global configuration + +The default location of global configuration files depends on the operating +system and, in the case of the user-specific file, whether Stack is configured +to use the XDG Base Directory Specification. + +An absolute path to these files can be specified by the +[`STACK_CONFIG`](../environment_variables.md#stack_config) and +[`STACK_GLOBAL_CONFIG`](../environment_variables.md#stack_config) environment +variables, respectively. + +=== "Unix-like" + + The default locations are: + + * system-wide: `/etc/stack/config.yaml`; and + * user-specific: `config.yaml` in the + [Stack root](../../topcis/stack_root.md). + + !!! note + + For compatibility with Stack 0.1.5.0 and earlier, if deprecated file + `/etc/stack/config` exists, then Stack will use it instead of + `/etc/stack/config.yaml`. + +=== "Windows" + + The default locations are: + + * system-wide: none; and + * user-specific: `config.yaml` in the + [Stack root](../../topics/stack_root.md). + +=== "XDG Base Directory Specification" + + On Unix-like operating systems and Windows, Stack can be configured to + follow the XDG Base Directory Specification if the environment variable + `STACK_XDG` is set to any non-empty value. However, Stack will ignore that + configuration if the [Stack root](../../topics/stack_root.md) location has + been set on the command line or the `STACK_ROOT` environment variable + exists. + + If Stack is following the XDG Base Directory Specification, the location of + `config.yaml` (for user-specific options) is `<XDG_CONFIG_HOME>/stack`. If + the `XDG_CONFIG_HOME` environment variable does not exist, the default is + `~/.config/stack` on Unix-like operating systems and `%APPDIR%\stack` on + Windows.
+ doc/configure/yaml/non-project.md view
@@ -0,0 +1,1606 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Non-project-specific configuration + +Non-project configuration options can be included in a project-level +configuration file (`stack.yaml`, by default) or in global configuration files +(`config.yaml`). However, non-project-specific options in the project-level +configuration file in the `global-project` directory are ignored by Stack. The +options below are listed in alphabetic order. + +## allow-different-user + +[:octicons-tag-24: 1.0.1.0](https://github.com/commercialhaskell/stack/releases/tag/v1.0.1.0) + +Restrictions: POSIX systems only. + +Default: `false` + +Command line equivalent (takes precedence): `--[no-]allow-different-user` flag + +Allow users other than the owner of the [Stack root](../../topics/stack_root.md) +to use the Stack installation. + +~~~yaml +allow-different-user: true +~~~ + +The intention of this option is to prevent file permission problems, for example +as the result of a Stack command executed under `sudo`. + +The option is automatically enabled when Stack is re-spawned in a Docker +process. + +## allow-newer + +[:octicons-tag-24: 0.1.8.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.8.0) + +Default: `false` + +Command line equivalent (takes precedence): +[`stack build --[no-]allow-newer`](build_command.md#-allow-newer-flag) flag + +Whether to ignore lower and upper version bounds in Cabal files. + +!!! info + + The name `allow-newer` was chosen to match a commonly-used Cabal option + which ignored only upper bounds. + +~~~yaml +allow-newer: true +~~~ + +## allow-newer-deps + +:octicons-beaker-24: Experimental + +[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) + +Default: `none` + +Determines a subset of packages to which `allow-newer` should apply. This option +has no effect (but warns) if `allow-newer` is `false`. + +~~~yaml +allow-newer-deps: + - foo + - bar +~~~ + +## apply-ghc-options + +[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) + +Default: `locals` + +Related command line: +[`stack build --ghc-options`](../../commands/build_command.md#-ghc-options-option) +option + +Determines to which packages any GHC command line options specified on the +command line are applied. Possible values are: `everything` (all packages, +project packages or otherwise), `locals` (all project packages, targets or +otherwise), and `targets` (all project packages that are targets). + +!!! note + + The use of `everything` can break invariants about your snapshot database. + +!!! info + + Before Stack 0.1.6.0, the default value was `targets`. + +## apply-prog-options + +[:octicons-tag-24: 2.11.1](https://github.com/commercialhaskell/stack/releases/tag/v2.11.1) + +Default: `locals` + +Related command line: +[`stack build --PROG-option`](../../commands/build_command.md#-prog-option-options) options + +Determines to which packages all and any `--PROG-option` command line options +specified on the command line are applied. Possible values are: `everything` +(all packages, project packages or otherwise), `locals` (all project packages, +targets or otherwise), and `targets` (all project packages that are targets). + +!!! note + + The use of `everything` can break invariants about your snapshot database. + +## arch + +Default: The machine architecture on which Stack is running. + +Command line equivalent (takes precedence): +[`--arch`](../global_flags.md#-arch-option) option + +Stack identifies different GHC executables by platform (operating system and +machine architecture), (optional) GHC variant and (optional) GHC build. +See [`setup-info`](#setup-info). + +`arch` sets the machine architecture. Values can be those recognized by Cabal +(the library) (which are case-insensitive and include `i386`, `x86_64`, and +`aarch64` / `arm64`), or other values (which are case-sensitive and treated as +an unknown 'other' architecture of the specified name). + +By default, Stack will warn the user if the specified machine architecture is an +unknown 'other' architecture. The warning can be muted; see +[`notify-if-arch-unknown`](#notify-if-arch-unknown) + +!!! note + + The machine architecture on which Stack is running is as classified by + Cabal (the library). Cabal does not distinguish between certain + architectures. Examples are `ppc64`/`powerpc64`/`powerpc64le` (classified as + `ppc64`) and `arm`/`armel`/`armeb` (classified as `arm`). + +!!! note + + As Cabal (the library) does not distinguish between machine architectures + `powerpc64` and `powerpc64le`, the latter can be specified in Stack's + configuration as an 'other' architecture, such as `arch: ppc64le`. + +## build + +[:octicons-tag-24: 1.1.0](https://github.com/commercialhaskell/stack/releases/tag/v1.1.0) + +Default: + +~~~yaml +build: + library-profiling: false + executable-profiling: false + library-stripping: true + executable-stripping: true + + # NOTE: global usage of haddock can cause build failures when documentation is + # incorrectly formatted. This could also affect scripts which use Stack. + haddock: false + haddock-arguments: + + # Additional arguments passed to haddock. The corresponding command line + # option is --haddock-arguments. Example of use: + # + # haddock-args: + # - "--css=/home/user/my-css" + haddock-args: [] + + # The corresponding command line flag is --[no-]open. + open-haddocks: false + + # If Stack is configured to build Haddock documentation, defaults to true. + haddock-deps: false + + # The configuration is ignored, if haddock-for-hackage: true. + haddock-internal: false + + # The configuration is ignored, if haddock-for-hackage: true. + haddock-hyperlink-source: true + + # If specified, implies haddock-internal: false and + # haddock-hyperlink-source: true. Since Stack 2.15.1. + haddock-for-hackage: false + copy-bins: false + copy-compiler-tool: false + prefetch: false + keep-going: false + keep-tmp-files: false + + # These are inadvisable to use in your global configuration, as they make the + # Stack build command line behave quite differently. + force-dirty: false + test: false + test-arguments: + rerun-tests: true # Rerun successful tests + + # The corresponding command line option is --test-arguments. Example of use: + # + # additional-args: + # - "--fail-fast" + additional-args: [] + coverage: false + no-run-tests: false + bench: false + benchmark-opts: + + # Example of use: + # + # benchmark-arguments: "--csv bench.csv" + benchmark-arguments: "" + no-run-benchmarks: false + reconfigure: false + cabal-verbosity: normal + cabal-verbose: false + split-objs: false + skip-components: [] # --skip + + # Since Stack 1.8. Starting with Stack 2.0, the default is true + interleaved-output: true + + # Since Stack 2.13.1. Available options are none, count-only, capped and full. + progress-bar: capped + + # Since Stack 1.10. + ddump-dir: "" +~~~ + +Command line equivalents (take precedence): Yes, see below. + +Allows setting build options which are usually specified on the command line. + +The meanings of these settings correspond directly with the command line flags +of the same name. For further information, see the +[`stack build`](../../commands/build_command.md) command documentation. + +## casa + +[:octicons-tag-24: 2.13.1](https://github.com/commercialhaskell/stack/releases/tag/v2.13.1) + +Default: + +~~~yaml +casa: + enable: true # Use a Casa server? + repo-prefix: https://casa.stackage.org # Unless casa-repo-prefix is set. + max-keys-per-request: 1280 # Maximum number of keys per request. +~~~ + +This option specifies whether or not Stack should use a Casa +(content-addressable storage archive) server to cache Cabal files and all other +files in packages; and, if so, the prefix for the URL used to pull information +from the server and the maximum number of keys per request. For further +information, see this blog post about +[Casa and Stack](https://www.fpcomplete.com/blog/casa-and-stack/). + +`repo-prefix` replaces [`casa-repo-prefix`](#casa-repo-prefix) (which is +deprecated) and has precedence if both keys are set. + +## casa-repo-prefix + +[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) + +Deprecated in favour of [`casa`](#casa), which takes precedence if present. + +Default: `https://casa.stackage.org` + +This option specifies the prefix for the URL used to pull information from the +Casa server. + +## color + +Command line equivalent (takes precedence): `--color` option + +This option specifies when to use color in output. The option is used as +`color: <WHEN>`, where `<WHEN>` is 'always', 'never', or 'auto'. On Windows +versions before Windows 10, for terminals that do not support color codes, the +default is 'never'; color may work on terminals that support color codes. + +(The British English spelling (colour) is also accepted. In configuration files, +the American spelling is the alternative that has priority.) + +## compiler + +[:octicons-tag-24: 0.1.8.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.8.0) + +Command line equivalent (takes precedence): `--compiler` option + +Overrides the compiler version in the snapshot. Note that the `compiler-check` +flag also applies to the version numbers. This uses the same syntax as compiler +snapshots like `ghc-9.6.6`. This can be used to override the compiler for a +Stackage snapshot, like this: + +~~~yaml +snapshot: lts-22.28 +compiler: ghc-9.6.5 +compiler-check: match-exact +~~~ + +### Building GHC from source + +:octicons-beaker-24: Experimental + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +Stack supports building the GHC compiler from source, using +[Hadrian](https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/README.md) (the +build system for GHC). The GHC version to build and to use is defined by a a Git +commit ID and a Hadrian "flavour", with the following syntax: + +~~~yaml +compiler: ghc-git-<commit_id>-<Hadrian_flavour> +~~~ + +In the following example the commit ID is "5be7ad..." and the flavour is +"quick": + +~~~yaml +compiler: ghc-git-5be7ad7861c8d39f60b7101fd8d8e816ff50353a-quick +~~~ + +By default, the code is retrieved from the main GHC repository. If you want to +select another repository, use the `compiler-repository` option: + +~~~yaml +compiler-repository: git://my/ghc/repository +# default +# compiler-repository: https://gitlab.haskell.org/ghc/ghc.git +~~~ + +Stack does not check the compiler version when it uses a compiler built from +source. It is assumed that the built compiler is recent enough as Stack doesn't +enable any known workaround to make older compilers work. + +Building the compiler can take a very long time (more than one hour). For faster +build times, use Hadrian flavours that disable documentation generation. + +### Bootstrap compiler + +Building GHC from source requires a working GHC (known as the bootstrap +compiler). As we use a Stack based version of Hadrian (`hadrian/build-stack` in +GHC sources), the bootstrap compiler is configured into `hadrian/stack.yaml` and +fully managed by Stack. + +!!! note + + For some commit IDs, the snapshot specified in `hadrian/stack.yaml` + specifies a version of GHC that cannot be used to build GHC. This results in + GHC's `configure` script reporting messages similar to the following before + aborting: + + ~~~text + checking version of ghc... 9.0.2 + configure: error: GHC version 9.2 or later is required to compile GHC. + ~~~ + + The resolution is: (1) to specify an alternative snapshot (one that + specifies a sufficiently recent version of GHC) on the command line, using + Stack's option `--snapshot <snapshot>`. Stack will use that snapshot when + running GHC's `configure` script; and (2) to set the contents of the `STACK` + environment variable to be `stack --snapshot <snapshot>`. Hadrian's + `build-stack` script wil refer to that environment variable for the Stack + command it uses. + +### Hadrian prerequisites + +The Hadrian build system has certain +[prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation). +It requires certain versions of the `happy` and `alex` executables on the PATH. +Stack will build and install `happy` and `alex`, if not already on the PATH. + +=== "macOS" + + Hadrian requires, or case use, certain tools or Python packages that do not + come with macOS by default and that need to be installed using `brew` or + `pip3` (Python). Hadrian's LaTeX documentation also requires the + [DejaVu fonts](https://dejavu-fonts.github.io/) to be installed. + + ~~~zsh + brew install python@3.11 + # GHC uses a Python script named `boot`. + brew install automake + # Tool for generating GNU Standards-compliant Makefiles. + brew install texinfo + # Official documentation format of the GNU project. + pip3 install -U sphinx + # Sphinx is the Python documentation generator. + brew install --cask mactex + # MacTeX: Full TeX Live distribution with GUI applications + ~~~ + +=== "Windows" + + Hadrian requires, or can use, certain MSYS2 or Python packages that do not + come with the Stack-supplied MSYS2 by default and need to be installed + using `pacman` (MSYS2) or `pip` (Python). Hadrian's LaTeX documentation also + requires the [DejaVu fonts](https://dejavu-fonts.github.io/) to be + installed. + + ~~~pwsh + stack exec -- pacman --sync --refresh + # Synchronize MSYS2 package databases + stack exec -- pacman --sync mingw-w64-x86_64-python-pip + # The PyPA recommended tool (pip) for installing Python packages. Also + # installs Python as a dependency. GHC uses a Python script named `boot`. + # The package must be the one from the `mingw64` MSYS2 repository, as Python + # from the `msys` repository cannot interpret Windows file paths correctly. + stack exec -- pacman --sync mingw-w64-x86_64-autotools + # The GNU autotools build system, including `autoreconf`, `aclocal` + # and `make`. GHC uses a sh script named `configure` which is itself created + # from a file named `configure.ac`. + stack exec -- pacman --sync patch + # A utility to apply patch files to original sources. + stack exec -- pacman --sync texinfo + # Utilities to work with and produce manuals, ASCII text, and on-line + # documentation from a single source file, including `makeinfo`. + stack exec -- pacman --sync mingw-w64-x86_64-ca-certificates + # Common CA (certificate authority) certificates. + stack exec -- pip install -U sphinx + # Sphinx is the Python documentation generator. + ~~~ + + Hadrian may require certain LaTeX packages and may prompt for these to be + installed duing the build process. + +### Global packages + +The GHC compiler you build from sources may depend on unreleased versions of +some global packages (e.g. Cabal). It may be an issue if a package you try to +build with this compiler depends on such global packages because Stack may not +be able to find versions of those packages (on Hackage, etc.) that are +compatible with the compiler. + +The easiest way to deal with this issue is to drop the offending packages as +follows. Instead of using the packages specified in the snapshot, the global +packages bundled with GHC will be used. + +~~~yaml +drop-packages: +- Cabal +- ... +~~~ + +Another way to deal with this issue is to add the relevant packages as +`extra-deps` built from source. To avoid mismatching versions, you can use +exactly the same commit id you used to build GHC as follows: + +~~~ +extra-deps: +- git: https://gitlab.haskell.org/ghc/ghc.git + commit: '5be7ad7861c8d39f60b7101fd8d8e816ff50353a' + subdirs: + - libraries/Cabal/Cabal + - libraries/... +~~~ + +## compiler-check + +[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) + +Default: `match-minor` + +Specifies how the compiler version in the snapshot is matched against concrete +versions. Valid values: + +* `match-minor`: make sure that the first three components match, but allow + patch-level differences. For example< 7.8.4.1 and 7.8.4.2 would both match + 7.8.4. This is useful to allow for custom patch levels of a compiler. +* `match-exact`: the entire version number must match precisely +* `newer-minor`: the third component can be increased, e.g. if your snapshot is + `ghc-7.10.1`, then 7.10.2 will also be allowed. This was the default up + through Stack 0.1.3 + +## concurrent-tests + +[:octicons-tag-24: 0.1.2.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.2.0) + +Default: `true` + +This option specifies whether test suites should be executed concurrently with +each other. The default is `true` since this is usually fine and it often means +that tests can complete earlier. However, if some test suites require exclusive +access to some resource, or require a great deal of CPU or memory resources, +then it makes sense to set this to `false`. + +~~~yaml +concurrent-tests: false +~~~ + +## configure-options + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +Related command line (takes precedence): +[`stack build --PROG-option`](../../commands/build_command.md#prog-option-options) +options + +`configure-options` can specify Cabal (the library) options (including +`--PROG-option` or `--PROG-options` options) for the configure step of the Cabal +build process for a named package, all project packages that are targets (using +the `$targets` key), all project packages (targets or otherwise) (using the +`$locals` key), or all packages (project packages or otherwise) (using the +`$everything` key). + +~~~yaml +configure-options: + $everything: + - --with-gcc + - /some/path + $locals: + - --happy-option=--ghc + $targets: + # Only works on platforms where GHC supports linking against shared Haskell + # libraries: + - --enable-executable-dynamic + my-package: + - --another-flag +~~~ + +On platforms where GHC supports linking against shared Haskell libraries (that +currently excludes Windows), Cabal's `--enable-executable-dynamic` flag (which +implies `--enable-shared`, unless `--disable-shared` is specified) links +dependent Haskell libraries into executables dynamically. + +## connection-count + +Default: `8` + +Integer indicating how many simultaneous downloads are allowed to happen. + +### default-init-snapshot + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +Default: As for the [`stack init`](init_command.md) command when no snapshot is +specified at the command line. + +Command line equivalent (takes precedence): +[`--snapshot`](global_flags.md#snapshot-option) or +[`--resolver`](global_flags.md#resolver-option) option + +This option specifies which snapshot to use with `stack init`, when none is +specified at the command line. + +`default-init-snapshot: global` specifies the snapshot specified by the +project-level configuration file in the `global-project` directory in the +[Stack root](stack_root.md#global-project-directory). + +## default-template + +Default: `new-template` in the +[stack-templates](https://github.com/commercialhaskell/stack-templates/) +repository. + +This option specifies which template to use with `stack new`, when none is +specified. Other templates are listed in the +[stack-templates](https://github.com/commercialhaskell/stack-templates/) +repository. See the output of `stack templates`. + +## docker + +Command line equivalents: `--docker-*` flags and options (see +`stack --docker-help` for details). + +For further information, see the +[Docker integration](../../topics/docker_integration.md#configuration) +documentation. + +## dump-logs + +[:octicons-tag-24: 1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v1.3.0) + +Default: `warning` + +Command line equivalent (takes precedence): `--[no-]dump-logs` flag + +In the case of *non-interleaved* output and *more than one* target package, +Stack sends the build output from GHC for each target package to a log file, +unless an error occurs that prevents that. For further information, see the +[`stack build --[no-]interleaved-output` flag](../../commands/build_command.md#-no-interleaved-output-flag) +documentation. + +The value of the `dump-logs` key controls what, if any, log file content is sent +('dumped') to the standard error stream of the console at the end of the build. +Possible values are: + +~~~yaml +dump-logs: none # don't dump the content of any log files +dump-logs: warning # dump the content of any log files that include GHC warnings +dump-logs: all # dump the content of all log files +~~~ + +At the command line, `--no-dump-logs` is equivalent to `dump-logs: none` and +`--dump-logs` is equivalent to `dump-logs: all`. + +If GHC reports an error during the build and a log file is created, that build +output will be included in the log file. Stack will also report errors during +building to the standard error stream. That stream can be piped to a file. For +example, for a file named `stderr.log`: + +~~~text +stack --no-dump-logs --color always build --no-interleaved-output 2> stderr.log +~~~ + +## extra-include-dirs + +Default: `[]` + +Command line equivalent: `--extra-include-dirs` option (repeat for each +directory) + +A list of extra paths to be searched for header files. Paths should be absolute + +~~~yaml +extra-include-dirs: +- /opt/foo/include +~~~ + +Since these are system-dependent absolute paths, it is recommended that you +specify these in your `config.yaml` file. If you control the build environment +in your project's ``stack.yaml``, perhaps through docker or other means, then it +may well make sense to include these there as well. + +## extra-lib-dirs + +Default: `[]` + +Command line equivalent: `--extra-lib-dirs` option (repeat for each directory) + +A list of extra paths to be searched for libraries. Paths should be absolute + +~~~yaml +extra-lib-dirs: +- /opt/foo/lib +~~~ + +Since these are system-dependent absolute paths, it is recommended that you +specify these in your `config.yaml` file. If you control the build environment +in your project's ``stack.yaml``, perhaps through Docker or other means, then it +may well make sense to include these there as well. + +## extra-path + +[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) + +This option specifies additional directories to prepend to the PATH. These will +be used when resolving the location of executables, and will also be visible in +the PATH of processes run by Stack. + +For example, to prepend `/path-to-some-dep/bin` to your PATH: + +~~~yaml +extra-path: +- /path-to-some-dep/bin +~~~ + +Other paths added by Stack - things like the project's binary directory and the +compiler's binary directory - will take precedence over those specified here +(the automatic paths get prepended). + +## file-watch-hook + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +Specifies the location of an executable or `sh` shell script to be run after +each attempted build with +[`build --file-watch`](build_command.md#-file-watch-flag). An absolute or +relative path can be specified. Changes to the configuration after the +initial `build --file-watch` command are ignored. + +If the project-level configuration is provided in the `global-project` directory +in the [Stack root](stack_root.md), a relative path is assumed to be relative to +the current directory. Otherwise, it is assumed to be relative to the directory +of the project-level configuration file. + +## ghc-build + +[:octicons-tag-24: 1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v1.3.0) + +Default: `standard` + +Command line equivalent (takes precedence): `--ghc-build` option + +Stack identifies different GHC executables by platform (operating system and +machine architecture), (optional) GHC variant and (optional) GHC build. +See [`setup-info`](#setup-info). + +`ghc-build` specifies a specialized architecture for the GHC executable. +Normally this is determined automatically, but it can be overridden. Possible +arguments include `standard`, `gmp4`, `nopie`, `tinfo6`, `tinfo6-libc6-pre232`, +`tinfo6-nopie`, `ncurses6`, `int-native` and `integersimple`. + +## ghc-options + +[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) + +Default: `{}` + +Related command line (takes precedence): +[`stack build --ghc-options`](../../commands/build_command.md#-ghc-options-option) +option + +GHC command line options can be specified for a package in its Cabal file +(including one created from a `package.yaml` file). This option augments and, if +applicable (see below), overrides any such GHC command line options. + +`ghc-options` can specify GHC command line options for a named package, all +project packages that are targets (using the `$targets` key), all project +packages (targets or otherwise) (using the `$locals` key), or all packages +(project packages or otherwise) (using the `$everything` key). + +~~~yaml +ghc-options: + "$everything": -O2 + "$locals": -Wall + "$targets": -Werror + some-package: -DSOME_CPP_FLAG +~~~ + +GHC's command line options are _order-dependent_ and evaluated from left to +right. Later options can override the effect of earlier ones. Stack applies +options (as applicable) in the order of `$everything`, `$locals`, `$targets`, +and then those for the named package. Any GHC command line options for a package +specified at Stack's command line are applied after those specified in Stack's +configuration files. + +Since Stack 1.6.1, setting a GHC options for a specific package will +automatically promote it to a project package (much like setting a custom +package flag). However, setting options via `$everything` on all flags will not +do so (see +[GitHub discussion](https://github.com/commercialhaskell/stack/issues/849#issuecomment-320892095) +for reasoning). This can lead to unpredictable behavior by affecting your +snapshot packages. + +!!! info + + Before Stack 1.6.1, the key `*` (then deprecated) had the same function as + the key `$everything`. + +## ghc-variant + +[:octicons-tag-24: 0.1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.5.0) + +Default: `standard` + +Command line equivalent (takes precedence): `--ghc-variant` option + +Stack identifies different GHC executables by platform (operating system and +machine architecture), (optional) GHC variant and (optional) GHC build. +See [`setup-info`](#setup-info). + +`ghc-variant` specifies a variant of the GHC executable. Known values are: + +* `standard`: Use the standard GHC binary distribution +* `int-native`: From GHC 9.4.1, use a GHC bindist that uses the Haskell-native + big-integer + [backend](https://downloads.haskell.org/~ghc/9.0.2/docs/html/users_guide/9.0.1-notes.html#highlights). + For further information, see this [article](https://iohk.io/en/blog/posts/2020/07/28/improving-haskells-big-numbers-support/). +* `integersimple`: Use a GHC bindist that uses + [integer-simple instead of GMP](https://ghc.haskell.org/trac/ghc/wiki/ReplacingGMPNotes) +* any other value: Use a custom GHC bindist. You should specify + [setup-info](#setup-info) or [setup-info-locations](#setup-info-locations) + so `stack setup` knows where to download it, + or pass the `stack setup --ghc-bindist` argument on the command-line + +This option is incompatible with `system-ghc: true`. + +## global-hints-location + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +Default: + +~~~yaml +global-hints-location: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-content/master/stack/global-hints.yaml +~~~ + +(as set in the `pantry` library) + +Sets the location of the global hints YAML file. The location can be either a +filepath of a local file or a URL. The filepath can be absolute or relative to +the Stack root. + +For example: + +~~~yaml +global-hints-location: + filepath: \pantry\global-hints.yaml +~~~ + +or: + +~~~yaml +global-hints-location: + url: https://example.com/global-hints/location/global-hints.yaml +~~~ + +## hackage-base-url + +[:octicons-tag-24: 1.9.1](https://github.com/commercialhaskell/stack/releases/tag/v1.9.1) + +Default: `https://hackage.haskell.org/` + +Sets the address of the Hackage server to upload the package to. + +~~~yaml +hackage-base-url: https://hackage.example.com/ +~~~ + +## hide-source-paths + +Default: `true` +([:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1)) + +Whether to use the `-fhide-source-paths` option by default for GHC >= 8.2: + +~~~yaml +hide-source-paths: false +~~~ + +Build output when enabled: + +~~~text +... +[1 of 2] Compiling Lib +[2 of 2] Compiling Paths_test_pr +... +~~~ + +Build output when disabled: + +~~~text +... +[1 of 2] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/Lib.o ) +... +~~~ + +## hide-th-loading + +Default: `true` + +Strip out the "Loading ..." lines from GHC build output, produced when using +Template Haskell. + +## hpack-force + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +Default: `false` + +Command line equivalent (takes precedence): +[`--hpack-force` option](global_flags.md#-no-hpack-force-flag) + +Whether or not to allow Hpack to overwrite a Cabal file that has been modified +manually. By default, Hpack 0.20.0 or later will decline to overwrite such a +Cabal file. + +## ignore-revision-mismatch + +(Removed 1.11) + +This flag was introduced in Stack 1.6, and removed on the move to Pantry. You +will receive a warning if this configuration value is set. + +## install-ghc + +Default: `true` +([:octicons-tag-24: 1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v1.5.0)) + +Command line equivalent (takes precedence): `--[no-]install-ghc` flag + +Whether or not to automatically install GHC when necessary. + +## jobs + +Default: the number of CPUs (cores) that the machine has. + +Command line equivalent (takes precedence): +[`-j`, `--jobs` option](../global_flags.md#-jobs-or-j-option) + +Specifies the number of concurrent jobs (principally, Stack actions during +building - see further below) to run. + +When [building GHC from source](#building-ghc-from-source), specifies the +`-j[<n>]` flag of GHC's Hadrian build system. + +In some circumstances, the default can cause some machines to run out of memory +during building. If those circumstances arise, specify `jobs: 1`. + +This configuration option is distinct from GHC's own `-j[<n>]` flag, which +relates to parallel compilation of modules within a package. + +## local-bin-path + +Default (on Unix-like operating systems): `~/.local/bin` + +Default (on Windows): `%APPDATA%\local\bin` + +Command line equivalent (takes precedence): `--local-bin-path` option + +Specifies the target directory for +[`stack build --copy-bins`](../../commands/build_command.md#-no-copy-bins-flag) +and `stack install`. An absolute or relative path can be specified. + +If the project-level configuration is provided in the `global-project` directory +in the [Stack root](../../topics/stack_root.md), a relative path is assumed to +be relative to the current directory. Otherwise, it is assumed to be relative to +the directory of the project-level configuration file. + +## local-programs-path + +[:octicons-tag-24: 1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v1.3.0) + +This overrides the location of the Stack 'programs' directory, where tools like +GHC get installed. The path must be an absolute one. + +Stack's defaults differ between Unix-like operating systems and Windows. + +=== "Unix-like" + + Default: `programs` directory in the + [Stack root](../../topics/stack_root.md). + +=== "Windows" + + Default: `%LOCALAPPDATA%\Programs\stack`, if the `%LOCALAPPDATA%` + environment variable exists. Otherwise, the `programs` directory in the + [Stack root](../../topics/stack_root.md). + + The MSYS2 tool is also installed in the Stack 'programs' directory. + + !!! warning + + If there is a space character in the path to Stack's 'programs' + directory this may cause problems with building packages that make use + of the GNU project's `autoconf` package and `configure` shell script + files. That may be the case particularly if there is no corresponding + short name ('8 dot 3' name) for the directory in the path with the space + (which may be the case if '8 dot 3' names have been stripped or their + creation not enabled by default). If there are problems building, it + will be necessary to specify an alternative path that does not contain + space characters. Examples of packages on Hackage that make use of + `configure` are `network` and `process`. + +## modify-code-page + +[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) + +Restrictions: Windows systems only. + +Default: `true` + +Command line equivalent (takes precedence): `--[no-]modify-code-page` flag + +Whether to modify the code page for UTF-8 output. + +~~~yaml +modify-code-page: false +~~~ + +## msys-environment + +[:octicons-tag-24: 3.1.1](https://github.com/commercialhaskell/stack/releases/tag/v3.1.1) + +Restrictions: Windows systems only. + +Default: `MINGW64` (64-bit Windows) or `MINGW32` (32-bit Windows) + +The name of the MSYS2 environment (case-sensitive) used in the Stack +environment. Valid environments are `CLANG32`, `CLANG64`, `CLANGARM64`, +`MINGW32`, `MINGW64`, and `UCRT64`. + +## nix + +[:octicons-tag-24: 0.1.10.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.10.0) + +Default: + +~~~yaml +nix: + enable: false # Except on NixOS, where `enable: true` + pure: true + packages: [] + shell-file: + nix-shell-options: [] + path: [] + add-gc-roots: false +~~~ + +Command line equivalents: `--nix-*` flags and options (see `stack --nix-help` +for details). + +For further information, see the +[Nix integration](../../topics/nix_integration.md#configuration) documentation. + +## notify-if-arch-unknown + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +Default: `true` + +If the specified machine architecture value is unknown to Cabal (the library), +should Stack notify the user of that? + +## notify-if-cabal-untested + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +Default: `true` + +If Stack has not been tested with the version of Cabal (the library) that has +been found, should Stack notify the user of that? + +## notify-if-ghc-untested + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +Default: `true` + +If Stack has not been tested with the version of GHC that is being used, should +Stack notify the user of that? + +## notify-if-nix-on-path + +[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) + +Default: `true` + +If Stack's integration with the Nix package manager is not enabled, should Stack +notify the user if a `nix` executable is on the PATH? + +## package-index + +[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) + +Default: + +~~~yaml +package-index: + download-prefix: https://hackage.haskell.org/ + hackage-security: + keyids: + - 0a5c7ea47cd1b15f01f5f51a33adda7e655bc0f0b0615baa8e271f4c3351e21d + - 1ea9ba32c526d1cc91ab5e5bd364ec5e9e8cb67179a471872f6e26f0ae773d42 + - 2c6c3627bd6c982990239487f1abd02e08a02e6cf16edb105a8012d444d870c3 + - 51f0161b906011b52c6613376b1ae937670da69322113a246a09f807c62f6921 + - fe331502606802feac15e514d9b9ea83fee8b6ffef71335479a2e68d84adc6b0 + key-threshold: 3 + ignore-expiry: true +~~~ + +Specify the package index. The index must use the +[Hackage Security](https://hackage.haskell.org/package/hackage-security) format. +This setting is most useful for providing a mirror of the official Hackage +server for + +* bypassing a firewall; or +* faster downloads. + +If the setting specifies an index that does not mirror Hackage, it is likely +that will result in significant breakage, including most snapshots failing to +work. + +In the case of Hackage, the keys of its root key holders are contained in the +`haskell-infra/hackage-root-keys` +[repository](https://github.com/haskell-infra/hackage-root-keys). The Hackage +package index is signed. A signature is valid when three key holders have +signed. The Hackage timestamp is also signed. A signature is valid when one key +holder has signed. + +If the `hackage-security` key is absent, the Hackage Security configuration will +default to that for the official Hackage server. + +`key-threshold` specifies the minimum number of keyholders that must have signed +the package index for it to be considered valid. + +`ignore-expiry` specifies whether or not the expiration of timestamps should be +ignored. + +!!! info + + Before Stack 2.1.3, the default for `ignore-expiry` was `false`. For more + information, see + [issue #4928](https://github.com/commercialhaskell/stack/issues/4928). + +## pvp-bounds + +[:octicons-tag-24: 0.1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.5.0) + +Default: `none` + +Command line equivalent (takes precedence): `stack sdist --pvp-bounds` option or +`stack upload --pvp-bounds` option + +!!! warning + + As of Stack 1.6.0, this feature does not reliably work, due to issues with + the Cabal library's printer. Stack will generate a warning when a lossy + conversion occurs, in which case you may need to disable this setting. For + further information, see issue + [#3550](https://github.com/commercialhaskell/stack/issues/3550). + +When using the `sdist` and `upload` commands, this setting determines whether +the Cabal file's dependencies should be modified to reflect PVP lower and upper +bounds. + +### Basic use + +Values are `none` (unchanged), `upper` (add upper bounds), `lower` (add +lower bounds), and both (and upper and lower bounds). The algorithm Stack +follows is: + +* If an upper or lower bound (other than `>= 0` - 'any version') already exists + on a dependency, it is left alone +* When adding a lower bound, Stack looks at the current version specified by + `stack.yaml`, and sets it as the lower bound (e.g., `foo >= 1.2.3`) +* When adding an upper bound, Stack sets it as less than the next major version + (e.g., `foo < 1.3`) + +~~~yaml +pvp-bounds: none +~~~ + +For further information, see the announcement +[blog post](https://www.fpcomplete.com/blog/2015/09/stack-pvp). + +### Use with Cabal file revisions + +[:octicons-tag-24: 1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v1.5.0) + +Each of the values listed above supports adding `-revision` to the end of the +value, e.g. `pvp-bounds: both-revision`. This means that, when uploading to +Hackage, Stack will first upload your tarball with an unmodified Cabal file, and +then upload a Cabal file revision with the PVP bounds added. + +This can be useful - especially combined with the +[Stackage no-revisions feature](http://www.snoyman.com/blog/2017/04/stackages-no-revisions-field) - +as a method to ensure PVP compliance without having to proactively fix bounds +issues for Stackage maintenance. + +## recommend-stack-upgrade + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +Default: `true` + +When Stack notices that a new version of Stack is available, should it notify +the user? + +## rebuild-ghc-options + +[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) + +Default: `false` + +Should Stack rebuild a package when its GHC options change? + +The default value reflects that, in most cases, GHC options are used to affect +optimization levels and warning behavior, for which GHC does not recompile the +modules. + +!!! info + + Before Stack 0.1.6.0, Stack rebuilt a package when its GHC options changed. + +## require-stack-version + +Default: `"-any"` + +Require a version of Stack within the specified range +([cabal-style](https://www.haskell.org/cabal/users-guide/developing-packages.html#build-information)) +to be used for this project. Example: `require-stack-version: "== 0.1.*"` + +## save-hackage-creds + +[:octicons-tag-24: 1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v1.5.0) + +Default: `true` + +Command line equivalent (takes precedence): +[`stack upload --[no]-save-hackage-creds`](upload_command.md) option + +Controls whether, when using `stack upload`, the user's Hackage username and +password are stored in a local file. + +~~~yaml +save-hackage-creds: true +~~~ + +## setup-info + +[:octicons-tag-24: 0.1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.5.0) + +The `setup-info` dictionary specifies download locations for tools to be +installed during set-up, such as GHC or, on Windows, 7z and MSYS2. The +dictionary maps `('Tool', 'Platform', 'Version')` to the location where it can +be obtained. For example, mapping `(GHC, 64-bit Windows, 9.2.3)` to the URL +hosting the archive file for GHC's installation. + +Possible usages of this configuration option are: + +1. Using Stack offline or behind a firewall. +2. Extending the tools known to Stack, such as cutting-edge versions of GHC or + builds for custom Linux distributions (for use with the + [ghc-variant](#ghc-variant) option). + +By default, Stack obtains the dictionary from +[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml). + +The `setup-info` dictionary is constructed in the following order: + +1. `setup-info` in the configuration - inline configuration +2. `--setup-info-yaml` command line arguments - URLs or paths. Multiple + locations may be specified. +3. `setup-info-locations` in the configuration - URLs or paths. See further + below. + +The format of this key is the same as in the default +[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml). +For example, GHC 9.2.3 of custom variant `myvariant` (see further below) on +64-bit Windows: + +~~~yaml +setup-info: + ghc: + windows64-custom-myvariant: + 9.2.3: + url: "https://example.com/ghc-9.2.3-x86_64-unknown-mingw32-myvariant.tar.xz" +~~~ + +'Platforms' are pairs of an operating system and a machine architecture (for +example, 32-bit i386 or 64-bit x86-64) (represented by the +`Cabal.Distribution.Systems.Platform` type). Stack currently (version 2.15.1) +supports the following pairs in the format of the `setup-info` key: + +|Operating system|I386 arch|X86_64 arch|Other machine architectures | +|----------------|---------|-----------|------------------------------------------------------------| +|Linux |linux32 |linux64 |AArch64: linux-aarch64, Arm: linux-armv7, Sparc: linux-sparc| +|OSX |macosx |macosx | | +|Windows |windows32|windows64 | | +|FreeBSD |freebsd32|freebsd64 |AArch64: freebsd-aarch64 | +|OpenBSD |openbsd32|openbsd64 | | + +For GHC, the distinguishing 'Version' in the key format includes a 'tag' for +any (optional) GHC variant (see [ghc-variant](#ghc-variant)) and a further 'tag' +for any (optional) specialised GHC build (see [ghc-build](#ghc-build)). + +The optional variant 'tag' is either `-integersimple` or +`-custom-<custom_variant_name>`. + +For example, for GHC 9.0.2 of specialised GHC build `tinfo6` on x86_64 Linux: +~~~yaml +setup-info: + ghc: + linux64-tinfo6: + 9.0.2: + url: "http://downloads.haskell.org/~ghc/9.0.2/ghc-9.0.2a-x86_64-fedora27-linux.tar.xz" + content-length: 237286244 + sha1: affc2aaa3e6a1c446698a884f56a0a13e57f00b4 + sha256: b2670e9f278e10355b0475c2cc3b8842490f1bca3c70c306f104aa60caff37b0 +~~~ + +On Windows, the required 7z executable and DLL tools are represented in the +format of the `setup-info` key simply by `sevenzexe-info` and `sevenzdll-info`. + +This configuration **adds** the specified setup information metadata to the +default. Specifying this configuration **does not** prevent the default +[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml) +from being consulted as a fallback. If, however, you need to **replace** the +default `setup-info` dictionary, use the following: + +~~~yaml +setup-info-locations: [] +~~~ + +## setup-info-locations + +[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) + +Command line equivalent (takes precedence): `--setup-info-yaml` option + +By way of introduction, see the [`setup-info`](#setup-info) option. This option +specifies the location(s) of `setup-info` dictionaries. + +The first location which provides a dictionary that specifies the location of a +tool - `('Tool', 'Platform', 'Version')` - takes precedence. For example, you +can extend the default tools, with a fallback to the default `setup-info` +location, as follows: + +~~~yaml +setup-info-locations: +- C:/stack-offline/my-stack-setup.yaml +- relative/inside/my/project/setup-info.yaml +- \\smbShare\stack\my-stack-setup.yaml +- http://stack-mirror.com/stack-setup.yaml +# Fallback to the default location +- https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml +~~~ + +Stack only refers to the default `setup-info` location if no locations are +specified in the `setup-info-locations` configuration or on the command line +using the `--setup-info-yaml` option. + +For example, both of the following will cause `stack setup` not to consult the +default `setup-info` location: + +~~~yaml +setup-info-locations: +- C:/stack-offline/my-stack-setup.yaml +~~~ + +and + +~~~yaml +setup-info-locations: [] +~~~ + +Relative paths are resolved relative to the `stack.yaml` file (either the one in +the local project or the global `stack.yaml`). + +Relative paths may also be used for the installation paths to tools (such as GHC +or 7z). This allows vendoring the tools inside a monorepo (a single repository +storing many projects). For example: + +Directory structure: + +~~~text +- src/ +- installs/ + - my-stack-setup.yaml + - 7z.exe + - 7z.dll + - ghc-9.2.3.tar.xz +- stack.yaml +~~~ + +In the project's `stack.yaml`: + +~~~yaml +setup-info-locations: +- installs/my-stack-setup.yaml +~~~ + +In `installs/my-stack-setup.yaml`: + +~~~yaml +sevenzexe-info: + url: "installs/7z.exe" + +sevenzdll-info: + url: "installs/7z.dll" + +ghc: + windows64: + 9.2.3: + url: "installs/ghc-9.2.3.tar.xz" +~~~ + +## skip-ghc-check + +Default: `false` + +Command line equivalent (takes precedence): `--[no-]skip-ghc-check` flag + +Should we skip the check to confirm that your system GHC version (on the PATH) +matches what your project expects? + +## skip-msys + +[:octicons-tag-24: 0.1.2.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.2.0) + +Restrictions: Windows systems only + +Default: `false` + +Command line equivalent (takes precedence): +[`--[no-]skip-msys`](../global_flags.md#-no-skip-msys-option) flag + +Skips checking for the Stack-supplied MSYS2 (and installing that MSYS2, if it is +not installed) when Stack is setting up the environment. + +~~~yaml +skip-msys: true +~~~ + +!!! note + + Usually, the use of this option does not make sense in project-level + configuration and it is used only in global configuration. + +## snapshot-location-base + +[:octicons-tag-24: 2.5.1](https://github.com/commercialhaskell/stack/releases/tag/v2.5.1) + +Default: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/ +(as set in the `pantry` library) + +Command line equivalent (takes precedence): `--snapshot-location-base` option + +Sets the base location of the LTS Haskell or Stackage Nightly snapshots. + +For example: + +~~~yaml +snapshot-location-base: https://example.com/snapshots/location/ +~~~ + +has the following effect: + +* `lts-X.Y` expands to `https://example.com/snapshots/location/lts/X/Y.yaml` +* `nightly-YYYY-MM-DD` expands to + `https://example.com/snapshots/location/nightly/YYYY/M/D.yaml` + +This key is convenient in setups that restrict access to GitHub, for instance +closed corporate setups. In this setting, it is common for the development +environment to have general access to the internet, but not for testing/building +environments. To avoid the firewall, one can run a local snapshots mirror and +then use a custom `snapshot-location-base` in the closed environments only. + +## stack-colors + +Command line equivalent (takes precedence): `--stack-colors` option + +Stack uses styles to format some of its output. The default styles do not work +well with every terminal theme. This option specifies Stack's output styles, +allowing new styles to replace the defaults. The option is used as +`stack-colors: <STYLES>`, where `<STYLES>` is a colon-delimited sequence of +key=value, 'key' is a style name and 'value' is a semicolon-delimited list of +'ANSI' SGR (Select Graphic Rendition) control codes (in decimal). Use the +command `stack ls stack-colors --basic` to see the current sequence. + +The 'ANSI' standards refer to (1) standard ECMA-48 'Control Functions for Coded +Character Sets' (5th edition, 1991); (2) extensions in ITU-T Recommendation +(previously CCITT Recommendation) T.416 (03/93) 'Information Technology – Open +Document Architecture (ODA) and Interchange Format: Character Content +Architectures' (also published as ISO/IEC International Standard 8613-6); and +(3) further extensions used by 'XTerm', a terminal emulator for the X Window +System. The 'ANSI' SGR codes are described in a +[Wikipedia article](http://en.wikipedia.org/wiki/ANSI_escape_code) +and those codes supported on current versions of Windows in +[Microsoft's documentation](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences). + +For example, users of the popular +[Solarized Dark](https://ethanschoonover.com/solarized/) +terminal theme might wish to set the styles as follows: + +~~~yaml +stack-colors: error=31:good=32:shell=35:dir=34:recommendation=32:target=95:module=35:package-component=95:secondary=92:highlight=32 +~~~ +In respect of styles used in verbose output, some of that output occurs before +the configuration file is processed. + +(The British English spelling (colour) is also accepted. In configuration files, +the American spelling is the alternative that has priority.) + +## stack-developer-mode + +[:octicons-tag-24: 2.3.3](https://github.com/commercialhaskell/stack/releases/tag/v2.3.3) + +Default (official distributed binaries): `false` + +Default (built from source): `true` + +Turns on a mode where some messages are printed at WARN level instead of DEBUG +level, especially useful for developers of Stack itself. + +~~~yaml +stack-developer-mode: false +~~~ + +## system-ghc + +Default: `false`, unless the [Docker](../../topics/docker_integration.md) or +[Nix](../../topics/nix_integration.md) integration is enabled. + +Command line equivalent (takes precedence): `--[no-]system-ghc` flag + +Enables or disables using the GHC available on the PATH. (Make sure PATH is +explicit, i.e., don't use ~.) Useful to enable if you want to save the time, +bandwidth or storage space needed to setup an isolated GHC. + +In a Nix-enabled configuration, Stack is incompatible with `system-ghc: false`. + +~~~yaml +# Turn on system GHC +system-ghc: true +~~~ + +## templates + +Command line equivalent (takes precedence): `stack new --param <key>:<value>` +(or `-p`) option + +Templates used with `stack new` have a number of parameters that affect the +generated code. These can be set for all new projects you create. The result of +them can be observed in the generated LICENSE and Cabal files. The value for all +of these parameters must be strings. + +The parameters are: `author-email`, `author-name`, `category`, `copyright`, +`year` and `github-username`. + +* _author-email_ - sets the `maintainer` property in Cabal +* _author-name_ - sets the `author` property in Cabal and the name used in + LICENSE +* _category_ - sets the `category` property in Cabal. This is used in Hackage. + For examples of categories see + [Packages by category](https://hackage.haskell.org/packages/). It makes sense + for `category` to be set on a per project basis because it is uncommon for all + projects a user creates to belong to the same category. The category can be + set per project by passing `-p "category:value"` to the `stack new` command. +* _copyright_ - sets the `copyright` property in Cabal. It is typically the + name of the holder of the copyright on the package and the year(s) from which + copyright is claimed. For example: `Copyright (c) 2023-2024 Joe Bloggs` +* _year_ - if `copyright` is not specified, `year` and `author-name` are used + to generate the copyright property in Cabal. If `year` is not specified, it + defaults to the current year. +* _github-username_ - used to generate `homepage` and `source-repository` in + Cabal. For instance `github-username: myusername` and + `stack new my-project new-template` would result: + +~~~yaml +homepage: http://github.com/myusername/my-project#readme + +source-repository head + type: git + location: https://github.com/myusername/my-project +~~~ + +These properties can be set in `config.yaml` as follows: +~~~yaml +templates: + params: + author-name: Your Name + author-email: youremail@example.com + category: Your Projects Category + copyright: 'Copyright (c) 2024 Your Name' + github-username: yourusername +~~~ + +Additionally, `stack new` can automatically initialize source control +repositories in the directories it creates. Source control tools can be +specified with the `scm-init` option. At the moment, only `git` is supported. + +~~~yaml +templates: + scm-init: git +~~~ + +## urls + +Default: + +~~~yaml +urls: + latest-snapshot: https://stackage-haddock.haskell.org/snapshots.json +~~~ + +Customize the URLs where Stack looks for snapshot build plans. + +!!! note + + The default for Stack 1.3.0 to 2.15.3 was + https://s3.amazonaws.com/haddock.stackage.org/snapshots.json. Following the + handover of the Stackage project to the Haskell Foundation in + early 2024, the file at that URL may not be up to date. Users of those + versions of Stack should configure the URL to be the default above. + +## with-gcc + +Command line equivalent (takes precedence): `--with-gcc` option + +Specify a path to GCC explicitly, rather than relying on the normal path +resolution. + +~~~yaml +with-gcc: /usr/local/bin/gcc-5 +~~~ + +## with-hpack + +Command line equivalent (takes precedence): `--with-hpack` option + +Use an [Hpack](https://github.com/sol/hpack) executable, rather than Stack's +in-built version of the Hpack functionality. + +~~~yaml +with-hpack: /usr/local/bin/hpack +~~~ + +## work-dir + +[:octicons-tag-24: 0.1.10.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.10.0) + +Default: `.stack-work` + +Command line equivalent (takes precedence): +[`--work-dir`](../global_flags.md#-work-dir-option) option + +Environment variable alternative (lowest precedence): +[`STACK_WORK`](../environment_variables.md#stack_work) + +`work-dir` specifies the path of Stack's work directory, within a local project +or package directory. The path must be a relative one, relative to the +root directory of the project or package. The relative path cannot include a +`..` (parent directory) component.
+ doc/configure/yaml/project.md view
@@ -0,0 +1,455 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Project-specific configuration + +Project-specific configuration options are valid only in a project-level +configuration file (`stack.yaml`, by default). + +Each of the Haskell packages to which a Stack project relates is either a +**project package** that is part of the project and located locally or a package +on which one or more of the project packages depends (directly or indirectly). +The latter is referred to as a **dependency** and it may be located locally or +elsewhere. + +!!! info + + Project packages are built by default. Dependencies are only built when + needed. Building can target individual components of a project package. The + individual components of dependencies cannot be targeted. Test suite and + benchmark components of a project package can be built and run. The library + and executable components of a dependency, and only those components, are + built when the dependency is needed. + +In your project-specific options, you specify both **which project packages** to +build and **which dependencies to use** when building these packages. + +A dependency specified as an [extra-dep](#extra-deps) will shadow a package of +the same name specified in a [snapshot](#snapshot). A project package will +shadow a dependency of the same name. + +## snapshot + +Command line equivalent (takes precedence): +[`--snapshot`](../global_flags.md#snapshot-option) or +[`--resolver`](../global_flags.md#resolver-option) option + +The `snapshot` key specifies which snapshot is to be used for this project. A +snapshot defines a GHC version, the package version of packages available for +installation, and various settings like build flags. It is also called a +resolver since a snapshot states how dependencies are resolved. There are +currently four snapshot types: + +* LTS Haskell snapshots, e.g. `snapshot: lts-22.21` +* Stackage Nightly snapshots, e.g. `snapshot: nightly-2024-05-06` +* No snapshot, just use packages shipped with the compiler. For GHC this looks + like `snapshot: ghc-9.6.5` +* Custom snapshot, via a URL or relative file path. For further information, see + the [snapshot location](../../topics/snapshot_location.md) documentation. + +Each of these snapshots will also determine what constraints are placed on the +compiler version. See the [compiler-check](non-project.md#compiler-check) option +for some additional control over compiler version. + +A package version specified in a snapshot can be shadowed by an +[extra-dep](#extra-deps) of the same name or a [project package](#packages) of +the same name. + +## resolver + +`resolver` and [`snapshot`](#snapshot) are synonyms. Only one of these keys is +permitted, not both. + +## packages + +Default: + +~~~yaml +packages: +- . +~~~ + +The `packages` key specifies a list of the project packages that are part of +your project. These are specified via paths to local directories. A path is +considered relative to the directory containing the project-level configuration +file (`stack.yaml`, by default). For example, if the `stack.yaml` file is +located at `/dir1/dir2/stack.yaml`, and has: + +~~~yaml +packages: +- my-package +- dir3/my-other-package +~~~ + +the configuration means "project packages in directories `/dir1/dir2/my-package` +and `/dir1/dir2/dir3/my-other-package`". + +The `packages` key is optional. The default value, '`.`', means that the +project has a single project package located in the current directory. + +A project package will shaddow a dependency of the same name. + +A package version specified in a snapshot can be shadowed by an +[extra-dep](#extra-deps) of the same name or a [project package](#packages) of +the same name. + +Each specified project package directory must have a valid Cabal file or Hpack +`package.yaml` file present. Any subdirectories of the directory are not +searched for Cabal files. A subdirectory has to be specified as an independent +item in the list of project packages. + +A project package is different from a dependency (located locally or elsewhere) +specified as an [extra-dep](#extra-deps) or via a [snapshot](#snapshot). For +example: + +* a project package will be built by default by commanding + [`stack build`](../../commands/build_command.md) without specific targets. A + dependency will only be built if it is needed; and +* test suites and benchmarks may be built and run for a project package. They + are never run for a dependency. + +## extra-deps + +Default: `[]` + +The `extra-deps` key specifies a list of extra dependencies on top of what is +defined in the [snapshot](#snapshot). A dependency may come from either a Pantry +package location or a local file path. + +A Pantry package location is one or three different kinds of sources: + +* the package index (Hackage); +* an archive (a tarball or zip file, either local or over HTTP or HTTPS); or +* a Git or Mercurial repository. + +For further information on the format for specifying a Pantry package location, +see the [package location](../../topics/package_location.md) documentation. For +example: + +~~~yaml +extra-deps: +# The latest revision of a package in the package index (Hackage): +- acme-missiles-0.3 +# A specific revision of a package in the package index (Hackage): +- acme-missiles-0.3@rev:0 +# An *.tar.gz archive file over HTTPS: +- url: https://github.com/example-user/my-repo/archive/08c9b4cdf977d5bcd1baba046a007940c1940758.tar.gz + subdirs: + - my-package +# A Git repository at a specific commit: +- git: https://github.com/example-user/my-repo.git + commit: '08c9b4cdf977d5bcd1baba046a007940c1940758' +# An archive of files at a point in the history of a GitHub repository +# (identified by a specific commit): +- github: example-user/my-repo + commit: '08c9b4cdf977d5bcd1baba046a007940c1940758' + subdirs: + - my-package +~~~ + +!!! note + + GHC boot packages are special. An extra-dep with the same package name and + version as a GHC boot package will be ignored. + +!!! note + + The `commit:` key expects a YAML string. A commit hash, or partial hash, + comprised only of digits represents a YAML number, unless it is enclosed in + quotation marks. + +For a local file path source, the path is considered relative to the directory +containing the `stack.yaml` file. For example, if the `stack.yaml` is located +at `/dir1/dir2/stack.yaml`, and has: + +~~~yaml +extra-deps: +- my-package +- dir3/my-other-package +~~~ + +the configuration means "extra-deps packages in directories +`/dir1/dir2/my-package` and `/dir1/dir2/dir3/my-other-package`". + +!!! note + + A local file path that has the format of a package identifier will be + interpreted as a reference to a package on Hackage. Prefix it with `./` to + avoid that confusion. + +!!! note + + A specified extra-dep that does not have the format of a valid Pantry + package location (for example, a reference to a package on Hackage that + omits the package's version) will be interpreted as a local file path. + +An extra-dep will shadow a dependency specified in a [snapshot](#snapshot) of +the same name. An extra-dep can be shadowed by a [project package](#packages) of +the same name. + +!!! info + + Some Haskell packages published on Hackage, for example `base` and `ghc`, + are referred to as 'wired-in' to one or more versions of GHC or as 'magic'. + They can be distinguished from normal packages by the contents of their + Cabal files: GHC's `-this-unit-id` option is set as the name of the package + without a version. For example, the `base.cabal` for `base-4.19.1.0` + includes: + + ~~~yaml + -- We need to set the unit id to base (without a version number) + -- as it's magic. + ghc-options: -this-unit-id base + ~~~ + + The GHC boot packages that are 'wired-in' cannot be shaddowed with different + versions of the same package. Given their dependencies, the use of these + boot packages in a build plan may limit what can be specified as an + extra-dep. + + For example, GHC boot package `ghc-9.8.2` has a dependency on `process`. Its + `*.conf` file identifies the dependency as `process-1.6.18.0-4fb7`. If + package `ghc-9.8.2` is part of a build plan and a different version of + `process` is specified as an extra-dep, during a build, Stack will identify + that the build plan refers to two versions of `process` and warn that the + build is likely to fail. + + Stack treats the following as the names of 'wired-in' packages: `base`, + `dph-par`, `dph-seq`, `ghc-bignum`, `ghc-prim`, `ghc`, `integer-gmp`, + `integer-simple`, `interactive`, `rts` and `template-haskell`. + +## flags + +Default: `{}` + +Command line equivalent (takes precedence): +[`stack build --flag`](../../commands/build_command.md#-flag-option) option + +Cabal flags can be set for each package separately. For example: + +~~~yaml +flags: + package-name: + flag-name: true +~~~ + +This overrides all Cabal flag specifications (if any) for the specified packages +in the snapshot. + +!!! note + + For a package included directly in the snapshot, if the Cabal flag + specifications differ from the Cabal flag specifications (if any) in the + snapshot, then the package will automatically be promoted to be an + [extra-dep](#extra-deps). + +!!! note + + In order to set a Cabal flag for a GHC boot package, the package must be + specified as an [extra-dep](#extra-deps). + +## drop-packages + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +Default: `[]` + +Packages which, when present in the snapshot specified in the +[`snapshot`](#snapshot) or [`resolver`](#resolver) key, should not be included +in our project. This can be used for a few different purposes, e.g.: + +* Ensure that packages you don't want used in your project cannot be used in a + `package.yaml` file (e.g., for license reasons) +* When using a custom GHC build, avoid incompatible packages (see this + [comment](https://github.com/commercialhaskell/stack/pull/4655#issuecomment-477954429)). + +~~~yaml +drop-packages: +- buggy-package +- package-with-unacceptable-license +~~~ + +!!! info + + Stackage snapshots LTS Haskell 14.27 (GHC 8.6.5) and earlier, and Nightly + 2022-02-08 (GHC 8.8.2) and earlier, included directly the `Cabal` package. + Later snapshots do not include directly that package (which is a GHC boot + package). + + For the older Stackage snapshots, it could be handy to drop the + snapshot-specified `Cabal` package, to avoid building that version of the + package. For the later snapshots, there is no package version to drop. + +## user-message + +If present, specifies a message to be displayed every time the configuration is +loaded by Stack. It can serve as a reminder for the user to review the +configuration and make any changes if needed. The user can delete this message +if the generated configuration is acceptable. + +For example, a user-message is inserted by `stack init` when it omits packages +or adds external dependencies, namely: + +~~~yaml +user-message: ! 'Warning: Some packages were found to be incompatible with the resolver + and have been left commented out in the packages section. + + Warning: Specified resolver could not satisfy all dependencies. Some external packages + have been added as dependencies. + + You can omit this message by removing it from stack.yaml + +' +~~~ + +## custom-preprocessor-extensions + +Default: `[]` + +Command line equivalent: `--customer-preprocessor-extensions` option + +In order for Stack to be aware of any custom preprocessors you are using, add +their extensions here + +~~~yaml +custom-preprocessor-extensions: +- erb +~~~ + +??? example "Use of a custom preprocessor" + + The [Ruby](https://www.ruby-lang.org/en/) programming language provides + [`erb`](https://docs.ruby-lang.org/en/master/ERB.html) at the command line. + `erb` provides a templating system for Ruby. The following example uses + `erb` as a custom preprocessor. + + The example is a single-package project with a customised `Setup.hs`, which + Stack will use to build: + ~~~haskell + {-# LANGUAGE CPP #-} + + module Main + ( main + ) where + + import Distribution.Simple ( defaultMainWithHooks, simpleUserHooks ) + import Distribution.Simple.PreProcess + ( PreProcessor (..), mkSimplePreProcessor, unsorted ) + import Distribution.Simple.UserHooks ( UserHooks (..) ) + import Distribution.Types.BuildInfo ( BuildInfo ) + import Distribution.Types.ComponentLocalBuildInfo + ( ComponentLocalBuildInfo ) + import Distribution.Types.LocalBuildInfo ( LocalBuildInfo ) + import System.Process ( readCreateProcess, proc, shell ) + + main :: IO () + main = defaultMainWithHooks simpleUserHooks + { hookedPreProcessors = [("erb", runRuby)] + } + + runRuby :: + BuildInfo + -> LocalBuildInfo + -> ComponentLocalBuildInfo + -> PreProcessor + runRuby _ _ _ = PreProcessor + { platformIndependent = True + , ppOrdering = unsorted + , runPreProcessor = mkSimplePreProcessor $ \erbFile fout verbosity -> + readCreateProcess (erbProcess erbFile) "" >>= writeFile fout + } + where + erbProcess erbFile = + #if defined(mingw32_HOST_OS) + shell $ "erb " <> erbFile + #else + proc "erb" [erbFile] + #endif + ~~~ + + The example has a package description file (`package.yaml`) that specifies a + `Custom` build type: + ~~~yaml + spec-version: 0.36.0 + name: my-package + version: 0.1.0.0 + build-type: Custom + + dependencies: base + + custom-setup: + dependencies: + - base + - Cabal + - process + + library: + source-dirs: src + generated-exposed-modules: MyModule + ~~~ + + The example has a `src/MyModule.erb` file that will be preprocessed to + create Haskell source code: + ~~~text + module MyModule where + + <% (1..5).each do |i| %> + test<%= i %> :: Int + test<%= i %> = <%= i %> + <% end %> + ~~~ + + The example has a project-level configuration file (`stack.yaml`): + ~~~yaml + snapshot: lts-22.30 + custom-preprocessor-extensions: + - erb + ~~~ + +## extra-package-dbs + +[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) + +Default: `[]` + +A list of relative or absolute paths to package databases. These databases will +be added on top of GHC's global package database before the addition of other +package databases. + +!!! warning + + Use of this feature may result in builds that are not reproducible, as Stack + has no control over the contents of the extra package databases. + +## curator + +:octicons-beaker-24: Experimental + +[:octicons-tag-24: 2.1.0.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.0.1) + +Default: `{}` + +Configuration intended for use only by the +[`curator` tool](https://github.com/commercialhaskell/curator), which uses Stack +to build packages. For given package names (which need not exist in the +project), Stack can be configured to ignore (skip) silently building test +suites, building benchmarks and/or creating Haddock documentation or to expect +that building test suites, building benchmarks and/or creating Haddock +documentation will fail. + +For example: + +~~~yaml +curator: + skip-test: + - my-package1 + expect-test-failure: + - my-package2 + skip-bench: + - my-package3 + expect-benchmark-failure: + - my-package4 + skip-haddock: + - my-package5 + expect-haddock-failure: + - my-package6 +~~~
− doc/custom_snapshot.md
@@ -1,136 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -## Snapshot specification - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -Snapshots provide a list of packages to use, along with flags, GHC options, and -a few other settings. Snapshots may extend any other snapshot that can be -specified in a [`snapshot`](yaml_configuration.md#snapshot) or -[`resolver`](yaml_configuration.md#resolver) key. The packages specified follow -the same syntax for dependencies in Stack's project-level configuration files. -Unlike the `extra-deps` key, however, no support for local directories is -available in snapshots to ensure reproducibility. - -!!! info - - Stack uses the [Pantry](https://hackage.haskell.org/package/pantry) library - for snapshot specification. - -~~~yaml -snapshot: lts-22.21 # Inherits GHC version and package set -compiler: ghc-9.6.4 # Overwrites GHC version in the snapshot, optional - -# Additional packages, follows extra-deps syntax -packages: -- unordered-containers-0.2.7.1 -- hashable-1.2.4.0 -- text-1.2.2.1 - -# Packages from the parent snapshot to ignore -drop-packages: -- wai-extra - -# Packages which should be hidden -hidden: - wai: true - warp: false - -# Set GHC options for specific packages -ghc-options: - warp: - - -O2 - -# Override flags, can also override flags in the parent snapshot -flags: - unordered-containers: - debug: true -~~~ - -If you put this in a `snapshot.yaml` file in the same directory as your project, -you can now use the snapshot like this: - -~~~yaml -snapshot: snapshot.yaml -~~~ - -This is an example of a custom snapshot stored in the filesystem. They are -assumed to be mutable, so you are free to modify it. We detect that the snapshot -has changed by hashing the contents of the involved files, and using it to -identify the snapshot internally. It is often reasonably efficient to modify a -custom snapshot, due to Stack sharing snapshot packages whenever possible. - -### Overriding the compiler - -The following snapshot specification will be identical to `lts-22.21`, but -instead use `ghc-9.6.4` instead of `ghc-9.6.5`: - -~~~yaml -snapshot: lts-22.21 -compiler: ghc-9.6.4 -~~~ - -### Dropping packages - -The following snapshot specification will be identical to `lts-22.21`, but -without the `text` package in our snapshot. Removing this package will cause all -the packages that depend on `text` to be unbuildable, but they will still be -present in the snapshot. - -~~~yaml -snapshot: lts-22.21 -drop-packages: -- text -~~~ - -### Hiding packages - -The following snapshot specification will be identical to `lts-22.21`, but the -`text` package will be hidden when registering. This will affect, for example, -the import parser in the script command. - -~~~yaml -snapshot: lts-22.21 -hidden: -- text -~~~ - -### Specifying GHC options - -In order to specify GHC options for a package, you use the same syntax as the -[ghc-options](yaml_configuration.md#ghc-options) key for build configuration. - -The following snapshot specification will be identical to `lts-22.21`, but -provides `-O1` as a ghc-option for `text`: - -~~~yaml -snapshot: lts-22.21 -packages: -- text-2.0.2 -ghc-options: - text: -O1 -~~~ - -This works somewhat differently than the stack.yaml `ghc-options` field, in that -options can only be specified for packages that are mentioned in the custom -snapshot's `packages` list. It sets the ghc-options, rather than extending those -specified in the snapshot being extended. - -Another difference is that the `*` entry for `ghc-options` applies to all -packages in the `packages` list, rather than all packages in the snapshot. - -### Specifying Cabal flags - -In order to specify Cabal flags for a package, you use the same syntax as the -[flags](yaml_configuration.md#flags) key for build configuration. The -following snapshot specification will be identical to `lts-22.21`, but -it enables the `developer` Cabal flag: - -~~~yaml -snapshot: lts-22.21 -packages: -- text-2.0.2 -flags: - text: - developer: true -~~~
− doc/debugging.md
@@ -1,95 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Debugging - -To profile a component of the current project, pass the -[`--profile` flag](build_command.md#-profile-flag) to `stack build`. - -The flag: - -* for project packages, turns on the Cabal flag - [`--enable-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-profiling); -* turns on the Cabal flag - [`--enable-library-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-library-profiling); and -* passes GHC's - [`+RTS -p` runtime options](https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#rts-flag--p) - to any test suites and benchmarks. - -For example the following command will build the `my-tests` testsuite with -profiling options and create a `my-tests.prof` file in the current directory -as a result of the test run. - -~~~text -stack test --profile my-tests -~~~ - -The `my-tests.prof` file now contains time and allocation info for the test run. - -To create a profiling report for an executable, e.g. `my-exe`, you can command: - -~~~text -stack exec --profile -- my-exe +RTS -p -~~~ - -For more fine-grained control of compilation options there are the -[`--library-profiling` flag](build_command.md#-no-library-profiling-flag) and -[`--executable-profiling` flag](build_command.md#-no-executable-profiling-flag). - -The `--library-profiling` flag: - -* turns on the Cabal flag - [`--enable-library-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-library-profiling); and -* passes GHC's - [`+RTS -p` runtime options](https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#rts-flag--p) - to any test suites and benchmarks. - -The `--executable-profiling` flag: - -* for project packages, turns on the Cabal flag - [`--enable-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-profiling); -* turns on the Cabal flag - [`--enable-library-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-library-profiling); and -* passes GHC's - [`+RTS -p` runtime options](https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#rts-flag--p) - to any test suites and benchmarks. - -To enable compilation with profiling options by default you can add the -following to a project-level or global YAML configuration file: - -~~~yaml -build: - library-profiling: true - executable-profiling: true -~~~ - -## Further reading - -For more commands and uses, see the -[official GHC chapter on profiling](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html), -the [Haskell wiki](https://wiki.haskell.org/How_to_profile_a_Haskell_program), -and the -[chapter on profiling in Real World Haskell](http://book.realworldhaskell.org/read/profiling-and-optimization.html). - -## Tracing - -To generate a backtrace in case of exceptions during a test or benchmarks run, -use the `--trace` flag. Like `--profile` this compiles with profiling options, -but adds the `+RTS -xc` runtime option. - -## Debugging symbols - -Building with debugging symbols in the -[DWARF information](https://ghc.haskell.org/trac/ghc/wiki/DWARF) is supported by -Stack. This can be done by passing the flag `--ghc-options="-g"` and also to -override the default behaviour of stripping executables of debugging symbols by -passing either one of the following flags: `--no-strip`, -`--no-library-stripping` or `--no-executable-stripping`. - -In Windows, GDB can be installed to debug an executable with -`stack exec -- pacman -S gdb`. Windows' Visual Studio compiler's debugging -format PDB is not supported at the moment. This might be possible by -[separating](https://stackoverflow.com/questions/866721/how-to-generate-gcc-debug-symbol-outside-the-build-target) -debugging symbols and -[converting](https://github.com/rainers/cv2pdb) their format. Or as an option -when -[using the LLVM backend](http://blog.llvm.org/2017/08/llvm-on-windows-now-supports-pdb-debug.html).
doc/dev_containers.md view
@@ -124,8 +124,8 @@ and the [Haskell extension](https://marketplace.visualstudio.com/items?itemName=haskell.haskell) are only available in the default Dev Container. In order to use the Haskell -extension, you must first configure the project for the build tool of your -choice. +extension, you must first configure the project for the tool used for building +of your choice. <!-- **Stack**
− doc/developing_on_windows.md
@@ -1,102 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Developing on Windows # - -On Windows, Stack comes with an installation of [MSYS2](https://www.msys2.org/). -The MINGW64 (MINGW32 on 32-bit Windows) environment of MSYS2 will be used by -Stack to provide a Unix-like shell and environment for Stack. This may be -necessary for installing some Haskell packages, such as those which use -`configure` scripts, or if your project needs some additional tools during the -build phase. - -No matter which terminal software you choose (Windows Terminal, Console Windows -Host, Command Prompt, PowerShell, Git bash or any other) you can use this -environment too by executing all programs through -`stack exec -- <program_name>`. - -Executables and libraries can be installed with the MSYS2 package manager -`pacman`. All tools can be found in the [index](https://packages.msys2.org) to -MSYS2 packages. A [guide](https://www.msys2.org/docs/package-management/) to -package management with `pacman` is also available. `pacman` — like all -other tools in the Stack environment — should be started with -`stack exec -- pacman`. Help about `pacman` commands (operations) can be -obtained by `stack exec -- pacman --help`. Help about a specific `pacman` -operation can be obtained by using `--help` (or `-h`) with an operation. For -example, help about the operation `--sync` (or `-S`) can be obtained with -`stack exec -- pacman --sync --help` or, equivalently, -`stack exec -- pacman -Sh`. - -Command `stack path --bin-path` to see the PATH in the Stack environment. On -Windows, it includes the `\mingw64\bin` (`\mingw32\bin` on 32-bit Windows), -`\usr\bin` and `\usr\local\bin` directories of the Stack-supplied MSYS2. If your -executable depends on files (for example, dynamic-link libraries) in those -directories and you want to run it outside of the Stack environment, you will -need to ensure copies of those files are on the PATH. - -Command `stack path --extra-include-dirs` and `stack path --extra-library-dirs` -to see the extra directories searched for C header files or system libraries -files in the Stack environment. On Windows, it includes the `\mingw64\include` -(`mingw32\include` on 32-bit Windows) (include) and the `\mingw64\lib` and -`\mingw64\bin` directories (`mingw32\lib` and `mingw32\bin` on 32-bit Windows) -(library) of the Stack-supplied MSYS2. - -## Updating the Stack-supplied MSYS2 ## - -The Stack-supplied MSYS2 can itself be updated with the Stack-supplied `pacman`. -See the MSYS2 guide [Updating MSYS2](https://www.msys2.org/docs/updating/). If -the Stack-supplied `pacman` has a version that is 5.0.1.6403 or greater (see -`stack exec -- pacman --version`) then the command to update is simply: - - stack exec -- pacman -Suy - -This command may need to be run more than once, until everything is reported by -`pacman` as 'up to date' and 'nothing to do'. - -## Setup.hs ## - -`Setup.hs` is automatically run inside the Stack environment. So when you need -to launch another tool you don't need to prefix the command with `stack exec --` -within the custom `Setup.hs` file. - -## Pacman packages to install for common Haskell packages ## - -The following lists MSYS2 packages known to allow the installation of some -common Haskell packages on Windows. Feel free to submit additional entries via a -pull request. - -* For [text-icu](https://hackage.haskell.org/package/text-icu) install - `mingw64/mingw-w64-x86_64-icu`. - -* For [zlib >= 0.7](https://hackage.haskell.org/package/zlib) the default - Cabal flag `pkg-config` is `true` and requires executable `pkg-config` on - the PATH. MSYS2 [defaults](https://www.msys2.org/docs/pkgconfig/) to - [`pkgconf`](https://packages.msys2.org/package/pkgconf?repo=msys&variant=x86_64) - as its `pkg-config` implementation. Installation: - - stack exec -- pacman -S pkgconf - - Alternatively, build with `--flag zlib:-pkg-config`. - -## CMake ## - -CMake has trouble finding other tools even if they are available on the PATH. -Likely this is not a CMake problem but one of the environment not fully -integrating. For example GHC comes with a copy of GCC which is not installed by -MSYS2 itself. If you want to use this GCC you can provide a full path to it, or -find it first with `System.Directory.findExecutable` if you want to launch GCC -from a Haskell file such as `Setup.hs`. - -Experience tells that the `mingw-w64` versions of Make and CMake are most -likely to work. Though there are other versions available through `pacman`, so -have a look to see what works for you. Both tools can be installed with the -commands: - - stack exec -- pacman -S mingw-w64-x86_64-make - stack exec -- pacman -S mingw-w64-x86_64-cmake - -Even though Make and CMake are then both installed into the same environment, -CMake still seems to have trouble to find Make. To help CMake find GCC and Make -supply the following flags: - - -DCMAKE_C_COMPILER=path - -DCMAKE_MAKE_PROGRAM=path
− doc/docker_command.md
@@ -1,37 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack docker` commands - -~~~text -stack docker COMMAND - -Available commands: - pull Pull latest version of Docker image from registry - reset Reset the Docker sandbox -~~~ - -Stack is able to build your code inside a Docker image, which means even more -reproducibility to your builds, since you and the rest of your team will always -have the same system libraries. - -For further information, see the [Docker integration](docker_integration.md) -documentation. - -## The `stack docker pull` command - -~~~text -stack docker pull -~~~ - -`stack docker pull` pulls the latest version of the Docker image from the -registry. - -## The `stack docker reset` command - -~~~text -stack docker reset [--keep-home] -~~~ - -`stack docker reset` resets the Docker sandbox. - -Pass the flag `--keep-home` to preserve the sandbox's home directory.
− doc/docker_integration.md
@@ -1,473 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -Docker integration -=============================================================================== - -Stack has support for automatically performing builds inside a Docker -container, using volume mounts and user ID switching to make it mostly seamless. -FP Complete provides images for use with stack that include GHC, tools, and -optionally have all of the Stackage LTS packages pre-installed in the global -package database. - -The primary purpose for using stack/docker this way is for teams to ensure all -developers are building in an exactly consistent environment without team -members needing to deal with Docker themselves. - -See the -[how stack can use Docker under the hood](https://www.fpcomplete.com/blog/2015/08/stack-docker) -blog post for more information about the motivation and implementation of stack's -Docker support. - -If you'd like to build Docker images that contain your Haskell -executables, see [Building Haskell Apps with -Docker](https://www.fpcomplete.com/blog/2017/12/building-haskell-apps-with-docker). - -Prerequisites -------------------------------------------------------------------------------- - -### Supported operating systems - -**Linux 64-bit**: Docker use requires machine (virtual or metal) running a Linux -distribution -[that Docker supports](https://docs.docker.com/installation/#installation), with -a 64-bit kernel. If you do not already have one, we suggest Ubuntu 14.04 -("trusty") since this is what we test with. - -**macOS**: [Docker for Mac](https://docs.docker.com/docker-for-mac/) is the -supported way to use Docker integration on macOS (the older Docker Machine -(boot2docker) approach to using Docker on macOS is not supported due to issues -with host volume mounting that make Stack nearly unusable for anything but the -most trivial projects). - -Other Un*xen are not officially supported but there are ways to get them working. -See [#194](https://github.com/commercialhaskell/stack/issues/194) for details -and workarounds. - -Note: you may want to use set the `mount-mode` option to `delegated`, since -this can dramatically improve performance on macOS (see -[configuration](#configuration) for more information). - -**Windows does not work at all** (see -[#2421](https://github.com/commercialhaskell/stack/issues/2421)). - -### Docker - -Install the latest version of Docker by following the -[instructions for your operating system](http://docs.docker.com/installation/). - -The Docker client should be able to connect to the Docker daemon as a non-root -user. For example (from -[here](http://docs.docker.com/installation/ubuntulinux/#ubuntu-raring-1304-and-saucy-1310-64-bit)): - - # Add the connected user "${USER}" to the docker group. - # Change the user name to match your preferred user. - sudo gpasswd -a ${USER} docker - - # Restart the Docker daemon. - sudo service docker restart - -You will now need to log out and log in again for the group addition -to take effect. - -Note the above has security implications. See [security](#security) for more. - -Usage -------------------------------------------------------------------------------- - -This section assumes that you already have Docker installed and working. If -not, see the [prerequisites](#prerequisites) section. If you run into any -trouble, see the [troubleshooting](#troubleshooting) section. - -### Enable in stack.yaml - -The most basic configuration is to add this to your project's `stack.yaml`: - - docker: - enable: true - -See [configuration](#configuration) for additional options. You can enable it on -the command-line using `stack --docker`. - -Please note that in a docker-enabled configuration, stack uses the GHC installed -in the Docker container by default. To use a compiler installed by stack, add - - system-ghc: false - -(see [`system-ghc`](yaml_configuration.md#system-ghc)). - -### Use stack as normal - -With Docker enabled, most stack sub-commands will automatically launch -themselves in an ephemeral Docker container (the container is deleted as soon as -the command completes). The project directory and `~/.stack` are volume-mounted -into the container, so any build artifacts are "permanent" (not deleted with the -container). - -The first time you run a command with a new image, you will be prompted to run -`stack docker pull` to pull the image first. This will pull a Docker -image with a tag that matches your snapshot. Only LTS snapshots are supported -(we do not generate images for nightly snapshots). Not every LTS version is -guaranteed to have an image existing, and new LTS images tend to lag behind -the LTS snapshot being published on stackage.org. Be warned: these images are -rather large! - -Docker sub-commands -------------------------------------------------------------------------------- - -These `stack docker` sub-commands have Docker-specific functionality. Most other -`stack` commands will also use a Docker container under the surface if Docker is -enabled. - -### pull - Pull latest version of image - -`stack docker pull` pulls an image from the Docker registry for the first time, -or updates the image by pulling the latest version. - -### reset - Reset the Docker "sandbox" - -In order to preserve the contents of the in-container home directory between -runs, a special "sandbox" directory is volume-mounted into the container. -`stack docker reset` will reset that sandbox to its defaults. - -Note: `~/.stack` is separately volume-mounted, and is left alone during reset. - -Command-line options -------------------------------------------------------------------------------- - -The default Docker configuration can be overridden on the command-line. See -`stack --docker-help` for a list of all Docker options, and consult -[configuration](#configuration) section below for more information about -their meanings. These are global options, and apply to all commands (not just -`stack docker` sub-commands). - -Configuration -------------------------------------------------------------------------------- - -`stack.yaml` contains a `docker:` section with Docker settings. If this -section is omitted, Docker containers will not be used. These settings can -be included in project, user, or global configuration. - -Here is an annotated configuration file. The default values are shown unless -otherwise noted. - - docker: - - # Set to false to disable using Docker. In the project configuration, - # the presence of a `docker:` section implies docker is enabled unless - # `enable: false` is set. In user and global configuration, this is not - # the case. - enable: true - - # The name of the repository to pull the image from. See the "repositories" - # section of this document for more information about available repositories. - # If this includes a tag (e.g. "my/image:tag"), that tagged image will be - # used. Without a tag specified, the LTS version slug is added automatically. - # Either `repo` or `image` may be specified, but not both. - repo: "fpco/stack-build" - - # Exact Docker image name or ID. Overrides `repo`. Either `repo` or `image` - # may be specified, but not both. (default none) - image: "5c624ec1d63f" - - # Registry requires login. A login will be requested before attempting to - # pull. - registry-login: false - - # Username to log into the registry. (default none) - registry-username: "myuser" - - # Password to log into the registry. (default none) - registry-password: "SETME" - - # If true, the image will be pulled from the registry automatically, without - # needing to run `stack docker pull`. See the "security" section of this - # document for implications of enabling this. - auto-pull: true - - # If true, the container will be run "detached" (in the background). Refer - # to the Docker users guide for information about how to manage containers. - # This option would rarely make sense in the configuration file, but can be - # useful on the command-line. When true, implies `persist`. - detach: false - - # If true, the container will not be deleted after it terminates. Refer to - # the Docker users guide for information about how to manage containers. This - # option would rarely make sense in the configuration file, but can be - # useful on the command-line. `detach` implies `persist`. - persist: false - - # What to name the Docker container. Only useful with `detach` or - # `persist` true. (default none) - container-name: "example-name" - - # Sets the network used by docker. Gets directly passed to dockers `net` - # argument (default: host) - network: host - - # Additional arguments to pass to `docker run`. (default none) - run-args: ["--net=bridge"] - - # Directories from the host to volume-mount into the container. If it - # contains a `:`, the part before the `:` is the directory on the host and - # the part after the `:` is where it should be mounted in the container. - # (default none, aside from the project and stack root directories which are - # always mounted) - mount: - - "/foo/bar" - - "/baz:/tmp/quux" - - # Sets the volume mount mode, passed directly to `docker`. - # The default mode (consistent) is safest, but may suffer poor performance - # on non-Linux platforms such as macOS, where the `delegated` mode will - # be significantly faster. - # See https://docs.docker.com/docker-for-mac/osxfs-caching/ - # for valid values and the implications of changing the default. - mount-mode: delegated - - # Environment variables to set in the container. Environment variables - # are not automatically inherited from the host, so if you need any specific - # variables, use the `--docker-env` command-line argument version of this to - # pass them in. (default none) - env: - - "FOO=BAR" - - "BAR=BAZ QUUX" - - # Location of a Docker container-compatible 'stack' executable with the - # matching version. This executable must be compatible with the Docker - # image in terms of platform (linux-x86_64) and shared libraries - # (statically linked is best, otherwise the image needs to have the - # same shared libraries installed). - # Valid values are: - # host: use the host's executable. This is the default when the host's - # executable is known to work (e.g., from official linux-x86_64 bindist) - # download: download a compatible executable matching the host's version. - # This is the default when the host's executable is not known to work - # image: use the 'stack' executable baked into the image. The version - # must match the host's version - # /path/to/stack: path on the host's local filesystem - stack-exe: host - - # If true (the default when using the local Docker Engine), run processes - # in the Docker container as the same UID/GID as the host. The ensures - # that files written by the container are owned by you on the host. - # When the Docker Engine is remote (accessed by tcp), defaults to false. - set-user: true - - # Require the version of the Docker client to be within the specified - # Cabal-style version range (e.g., ">= 1.6.0 && < 1.9.0") - require-docker-version: "any" - -Image Repositories -------------------------------------------------------------------------------- - -FP Complete provides the following public image repositories on Docker Hub: - -- [fpco/stack-build](https://registry.hub.docker.com/r/fpco/stack-build/) (the - default) - GHC (patched), tools (Stack, Cabal (the tool), happy, alex, etc.), - and system developer libraries required to build all Stackage packages. - -FP Complete also builds custom variants of these images for their clients. - -These images can also be used directly with `docker run` and provide a complete -Haskell build environment. - -In addition, most Docker images that contain the basics for running GHC can be -used with Stack's Docker integration. For example, the -[official Haskell image repository](https://hub.docker.com/_/haskell/) works. -See [Custom images](#custom-images) for more details. - -Security -------------------------------------------------------------------------------- - -Having `docker` usable as a non-root user is always a security risk, and will -allow root access to your system. It is also possible to craft a `stack.yaml` -that will run arbitrary commands in an arbitrary docker container through that -vector, thus a `stack.yaml` could cause stack to run arbitrary commands as root. -While this is a risk, it is not really a greater risk than is posed by the -docker permissions in the first place (for example, if you ever run an unknown -shell script or executable, or ever compile an unknown Haskell package that uses -Template Haskell, you are at equal risk). Nevertheless, there are -[plans to close the stack.yaml loophole](https://github.com/commercialhaskell/stack/issues/260). - -One way to mitigate this risk is, instead of allowing `docker` to run as -non-root, replace `docker` with a wrapper script that uses `sudo` to run the -real Docker client as root. This way you will at least be prompted for your root -password. As [@gregwebs](https://github.com/gregwebs) pointed out, put this -script named `docker` in your PATH (and make sure you remove your user from the -`docker` group as well, if you added it earlier): - - #!/bin/bash -e - # The goal of this script is to maintain the security privileges of sudo - # Without having to constantly type "sudo" - exec sudo /usr/bin/docker "$@" - -Additional notes -------------------------------------------------------------------------------- - -### Volume-mounts and ephemeral containers - -Since filesystem changes outside of the volume-mounted project directory are not -persisted across runs, this means that if you `stack exec sudo apt-get install some-ubuntu-package`, -that package will be installed but then the container it's -installed in will disappear, thus causing it to have no effect. If you wish to -make this kind of change permanent, see later instructions for how to create a -[derivative Docker image](#derivative-image). - -Inside the container, your home directory is a special location that volume- -mounted from within your project directory's `.stack-work` in such a -way as that installed GHC/cabal packages are not shared between different -Stackage snapshots. In addition, `~/.stack` is volume-mounted from the host. - -### Network - -stack containers use the host's network stack within the container -by default, meaning a process running in the container can connect to -services running on the host, and a server process run within the container -can be accessed from the host without needing to explicitly publish its port. -To run the container with an isolated network, use `--docker-run-args` to pass -the `--net` argument to `docker-run`. For example: - - stack --docker-run-args='--net=bridge --publish=3000:3000' \ - exec some-server - -will run the container's network in "bridge" mode (which is Docker's default) -and publish port 3000. - -### Persistent container - -If you do want to do all your work, including editing, in the container, it -might be better to use a persistent container in which you can install Ubuntu -packages. You could get that by running something like -`stack --docker-container-name=NAME --docker-persist exec bash`. This -means when the container exits, it won't be deleted. You can then restart it -using `docker start -a -i NAME`. It's also possible to detach from a container -while it continues running in the background using by pressing Ctrl-P Ctrl-Q, -and then reattach to it using `docker attach NAME`. - -Note that each time you run `stack --docker-persist`, a _new_ persistent -container is created (it will not automatically reuse the previous one). -See the [Docker user guide](https://docs.docker.com/userguide/) for more -information about managing Docker containers. - -### Derivative image - -Creating your own custom derivative image can be useful if you need to install -additional Ubuntu packages or make other changes to the operating system. Here -is an example (replace `stack-build:custom` if you prefer a different name for -your derived container, but it's best if the repo name matches what you're -deriving from, only with a different tag, to avoid recompilation): - - ;;; On host - $ sudo stack --docker-persist --docker-container-name=temp exec bash - - ;;; In container, make changes to OS - # apt-get install r-cran-numderiv - [...] - # exit - - ;;; On host again - $ docker commit temp stack-build:custom - $ docker rm temp - -Now you have a new Docker image named `stack-build:custom`. To use the new image, run -a command such as the following or update the corresponding values in your -`stack.yaml`: - - stack --docker-image=stack-build:custom <COMMAND> - -Note, however, that any time a new image is used, you will have to re-do this -process. You could also use a Dockerfile to make this reusable. Consult the -[Docker user guide](https://docs.docker.com/userguide/) for more -on creating Docker images. - -### Custom images - -The easiest way to create your own custom image us by extending FP Complete's -images, but if you prefer to start from scratch, most images that include the -basics for building code with GHC will work. The image doesn't even, strictly -speaking, need to include GHC, but it does need to have libraries and tools that -GHC requires (e.g., libgmp, gcc, etc.). - -There are also a few ways to set up images that tightens the integration: - -* Create a user and group named `stack`, and create a `~/.stack` directory for - it. Any build plans and caches from it will be copied from the image by Stack, - meaning they don't need to be downloaded separately. -* Any packages in GHC's global package database will be available. This can be - used to add private libraries to the image, or the make available a set of - packages from an LTS release. - -Troubleshooting -------------------------------------------------------------------------------- - -### "No Space Left on Device", but 'df' shows plenty of disk space - -This is likely due to the storage driver Docker is using, in combination with -the large size and number of files in these images. Use `docker info|grep 'Storage Driver'` -to determine the current storage driver. - -We recommend using either the `overlay` or `aufs` storage driver for stack, as -they are least likely to give you trouble. On Ubuntu, `aufs` is the default for -new installations, but older installations sometimes used `devicemapper`. - -The `devicemapper` storage driver's doesn't work well with large filesystems, -and we have experienced other instabilities with it as well. We recommend -against its use. - -The `btrfs` storage driver has problems running out of metadata space long -before running out of actual disk space, which requires rebalancing or adding -more metadata space. See -[CoreOS's btrfs troubleshooting page](https://coreos.com/docs/cluster-management/debugging/btrfs-troubleshooting/) -for details about how to do this. - -Pass the `-s <driver>` argument to the Docker daemon to set the storage driver -(in `/etc/default/docker` on Ubuntu). See -[Docker daemon storage-driver option](https://docs.docker.com/reference/commandline/cli/#daemon-storage-driver-option) -for more details. - -You may also be running out of inodes on your filesystem. Use `df -i` to check -for this condition. Unfortunately, the number of inodes is set when creating -the filesystem, so fixing this requires reformatting and passing the `-N` -argument to mkfs.ext4. - -### Name resolution doesn't work from within container - -On Ubuntu 12.04, by default `NetworkManager` runs `dnsmasq` service, which sets -`127.0.0.1` as your DNS server. Since Docker containers cannot access this -dnsmasq, Docker falls back to using Google DNS (8.8.8.8/8.8.4.4). This causes -problems if you are forced to use internal DNS server. This can be fixed by -executing: - - sudo sed 's@dns=dnsmasq@#dns=dnsmasq@' -i \ - /etc/NetworkManager/NetworkManager.conf && \ - sudo service network-manager restart - -If you have already installed Docker, you must restart the daemon for this -change to take effect: - - sudo service docker restart - -<small> -The above commands turn off `dnsmasq` usage in NetworkManager -configuration and restart network manager. They can be reversed by executing -`sudo sed 's@#dns=dnsmasq@dns=dnsmasq@' -i /etc/NetworkManager/NetworkManager.conf && sudo service network-manager restart`. -These instructions are adapted from -[the Shipyard Project's QuickStart guide](https://github.com/shipyard/shipyard/wiki/QuickStart#127011-dns-server-problem-on-ubuntu). -</small> - -### Cannot pull images from behind firewall that blocks TLS/SSL - -If you are behind a firewall that blocks TLS/SSL and pulling images from a -private Docker registry, you must edit the system configuration so that the -`--insecure-registry <registry-hostname>` option is passed to the Docker daemon. -For example, on Ubuntu: - - echo 'DOCKER_OPTS="--insecure-registry registry.example.com"' \ - |sudo tee -a /etc/default/docker - sudo service docker restart - -This does require the private registry to be available over plaintext HTTP. - -See -[Docker daemon insecure registries documentation](https://docs.docker.com/reference/commandline/cli/#insecure-registries) -for details.
− doc/dot_command.md
@@ -1,103 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack dot` command - -~~~text -stack dot [--[no-]external] [--[no-]include-base] [--depth DEPTH] - [--prune PACKAGES] [TARGET] [--flag PACKAGE:[-]FLAG] - [--test] [--bench] [--global-hints] -~~~ - -A package and its dependencies and the direct dependency relationships between -them form a directed graph. [Graphviz](https://www.graphviz.org/) is open source -software that visualises graphs. It provides the DOT language for defining -graphs and the `dot` executable for drawing directed graphs. Graphviz is -available to [download](https://www.graphviz.org/download/) for Linux, Windows, -macOS and FreeBSD. - -`stack dot` produces output, to the standard output stream, in the DOT language -to represent the relationships between your packages and their dependencies. - -By default: - -* external dependencies are excluded from the output. Pass the flag - `--external` to include external dependencies; -* the `base` package and its dependencies are included in the output. Pass the - flag `--no-include-base` to exclude `base` and its dependencies; -* there is no limit to the depth of the resolution of dependencies. Pass the - `--depth <depth>` option to limit the depth; -* all relevant packages are included in the output. Pass the - `--prune <packages>` option to exclude the specified packages, where - `<packages>` is a list of package names separated by commas; -* all packages in the project are included in the output. However, the target - for the command can be specified as an argument. It uses the same format - as the [`stack build` command](build_command.md); -* test components of the packages in the project are excluded from the output. - Pass the flag `--test` to include test components; and -* benchmark components of the packages in the project are excluded from the - output. Pass the flag `--bench` to include benchmark components.git p - -Pass the option `--flag <package_name>:<flag_name>` or -`--flag <package_name>:-<flag_name>` to set or unset a Cabal flag. This -option can be specified multiple times. - -Pass the flag `--global-hints` to use a hint file for global packages. If a hint -file is used, GHC does not need to be installed. - -## Examples - -The following examples are based on a version of the -[`wreq` package](https://hackage.haskell.org/package/wreq). In each case, the -output from `stack dot` is piped as an input into Graphviz's `dot` executable, -and `dot` produces output in the form of a PNG file named `wreq.png`. - -* A simple example: - - ~~~text - stack dot | dot -Tpng -o wreq.png - ~~~ - - [](https://cloud.githubusercontent.com/assets/591567/8478591/ae10a418-20d2-11e5-8945-55246dcfac62.png) - -* Include external dependencies: - - ~~~text - stack dot --external | dot -Tpng -o wreq.png - ~~~ - - [](https://cloud.githubusercontent.com/assets/591567/8478621/d247247e-20d2-11e5-993d-79096e382abd.png) - -* Include external dependencies, limit the depth and save the output from - `stack dot` as an intermediate file (`wreq.dot`). - - ~~~text - stack dot --external --depth 1 > wreq.dot - dot -Tpng -o wreq.png wreq.dot - ~~~ - -* Include external dependencies, exclude `base` and limit the depth: - - ~~~text - stack dot --no-include-base --external --depth 1 | dot -Tpng -o wreq.png - ~~~ - - [](https://cloud.githubusercontent.com/assets/591567/8484310/45b399a0-20f7-11e5-8068-031c2b352961.png) - -* Include external dependencies and prune `base` and other packages: - - ~~~text - stack dot --external --prune base,lens,wreq-examples,http-client,aeson,tls,http-client-tls,exceptions | dot -Tpng -o wreq.png - ~~~ - - [](https://cloud.githubusercontent.com/assets/591567/8478768/adbad280-20d3-11e5-9992-914dc24fe569.png) - -* Include external dependencies, prune `base` and other packages, and use a - different Graphviz executable to draw the graph: - - Graphviz's `twopi` executable draws graphs in a radial layout. - - ~~~text - stack dot --external --prune base,lens,wreq-examples,http-client,aeson,tls,http-client-tls,exceptions | twopi -Groot=wreq -Goverlap=false -Tpng -o wreq.png - ~~~ - - [](https://cloud.githubusercontent.com/assets/591567/8495538/9fae1184-216e-11e5-9931-99e6147f8aed.png)
− doc/editor_integration.md
@@ -1,20 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Editor integration - -## Visual Studio Code - -For further information, see the [Stack and Visual Code](Stack_and_VS_Code.md) -documentation. - -## Shell auto-completion - -Love tab-completion of commands? You're not alone. If you're on bash, just run -the following command (or add it to `.bashrc`): - -~~~text -eval "$(stack --bash-completion-script stack)" -~~~ - -For more information and other shells, see the -[Shell auto-completion wiki page](https://docs.haskellstack.org/en/stable/shell_autocompletion)
− doc/environment_variables.md
@@ -1,134 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Stack's environment variables - -The environment variables listed in alphabetal order below can affect how Stack -behaves. - -## `GH_TOKEN` or `GITHUB_TOKEN` - -[:octicons-tag-24: 2.11.1](https://github.com/commercialhaskell/stack/releases/tag/v2.11.1) - -Stack will use the value of the `GH_TOKEN` or, in the alternative, -`GITHUB_TOKEN` environment variable (if not an empty string) as credentials to -authenticate its requests of the GitHub REST API, using HTTP 'Basic' -authentication. - -GitHub limits the rate of unauthenticated requests to its API, although most -users of Stack will not experience that limit from the use of Stack alone. The -limit for authenticated requests is significantly higher. - -For more information about authentication of requests of the GitHub REST API, -see GitHub's REST API documentation. - -## `HACKAGE_KEY` - -[:octicons-tag-24: 2.7.5](https://github.com/commercialhaskell/stack/releases/tag/v2.7.5) - -Related command: [`stack upload`](upload_command.md) - -Hackage allows its members to register an API authentification token and to -authenticate using the token. - -A Hackage API authentification token can be used with `stack upload` instead of -username and password, by setting the `HACKAGE_KEY` environment variable. For -example: - -=== "Unix-like" - - ~~~text - HACKAGE_KEY=<api_authentification_token> - stack upload . - ~~~ - -=== "Windows (with PowerShell)" - - ~~~text - $Env:HACKAGE_KEY=<api_authentification_token> - stack upload . - ~~~ - -## `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` - -[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) - -Related command: [`stack upload`](upload_command.md) - -`stack upload` will request a Hackage username and password to authenticate. -This can be avoided by setting the `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` -environment variables. For -example: - -=== "Unix-like" - - ~~~text - export $HACKAGE_USERNAME="<username>" - export $HACKAGE_PASSWORD="<password>" - stack upload . - ~~~ - -=== "Windows (with PowerShell)" - - ~~~text - $Env:HACKAGE_USERNAME='<username>' - $Env:HACKAGE_PASSWORD='<password>' - stack upload . - ~~~ - -## `NO_COLOR` - -Related command: all commands that can produce colored output using control character sequences. - -Stack follows the standard at http://no-color.org/. Stack checks for a -`NO_COLOR` environment variable. When it is present and not an empty string -(regardless of its value), Stack prevents the addition of control character -sequences for color to its output. - -## `STACK_ROOT` - -Related command: all commands that make use of Stack's global YAML configuration -file (`config.yaml`). - -Overridden by: Stack's global -[`--stack-root`](global_flags.md#-stack-root-option) option. - -The environment variable `STACK_ROOT` can be used to specify the -[Stack root](stack_root.md) directory. - -## `STACK_WORK` - -Related command: all commands that make use of Stack's work directories. - -Overridden by: Stack's [`work-dir`](yaml_configuration.md#work-dir) non-project -specific configuration option, or global -[`--work-dir`](global_flags.md#-work-dir-option) option. - -The environment variable `STACK_WORK` can be used to specify the path of Stack's -work directory, within a local project or package directory, and override -Stack's default of `.stack-work`. The path must be a relative one, relative to -the root directory of the project or package. The relative path cannot include a -`..` (parent directory) component. - -## `STACK_XDG` - -Related command: all commands that make use of Stack's user-specific general -YAML configuration file (`config.yaml`). - -Overridden by: the use of Stack's `STACK_ROOT` environment variable, or the use -of Stack's global -[`--stack-root`](global_flags.md#-stack-root-option) option. - -On Unix-like operating systems and Windows, Stack can be configured to follow -the XDG Base Directory Specification if the environment variable `STACK_XDG` is -set to any non-empty value. - -## `STACK_YAML` - -Related command: all commands that make use of Stack's project-level YAML -configuration file. - -Overridden by: Stack's global -[`--stack-yaml`](global_flags.md#-stack-yaml-option) option. - -The environment variable `STACK_YAML` can be used to specify Stack's -project-level YAML configuration file.
− doc/eval_command.md
@@ -1,20 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack eval` command - -~~~text -stack eval CODE [--[no-]ghc-package-path] [--[no-]stack-exe] - [--package PACKAGE] [--rts-options RTSFLAG] [--cwd DIR] -~~~ - -GHC has an -[expression-evaluation mode](https://downloads.haskell.org/ghc/latest/docs/users_guide/using.html#eval-mode), -set by passing the GHC option -`-e <expression>`. Commanding `stack eval <code>` is equivalent to commanding: - -~~~text -stack exec ghc -- -e <code> -~~~ - -For further information, see the [`stack exec` command](exec_command.md) -documentation.
− doc/exec_command.md
@@ -1,72 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack exec` command - -~~~text -stack exec COMMAND - [-- ARGUMENT(S) (e.g. stack exec ghc-pkg -- describe base)] - [--[no-]ghc-package-path] [--[no-]stack-exe] [--package PACKAGE] - [--rts-options RTSFLAG] [--cwd DIR] -~~~ - -`stack exec` executes the specified executable as a command in the Stack -environment. If an executable is not specified, the first argument after `--` is -taken to be the executable. Otherwise, all arguments after `--` are taken to be -command line arguments for the specified executable. - -By default: - -* the `GHC_PACKAGE_PATH` environment variable is set for the command's process. - Pass the flag `--no-ghc-package-path` to not set the environment variable; - -* the `STACK_EXE` environment variable is set for the command's process. Pass - the flag `--no-stack-exe` to not set the environment variable; and - -* the specified executable is executed in the current directory. Pass the option - `--cwd <directory>` to execute the executable in the specified directory. - -The option `--package <package>` has no effect for the `stack exec` command. For -further information about its use, see the [`stack ghc` command](ghc_command.md) -documentation or the [`stack runghc` command](runghc_command.md) documentation. - -Pass the option `--rts-option <rts_flag(s)>` to specify a GHC RTS flag or option. -The option can be specified multiple times. All specified GHC RTS flags and -options are added to the arguments for the specified executable between -arguments `+RTS` and `-RTS`. - -Specified GHC RTS flags and options are separated by spaces. Items can be -unquoted (if they do not contain space or `"` characters) or quoted (`""`). -Quoted items can include 'escaped' characters, escaped with an initial `\` -character. - -Account may need to be taken of the shell's approach to the processing of -command line arguments. For example, to pass `'a single quoted string'`: - -=== "Unix-like (Bash or Zsh)" - - In Bash, or Zsh (if `RC_QUOTES` option not set): - - `stack exec <command> -- \''a single quoted string'\'` - - Outside of single quotes, `\'` escapes a single quote. The content of single - quotes is taken literally, but cannot contain a single quote. - - In Zsh (if `RC_QUOTES` option set): - - `stack exec <command> -- '''a single quoted string'''` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -=== "Windows (PowerShell)" - - `stack exec <command> -- '''a single quoted string'''` - - The content of single quotes is taken literally. Within single quotes, `''` - escapes a single quote. - -The command also accepts flags and options of the -[`stack build`](build_command.md#flags-affecting-ghcs-behaviour) command that -affect the location of the local project installation directory, such as -`--profile` and `--no-strip`. For further information, see the documentation of -the [project Stack work directory](stack_work.md#project-stack-work-directory).
doc/faq.md view
@@ -1,681 +1,601 @@ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> -# FAQ +# Frequently asked questions -So that this doesn't become repetitive: for the reasons behind the answers -below, see the [Build overview](build_overview.md) page. The goal of the answers -here is to be as helpful and concise as possible. +## Stack and Cabal -## What version of GHC is used when I run something like `stack ghci`? +??? question "What is the relationship between Stack and Cabal?" -The version of GHC, as well as which packages can be installed, are specified by -the _snapshot_. This may be something like `lts-22.21`, which is from -[Stackage](https://www.stackage.org/). The [user's guide](GUIDE.md) discusses -the snapshot in more detail. + 'Cabal' can refer to Cabal (the library) or to Cabal (the tool). -The snapshot is determined by finding the relevant project-level configuration -file (`stack.yaml`, by default) for the directory you're running the command -from. This essentially works by: + === "Cabal (the library)" -1. Check for a `STACK_YAML` environment variable or the `--stack-yaml` - command line argument -2. If none present, check for a `stack.yaml` file in the current - directory or any parents -3. If no `stack.yaml` file was found, use the _implicit global_ + Cabal (the library) is used by Stack to build your Haskell code. -The implicit global is a shared project used whenever you're outside -of another project. It's a sort of "mutable shared state" that you -should be aware of when working with Stack. + A Haskell package is described by a Cabal file, which file is part of + the package. The file is named `<package_name>.cabal`. -A frequent request when working with the implicit global is how to move to a -more recent LTS snapshot. You can do this using the following command from -outside of a project: + Stack requires a project-level configuration file (`stack.yaml`, by + default). -~~~text -stack config set snapshot lts -~~~ + For further information about the difference between a Cabal file and + a project-level configuration file, see the + [stack.yaml vs a Cabal file](topics/stack_yaml_vs_cabal_package_file.md) + documentation. -## Where is Stack installed and will it interfere with the GHC (etc) I already have installed? + The [`stack init`](commands/init_command.md) command initializes a + project-level configuration file from package description files. -Stack itself is installed in normal system locations based on the mechanism you -used (see the [Install and upgrade](install_and_upgrade.md) page). Stack -installs files in the Stack root and other files in a `.stack-work` directory -within each project's directory. None of this should affect any existing Haskell -tools at all. + Stack uses Cabal (the library) via an executable. For + `build-type: Simple` (the most common case), Stack builds that + executable using the version of Cabal which came with GHC. Stack caches + such executables, in the [Stack root](topics/stack_root.md) under + directory `setup-exe-cache`. -## What is the relationship between Stack and Cabal (the tool)? + In rare or complex cases, a different version of Cabal to the one that + came with GHC may be needed. `build-type: Custom` and a `setup-custom` + stanza in the Cabal file, and a `Setup.hs` file in the package + directory, can be specified. Stack's project-level configuration file + can then specify the version of Cabal that Stack will use to build the + executable (named `setup`) from `Setup.hs`. Stack will use Cabal via + `setup`. -* 'Cabal' can refer to Cabal (the library) or to Cabal (the tool). Cabal (the - library) is used by Stack to build your Haskell code. Cabal (the tool) is - provided by the `cabal-install` package. -* A Cabal file is provided for each package, named `<package_name>.cabal`. It - defines all package-level metadata, just like it does in the world of Cabal - (the tool): modules, executables, test suites, etc. No change at all on this - front. -* A `stack.yaml` file references one or more packages, and provides information - on where dependencies come from. -* The `stack init` command initializes a `stack.yaml` file from an existing - Cabal file. -* Stack uses Cabal (the library) via an executable. For `build-type: Simple` - (the most common case), Stack builds that executable using the version of - Cabal which came with the compiler. Stack caches such executables, in the - Stack root under directory `setup-exe-cache`. -* In rare or complex cases, a different version of Cabal to the one that came - with the compiler may be needed. `build-type: Custom` and a `setup-custom` - stanza in the Cabal file, and a `Setup.hs` file in the package directory, can - be specified. The `stack.yaml` file can then specify the version of Cabal - that Stack will use to build the executable (named `setup`) from `Setup.hs`. - Stack will use Cabal via `setup`. + === "Cabal (the tool)" -For detail on the differences between a `stack.yaml` file and a Cabal file, see -[stack.yaml vs a Cabal file](stack_yaml_vs_cabal_package_file.md). + Cabal (the tool) is a tool provided by the + [`cabal-install`](https://hackage.haskell.org/package/cabal-install) + Haskell package. It aims to simplify the process of managing Haskell + software by automating the fetching, configuration, compilation and + installation of Haskell libraries and programs. These are goals that + Stack shares. Stack can be used independently of Cabal (the tool) but + users can also use both, if they wish. -## I need to use a different version of a package than what is provided by the LTS Haskell snapshot I'm using, what should I do? +??? question "How do I use Stack with sandboxes?" -You can make tweaks to a snapshot by modifying the `extra-deps` configuration -value in your `stack.yaml` file, e.g.: + A 'sandbox' is a development environment that is isolated from other parts + of the system. The concept of sandboxing is built in to Stack. All builds + are automatically isolated into separate package databases. -~~~yaml -snapshot: lts-22.21 -packages: -- . -extra-deps: -- text-2.1.1@rev:0 -~~~ +??? question "Can I run `cabal` commands inside `stack exec`?" -## I need to use a package (or version of a package) that is not available on Hackage, what should I do? + Yes. Some `cabal` commands are inconsistent with the `GHC_PACKAGE_PATH` + environment variable in the Stack environment. Command, for example: -Add it to the -[`extra-deps`](yaml_configuration.md#extra-deps) list in your project's -`stack.yaml` file, specifying the package's source code location relative to the -directory where your `stack.yaml` file lives, e.g. + ~~~text + stack exec --no-ghc-package-path -- cabal build + ~~~ -~~~yaml -snapshot: lts-22.21 -packages: -- . -extra-deps: -- third-party/proprietary-dep -- github-version-of/conduit -- patched/diagrams -~~~ +## GHC or GHCi-related -The above example specifies that the `proprietary-dep` package is found in the -project's `third-party` directory, that the `conduit` package is found in the -project's `github-version-of` directory, and that the `diagrams` package is -found in the project's `patched` directory. This autodetects changes and -reinstalls the package. +??? question "Will Stack interfere with the GHC I already have installed?" -To install packages directly from a Git repository, use e.g.: + No. -~~~yaml -extra-deps: - - git: https://github.com/githubuser/reponame.git - commit: somecommitID -~~~ +??? question "I already have GHC installed. Can I still use Stack?" -## What is the meaning of the arguments given to `stack build`, `test`, etc? + Yes. In its default configuration, Stack will simply ignore any system GHC + installation and use a sandboxed GHC that it has installed itself. You can + find these sandboxed GHC installations in the `ghc-*` directories in the + `stack path --programs` directory. -Those are the targets of the build, and can have one of three formats: + If you would like Stack to use your system GHC installation, use the + [`--system-ghc`](configure/yaml/non-project.md#system-ghc) flag or run + `stack config set system-ghc --global true` to make Stack check your PATH + for a suitable GHC by default. -* A package name (e.g., `my-package`) will mean that the `my-package` package - must be built -* A package identifier (e.g., `my-package-1.2.3`), which includes a specific - version. This is useful for passing to `stack install` for getting a specific - version from upstream -* A directory (e.g., `./my-package`) for including a local directory's package, - including any packages in subdirectories + Stack can only use a system GHC installation if its version is compatible + with the configuration of the current project, particularly the snapshot + specified by the [`snapshot`](configure/yaml/project.md#snapshot) or + [`resolver`](configure/yaml/project.md#resolver) key. -## I need to modify an upstream package, how should I do it? + GHC installation doesn't work for all operating systems, so in some cases + you will need to use `system-ghc` and install GHC yourself. -Typically, you will want to get the source for the package and then add it to -your `packages` list in the `stack.yaml` file. (See the previous question.) -`stack unpack` is one approach for getting the source. Another would be to add -the upstream package as a submodule to your project. +??? question "When I command `stack ghci` what version of GHC is used?" -## How do I use this with sandboxes? + The version of GHC is specified by the snapshot in the relevant Stack + project-level configuration file. This may be the file in the + `global-project` directory in the [Stack root](topics/stack_root.md). -Explicit sandboxing on the part of the user is not required by Stack. All -builds are automatically isolated into separate package databases without any -user interaction. This ensures that you won't accidentally corrupt your -installed packages with actions taken in other projects. + For further information, see the [configuration](configure/yaml/index.md) + documentation. -## Can I run `cabal` commands inside `stack exec`? +??? question "How does Stack determine what GHC to use?" -With a recent enough version of Cabal (the tool) (1.22 or later), you can. For -earlier versions this does not work, due to Cabal issue -[#1800](https://github.com/haskell/cabal/issues/1800). Note that -even with recent versions, for some commands you may need the following extra -level of indirection. Command: + In its default configuration, Stack determines from the current project which + GHC version, architecture etc it needs. It then looks in the `ghc-<version>` + subdirectory of the `stack path --programs` directory for a compatible GHC, + requesting to install one via `stack setup` if none is found. -~~~text -stack exec -- cabal exec -- cabal <command> -~~~ + If you are using the [`--system-ghc`](configure/yaml/non-project.md#system-ghc) + flag or have configured `system-ghc: true` either in the project `stack.yaml` or + the global `config.yaml`, Stack will use the first GHC that it finds on your + PATH, falling back on its sandboxed installations only if the found GHC doesn't + comply with the various requirements (version, architecture) that your project + needs. -However, virtually all `cabal` commands have an equivalent in Stack, so this -should not be necessary. In particular, users of Cabal (the tool) may be -accustomed to the `cabal run` command. With Stack, command: + See issue [#420](https://github.com/commercialhaskell/stack/issues/420) for a + detailed discussion of Stack's behavior when `system-ghc` is enabled. -~~~text -stack build -stack exec <program-name> -~~~ +??? question "How can I test that different GHC versions can build my project?" -Or, if you want to install the binaries in a shared location, command: + You can create multiple project-level configuration files for your project, + one for each build plan. For example, you might set up your project + directory like so: -~~~text -stack install <program-name> -~~~ + ~~~text + myproject/ + stack-ghc-9.0.2.yaml + stack-ghc-9.2.4.yaml + stack.yaml --> symlink to stack-ghc-9.2.4.yaml + myproject.cabal + src/ + ... + ~~~ -assuming your PATH has been set appropriately. + When you run `stack build`, you can set the `STACK_YAML` environment + variable to indicate which build plan to use. Command: -## Using custom preprocessors + === "Unix-like" -If you have a custom preprocessor, for example, Ruby, you may have a file like: + ~~~bash + stack build # builds using the default stack.yaml + STACK_YAML=stack-ghc-7.10.yaml + stack build # builds using the given yaml file + ~~~ -***B.erb*** + === "Windows (with PowerShell)" -~~~haskell -module B where + ~~~ps + $Env:STACK_YAML='stack-ghc-9.0.2.yaml' + stack build + ~~~ -<% (1..5).each do |i| %> -test<%= i %> :: Int -test<%= i %> = <%= i %> -<% end %> -~~~ +## Setup-related -To ensure that Stack picks up changes to this file for rebuilds, add the -following lines to your `stack.yaml` file: +??? question "Where is Stack installed?" -~~~yaml -custom-preprocessor-extensions: -- erb + Command: -require-stack-version: ">= 2.6.0" -~~~ + ~~~text + stack uninstall + ~~~ -And for backwards compatability with older versions of Stack, also add the -following line to your Cabal file: + for information about where Stack is installed. - extra-source-files: B.erb +??? question "Can I change Stack's default temporary directory?" -You could also use the -[`--custom-preprocessor-extensions`](yaml_configuration.md#custom-preprocessor-extensions) -flag. + Stack downloads and extracts files to `$STACK_ROOT/programs` on most platforms, + which defaults to `~/.stack/programs`. On Windows `$LOCALAPPDATA\Programs\stack` + is used. If there is not enough free space in this directory, Stack may fail. + For instance, `stack setup` with a GHC installation requires roughly 1GB free. + If this is an issue, you can set `local-programs-path` in your + `~/.stack/config.yaml` to a directory on a file system with more free space. -## I already have GHC installed, can I still use Stack? + If you use Stack with Nix integration, be aware that Nix uses a `TMPDIR` + variable, and if it is not set Nix sets it to some subdirectory of `/run`, which + on most Linuxes is a Ramdir. Nix will run the builds in `TMPDIR`, therefore if + you don't have enough RAM you will get errors about disk space. If this happens + to you, please _manually_ set `TMPDIR` before launching Stack to some directory + on the disk. -Yes. In its default configuration, Stack will simply ignore any system GHC -installation and use a sandboxed GHC that it has installed itself. You can find -these sandboxed GHC installations in the `ghc-*` directories in the -`stack path --programs` directory. +??? question "On Windows, `stack setup` tells me to add certain paths to the PATH instead of doing it?" -If you would like Stack to use your system GHC installation, use the -[`--system-ghc`](yaml_configuration.md#system-ghc) flag or run -`stack config set system-ghc --global true` to make Stack check your PATH for a -suitable GHC by default. + With PowerShell, it is easy to automate even that step. Command: -Stack can only use a system GHC installation if its version is compatible with -the configuration of the current project, particularly the snapshot specified by -the [`snapshot`](yaml_configuration.md#snapshot) or -[`resolver`](yaml_configuration.md#resolver) key. + ~~~ps + $Env:Path = ( stack setup | %{ $_ -replace '[^ ]+ ', ''} ), $Env:Path -join ";" + ~~~ -GHC installation doesn't work for all operating systems, so in some cases you -will need to use `system-ghc` and install GHC yourself. +??? question "Does Stack install the system/C libraries that some Cabal packages depend on?" -## How does Stack determine what GHC to use? + No. This is currently out of the scope of Stack's target set of features. + Instead of attempting to automate the installation of 3rd party dependencies, we + have the following approaches for handling system dependencies: -In its default configuration, Stack determines from the current project which -GHC version, architecture etc it needs. It then looks in the `ghc-<version>` -subdirectory of the `stack path --programs` directory for a compatible GHC, -requesting to install one via `stack setup` if none is found. + * Nix and docker help make your build and execution environment deterministic + and predictable. This way, you can install system dependencies into a + container, and share this container with all developers. -If you are using the [`--system-ghc`](yaml_configuration.md/#system-ghc) flag or -have configured `system-ghc: true` either in the project `stack.yaml` or the -global `config.yaml`, Stack will use the first GHC that it finds on your PATH, -falling back on its sandboxed installations only if the found GHC doesn't comply -with the various requirements (version, architecture) that your project needs. + * If you have installed some libraries into a non-standard location, use the + [`extra-lib-dirs`](configure/yaml/non-project.md#extra-lib-dirs) option or the + [`extra-include-dirs`](configure/yaml/non-project.md#extra-include-dirs) + option to specify it. -See issue [#420](https://github.com/commercialhaskell/stack/issues/420) for a -detailed discussion of Stack's behavior when `system-ghc` is enabled. + In the future, Stack might give operating system-specific suggestions for how to + install system libraries. -## How do I get extra build tools? +??? question "How can I make Stack aware of my custom SSL certificates?" -Stack will automatically install build tools required by your packages or their -dependencies, in particular [Alex](https://hackage.haskell.org/package/alex) and -[Happy](https://hackage.haskell.org/package/happy). + === "Linux" -!!! note + Use the `SYSTEM_CERTIFICATE_PATH` environment variable to point at the directory + where you keep your SSL certificates. - This works when using LTS or nightly snapshots, not with GHC or custom - snapshots. You can manually install build tools by running, e.g., - `stack build alex happy`. -## How does Stack choose which snapshot to use when creating a new configuration file? - -It checks the two most recent LTS Haskell major versions and the most recent -Stackage Nightly for a snapshot that is compatible with all of the version -bounds in your Cabal file, favoring the most recent LTS. For more information, -see the snapshot auto-detection section in the architecture document. - -## I'd like to use my installed packages in a different directory. How do I tell Stack where to find my packages? - -Set the `STACK_YAML` environment variable to point to the `stack.yaml` -configuration file for your project. Then you can run `stack exec`, `stack ghc`, -etc., from any directory and still use your packages. + === "macOS" -## My tests are failing. What should I do? + In principle, you can use the following command to add a certificate to your + system certificate keychain: -Like all other targets, `stack test` runs test suites in parallel by default. -This can cause problems with test suites that depend on global resources such -as a database or binding to a fixed port number. A quick hack is to force stack -to run all test suites in sequence, using `stack test --jobs=1`. For test -suites to run in parallel developers should ensure that their test suites do -not depend on global resources (e.g. by asking the operating system for a random -port to bind to) and where unavoidable, add a lock in order to serialize access -to shared resources. + ~~~bash + sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate> + ~~~ -## Can I get bash autocompletion? + Some users have reported issues with this approach, see issue + [#907](https://github.com/commercialhaskell/stack/issues/907) for more + information. -Yes, see the [shell-autocompletion](shell_autocompletion.md) documentation. +## Package description format-related -## How do I update my package index? +??? question "How does Stack support the Hpack specification?" -Users of Cabal (the tool) are used to running `cabal update` regularly. You can -do the same with Stack by running `stack update`. But generally, it's not -necessary: if the package index is missing, or if a snapshot refers to -package/version that isn't available, Stack will automatically update and then -try again. If you run into a situation where Stack doesn't automatically do the -update for you, please report it as a bug. + The [Hpack](https://github.com/sol/hpack) package description format is an + alternative to that used in a Cabal file. -## Isn't it dangerous to automatically update the index? Can't that corrupt build plans? + If a package directory contains an package description file in the Hpack + format (`package.yaml`), Stack will use that file to create the + corresponding Cabal file. -No, Stack is very explicit about which packages it's going to build for you. -There are three sources of information to tell it which packages to install: -the selected snapshot, the `extra-deps` configuration value, and your local -packages. The only way to get Stack to change its build plan is to modify one -of those three. Updating the index will have no impact on Stack's behavior. + [`stack init`](commands/init_command.md) will use Hpack format package + description files, if they are present. -## I have a custom package index I'd like to use, how do I do so? + The [`with-hpack`](configure/yaml/non-project.md#with-hpack) non-project + specific configuration option or the + [`--with-hpack`](configure/global_flags.md#-with-hpack-option) global flag + can be used to specify an Hpack executable to use instead of Stack's + built-in Hpack functionality. -You can configure this in your project-level configuration file (`stack.yaml`, -by default). See [YAML configuration](yaml_configuration.md). +## Package index-related -## How can I make sure my project builds against multiple GHC versions? +??? question "How do I update my package index?" -You can create multiple YAML configuration files for your project, one for each -build plan. For example, you might set up your project directory like so: + Command: -~~~text -myproject/ - stack-ghc-9.0.2.yaml - stack-ghc-9.2.4.yaml - stack.yaml --> symlink to stack-ghc-9.2.4.yaml - myproject.cabal - src/ - ... -~~~ + ~~~text + stack update + ~~~ -When you run `stack build`, you can set the `STACK_YAML` environment variable to -indicate which build plan to use. On Unix-like operating systems command: + However, generally, it's not necessary with Stack: if the package index is + missing, or if a snapshot refers to package version that isn't available, + Stack will automatically update the package index and then try again. -~~~bash -stack build # builds using the default stack.yaml -STACK_YAML=stack-ghc-7.10.yaml -stack build # builds using the given yaml file -~~~ + If you run into a situation where Stack doesn't automatically update the + package index, please report it as a bug. -On Windows (with PowerShell) command: +??? question "Is it dangerous to update the package index automatically? Can that corrupt build plans?" -~~~ps -$Env:STACK_YAML='stack-ghc-9.0.2.yaml' -stack build -~~~ + No. Stack is explicit about which packages it's going to build. There are + three sources of information to tell Stack which packages to install: the + selected snapshot, the `extra-deps` configuration value, and your project + packages. The only way to get Stack to change its build plan is to modify + one of those three. Updating the index will have no effect on Stack's + behavior. -## I heard you can use this with Docker? +??? question "How do I use a custom package index?" -Yes, Stack supports using Docker with images that contain preinstalled Stackage -packages and the tools. See [Docker integration](docker_integration.md) for -details. + See the [`package-index`](configure/yaml/non-project.md#package-index) + non-project specific configuration option documentation. -## How do I build a statically-linked executable on Linux? +## Package-related -The way that Stack itself builds statically-linked Stack executables for Linux -is as follows: +??? question "How do I use a package version on Hackage not in a snapshot?" -* In the Cabal file, the following - [`ld-options`](https://cabal.readthedocs.io/en/stable/cabal-package.html#pkg-field-ld-options) - are set: `-static` and `-pthread`. + Add the package version to the [`extra-deps`](configure/yaml/project.md) + project-specific configuration option in the + [project-level configuration file](configure/yaml/index.md). -* The Stack command is run in a Docker container based on Alpine Linux. The - relevant Docker image repository is set out in Stack's `stack.yaml` file. See - also Olivier Benz's [GHC musl project](https://gitlab.com/benz0li/ghc-musl). +??? question "How do I use a package version not on Hackage?" -* Stack's configuration includes: + Add the location of the package version to the + [`extra-deps`](configure/yaml/project.md) project-specific configuration + option in the [project-level configuration file](configure/yaml/index.md). - ~~~yaml - extra-include-dirs: - - /usr/include - extra-lib-dirs: - - /lib - - /usr/lib - ~~~ + For further information, see the + [package location](topics/package_location.md) documentation. -* The build command is `stack build --docker --system-ghc --no-install-ghc` (on - x86_64) or - `stack build --docker --docker-stack-exe=image --system-ghc --no-install-ghc` - (on AArch64; the host Stack and the image Stack must have the same version - number). +??? question "How do I use a modified version of a package?" -## How do I use this with Travis CI? + Typically, a modified version of a package is used as a project package. + Add the location of the package to the + [`packages`](configure/yaml/project.md#packages) project-specific + configuration option in the + [project-level configuration file](configure/yaml/index.md). -See the [Travis CI instructions](travis_ci.md) + One way to get the source code for the unmodified package version is to use + the [`stack unpack`](commands/unpack_command.md). -## How do I use this with Azure CI? +??? question "I'd like to use my installed packages in a different directory. How do I tell Stack where to find my packages?" -See the [Azure CI instructions](azure_ci.md) + Set the `STACK_YAML` environment variable to point to the `stack.yaml` + configuration file for your project. Then you can run `stack exec`, `stack ghc`, + etc., from any directory and still use your packages. -## What is licensing restrictions on Windows? +## `stack build`-related -Currently, on Windows, GHC produces binaries linked statically with -[GNU Multiple Precision Arithmetic Library](https://gmplib.org/) (GMP), which is -used by [integer-gmp](https://hackage.haskell.org/package/integer-gmp) library -to provide big integer implementation for Haskell. Contrary to the majority of -Haskell code licensed under permissive BSD3 license, GMP library is licensed -under LGPL, which means resulting binaries -[have to be provided with source code or object files](http://www.gnu.org/licenses/gpl-faq.html#LGPLStaticVsDynamic). -That may or may not be acceptable for your situation. Current workaround is to -use GHC built with alternative big integer implementation called -`integer-simple`, which is free from LGPL limitations as it's pure Haskell and -does not use GMP. Unfortunately it has yet to be available out of the box with -Stack. See issue [#399](https://github.com/commercialhaskell/stack/issues/399) -for the ongoing effort and information on workarounds. +??? question "How do I use a custom preprocessor?" -## How to get a working executable on Windows? + See the + [`customer-prepocessor-extensions`](configure/yaml/project.md#custom-preprocessor-extensions) + project-specific configuration option documentation. -When executing a binary after building with `stack build` (e.g. for target -"foo"), the command `foo.exe` might complain about missing runtime libraries -(whereas `stack exec foo` works). +??? question "How do I get extra tools used during building?" -Windows is not able to find the necessary C++ libraries from the standard -prompt because they're not in the PATH environment variable. `stack exec` works -because it's modifying PATH to include extra things. + Stack will automatically install tools used during building required by your + packages or their dependencies, in particular + [Alex](https://hackage.haskell.org/package/alex) and + [Happy](https://hackage.haskell.org/package/happy). -Those libraries are shipped with GHC (and, theoretically in some cases, MSYS2). -The easiest way to find them is `stack exec which`. For example, command: + !!! note -~~~text -stack exec -- which libstdc++-6.dll -/c/Users/Michael/AppData/Local/Programs/stack/i386-windows/ghc-7.8.4/mingw/bin/libstdc++-6.dll -~~~ + This works when using LTS or nightly snapshots, not with GHC or custom + snapshots. You can manually install tools used during building by running, + e.g., `stack build alex happy`. -A quick workaround is adding this path to the PATH environment variable or -copying the files somewhere Windows finds them (see -https://msdn.microsoft.com/de-de/library/7d83bc18.aspx). +??? question "My tests are failing. What should I do?" -See issue [#425](https://github.com/commercialhaskell/stack/issues/425). + Like all other targets, `stack test` runs test suites in parallel by default. + This can cause problems with test suites that depend on global resources such + as a database or binding to a fixed port number. A quick hack is to force stack + to run all test suites in sequence, using `stack test --jobs=1`. For test + suites to run in parallel developers should ensure that their test suites do + not depend on global resources (e.g. by asking the operating system for a random + port to bind to) and where unavoidable, add a lock in order to serialize access + to shared resources. -Another issue that may arise with building on Windows is as follows. The default -location of Stack's programs folder is `%LOCALAPPDATA\Programs\stack`. If there -is a space character in the `%LOCALAPPDATA%` path this may, in some -circumstances, cause problems with building packages that make use of the GNU -project's `autoconf` package and `configure` shell script files. It may be -necessary to override the default location of Stack's programs folder. See the -[local-programs-path](yaml_configuration.md#local-programs-path) option for more -information. +??? question "How do I use Stack with Docker?" -See issue [#4726](https://github.com/commercialhaskell/stack/issues/4726). + See the [Docker integration](topics/docker_integration.md) documentation. -## Can I change Stack's default temporary directory? +??? question "How do I build a statically-linked executable on Linux?" -Stack downloads and extracts files to `$STACK_ROOT/programs` on most platforms, -which defaults to `~/.stack/programs`. On Windows `$LOCALAPPDATA\Programs\stack` -is used. If there is not enough free space in this directory, Stack may fail. -For instance, `stack setup` with a GHC installation requires roughly 1GB free. -If this is an issue, you can set `local-programs-path` in your -`~/.stack/config.yaml` to a directory on a file system with more free space. + The way that Stack itself builds statically-linked Stack executables for Linux + is as follows: -If you use Stack with Nix integration, be aware that Nix uses a `TMPDIR` -variable, and if it is not set Nix sets it to some subdirectory of `/run`, which -on most Linuxes is a Ramdir. Nix will run the builds in `TMPDIR`, therefore if -you don't have enough RAM you will get errors about disk space. If this happens -to you, please _manually_ set `TMPDIR` before launching Stack to some directory -on the disk. + * In the Cabal file, the following + [`ld-options`](https://cabal.readthedocs.io/en/stable/cabal-package.html#pkg-field-ld-options) + are set: `-static` and `-pthread`. -## Why doesn't Stack rebuild my project when I specify `--ghc-options` on the command line? + * The Stack command is run in a Docker container based on Alpine Linux. The + relevant Docker image repository is set out in Stack's `stack.yaml` file. See + also Olivier Benz's [GHC musl project](https://gitlab.com/benz0li/ghc-musl). -Because GHC options often only affect optimization levels and warning behavior, -Stack doesn't recompile when it detects an option change by default. This -behavior can be changed though by setting the -[`rebuild-ghc-options` option](yaml_configuration.md#rebuild-ghc-options) to -`true`. + * Stack's configuration includes: -To force recompilation manually, use the `--force-dirty` flag. If this still -doesn't lead to a rebuild, add the `-fforce-recomp` flag to your -`--ghc-options`. + ~~~yaml + extra-include-dirs: + - /usr/include + extra-lib-dirs: + - /lib + - /usr/lib + ~~~ -## Why doesn't Stack apply my `--ghc-options` to my dependencies? + * The build command is `stack build --docker --system-ghc --no-install-ghc` (on + x86_64) or + `stack build --docker --docker-stack-exe=image --system-ghc --no-install-ghc` + (on AArch64; the host Stack and the image Stack must have the same version + number). -By default, Stack applies command line GHC options only to -[project packages](yaml_configuration.md#packages). For an explanation of this -choice see this discussion on issue -[#827](https://github.com/commercialhaskell/stack/issues/827#issuecomment-133263678). +??? question "Why doesn't Stack rebuild my project when I specify `--ghc-options` on the command line?" -If you still want to set specific GHC options for a dependency, use the -[`ghc-options`](yaml_configuration.md#ghc-options) option in your -YAML configuration file. + Because GHC options often only affect optimization levels and warning behavior, + Stack doesn't recompile when it detects an option change by default. This + behavior can be changed though by setting the + [`rebuild-ghc-options` option](configure/yaml/non-project.md#rebuild-ghc-options) + to `true`. -To change the set of packages that command line GHC options apply to, use the [`apply-ghc-options`](yaml_configuration.md#apply-ghc-options) option. + To force recompilation manually, use the `--force-dirty` flag. If this still + doesn't lead to a rebuild, add the `-fforce-recomp` flag to your + `--ghc-options`. -## `stack setup` on a Windows system only tells me to add certain paths to the PATH variable instead of doing it +??? question "Why doesn't Stack apply my `--ghc-options` to my dependencies?" -With PowerShell, it is easy to automate even that step. Command: + By default, Stack applies command line GHC options only to + [project packages](configure/yaml/project.md#packages). For an explanation of + this choice see this discussion on issue + [#827](https://github.com/commercialhaskell/stack/issues/827#issuecomment-133263678). -~~~ps -$Env:Path = ( stack setup | %{ $_ -replace '[^ ]+ ', ''} ), $Env:Path -join ";" -~~~ + If you still want to set specific GHC options for a dependency, use the + [`ghc-options`](configure/yaml/non-project.md#ghc-options) option in your YAML + configuration file. -## How do I reset/remove Stack (such as to do a completely fresh build)? + To change the set of packages that command line GHC options apply to, use the [`apply-ghc-options`](configure/yaml/non-project.md#apply-ghc-options) option. -The first thing to remove is project-specific `.stack-work` directory within -the project's directory. Next, remove the Stack root directory overall. You may -have errors if you remove the latter but leave the former. Removing Stack -itself will relate to how it was installed, and if you used GHC installed -outside of Stack, that would need to be removed separately. +??? question "How does Stack handle parallel builds?" -## How does Stack handle parallel builds? What exactly does it run in parallel? + See issue [#644](https://github.com/commercialhaskell/stack/issues/644) for more + details. -See issue [#644](https://github.com/commercialhaskell/stack/issues/644) for more -details. +??? question "I get strange `ld` errors about recompiling with `-fPIC`" -## I get strange `ld` errors about recompiling with "-fPIC" + (Updated in January 2019) -(Updated in January 2019) + This is related to more recent versions of Linux distributions that have GCC + with PIE enabled by default. The continuously-updated distros like Arch, in + particular, had been in flux with this change and the upgrading + libtinfo6/ncurses6, and there were some workarounds attempted in Stack that + ended up causing trouble as these distros evolved. -This is related to more recent versions of Linux distributions that have GCC -with PIE enabled by default. The continuously-updated distros like Arch, in -particular, had been in flux with this change and the upgrading -libtinfo6/ncurses6, and there were some workarounds attempted in Stack that -ended up causing trouble as these distros evolved. + GHC added official support for this setup in 8.0.2, so if you are using an + older version your best bet is to upgrade. You may be able to work around it + for older versions by editing `~/.stack/programs/x86_64-osx/ghc-VER/lib/ghc- + VER/settings` (replace `VER` with the GHC version) and adding `-no-pie` (or + `--no-pie` in the case of Gentoo, at least as of December 2017) to the __C + compiler link flags__. -GHC added official support for this setup in 8.0.2, so if you are using an -older version your best bet is to upgrade. You may be able to work around it -for older versions by editing `~/.stack/programs/x86_64-osx/ghc-VER/lib/ghc- -VER/settings` (replace `VER` with the GHC version) and adding `-no-pie` (or -`--no-pie` in the case of Gentoo, at least as of December 2017) to the __C -compiler link flags__. + If `stack setup` complains that there is no `linuxNN-*-nopie` bindist available, + try adding `ghc-build: *` (replacing the `*` with the actual value that + precedes `-nopie`, which may be empty) to your `~/.stack/config.yaml` (this + will no longer be necessary for stack >= 1.7). -If `stack setup` complains that there is no `linuxNN-*-nopie` bindist available, -try adding `ghc-build: *` (replacing the `*` with the actual value that -precedes `-nopie`, which may be empty) to your `~/.stack/config.yaml` (this -will no longer be necessary for stack >= 1.7). + If you are experiencing this with GHC >= 8.0.2, try running + `stack setup --reinstall` if you've upgraded your Linux distribution or you set + up GHC before late December 2017. -If you are experiencing this with GHC >= 8.0.2, try running -`stack setup --reinstall` if you've upgraded your Linux distribution or you set -up GHC before late December 2017. + If GHC doesn't recognize your C compiler as being able to use `-no-pie`, this + can happen even with GCC and Clang, it might be necessary to enable this feature + manually. To do this, just change + `("C compiler supports -no-pie", "NO"),` to + `("C compiler supports -no-pie", "YES"),` + in the file `~/.stack/programs/x86_64-osx/ghc-VER/lib/ghc-VER/settings`. -If GHC doesn't recognize your C compiler as being able to use `-no-pie`, this -can happen even with GCC and Clang, it might be necessary to enable this feature -manually. To do this, just change -`("C compiler supports -no-pie", "NO"),` to -`("C compiler supports -no-pie", "YES"),` -in the file `~/.stack/programs/x86_64-osx/ghc-VER/lib/ghc-VER/settings`. + If you are still having trouble after trying the above, check the following for + more possible workarounds: -If you are still having trouble after trying the above, check the following for -more possible workarounds: + * Previous version of this [FAQ entry](https://docs.haskellstack.org/en/v1.6.3/faq/#i-get-strange-ld-errors-about-recompiling-with-fpic) + * Related issues: + [#3518](https://github.com/commercialhaskell/stack/issues/3518), + [#2712](https://github.com/commercialhaskell/stack/issues/2712), + [#3630](https://github.com/commercialhaskell/stack/issues/3630), + [#3648](https://github.com/commercialhaskell/stack/issues/3648) - * Previous version of this [FAQ entry](https://docs.haskellstack.org/en/v1.6.3/faq/#i-get-strange-ld-errors-about-recompiling-with-fpic) - * Related issues: - [#3518](https://github.com/commercialhaskell/stack/issues/3518), - [#2712](https://github.com/commercialhaskell/stack/issues/2712), - [#3630](https://github.com/commercialhaskell/stack/issues/3630), - [#3648](https://github.com/commercialhaskell/stack/issues/3648) +??? question "Where does the output from `--ghc-options=-ddump-splices` (and other `-ddump*` options) go?" -## Where does the output from `--ghc-options=-ddump-splices` (and other `-ddump*` options) go? + These are written to `*.dump-*` files inside the package's `.stack-work` + directory. Specifically, they will be available at + `PKG-DIR/$(stack path --dist-dir)/build/SOURCE-PATH`, where `SOURCE-PATH` is the + path to the source file, relative to the location of the Cabal file. When + building named components such as test-suites, `SOURCE-PATH` will also include + `COMPONENT/COMPONENT-tmp`, where `COMPONENT` is the name of the component. -These are written to `*.dump-*` files inside the package's `.stack-work` -directory. Specifically, they will be available at -`PKG-DIR/$(stack path --dist-dir)/build/SOURCE-PATH`, where `SOURCE-PATH` is the -path to the source file, relative to the location of the Cabal file. When -building named components such as test-suites, `SOURCE-PATH` will also include -`COMPONENT/COMPONENT-tmp`, where `COMPONENT` is the name of the component. +??? question "Why is DYLD_LIBRARY_PATH ignored?" -## <a name="dyld-library-path-ignored"></a>Why is DYLD_LIBRARY_PATH ignored? + If you are on Mac OS X 10.11 ("El Capitan") or later, there is a GHC issue + [#11617](https://ghc.haskell.org/trac/ghc/ticket/11617) which prevents the + `DYLD_LIBRARY_PATH` environment variable from being passed to GHC (see issue + [#1161](https://github.com/commercialhaskell/stack/issues/1161)) when System + Integrity Protection (a.k.a. "rootless") is enabled. There are two known + workarounds: -If you are on Mac OS X 10.11 ("El Capitan") or later, there is a GHC issue -[#11617](https://ghc.haskell.org/trac/ghc/ticket/11617) which prevents the -`DYLD_LIBRARY_PATH` environment variable from being passed to GHC (see issue -[#1161](https://github.com/commercialhaskell/stack/issues/1161)) when System -Integrity Protection (a.k.a. "rootless") is enabled. There are two known -workarounds: + 1. Known to work in all cases: + [disable System Integrity Protection](http://osxdaily.com/2015/10/05/disable-rootless-system-integrity-protection-mac-os-x/). + **WARNING: Disabling SIP will severely reduce the security of your system, so only do this if absolutely necessary!** + 2. Experimental: modify GHC's shell script wrappers to use a shell outside the + protected directories (see issue + [#1161](https://github.com/commercialhaskell/stack/issues/1161#issuecomment-186690904)). - 1. Known to work in all cases: - [disable System Integrity Protection](http://osxdaily.com/2015/10/05/disable-rootless-system-integrity-protection-mac-os-x/). - **WARNING: Disabling SIP will severely reduce the security of your system, so only do this if absolutely necessary!** - 2. Experimental: modify GHC's shell script wrappers to use a shell outside the - protected directories (see issue - [#1161](https://github.com/commercialhaskell/stack/issues/1161#issuecomment-186690904)). +??? question "How do I get `verbose` output from GHC when I build?" -## <a name="usr-bin-ar-permission-denied"></a>Why do I get a `/usr/bin/ar: permission denied` error? + Set the [`--ghc-options`](commands/build_command.md#-ghc-options-option) + option of `stack build` to `-v`. -## Why is the `--` argument separator ignored in Windows PowerShell +## Snapshot-related -Some versions of Windows PowerShell don't pass the `--` to programs (see issue -[#813](https://github.com/commercialhaskell/stack/issues/813)). The workaround -is to quote the `"--"`. For example, command: +??? question "How does Stack choose which snapshot to use when creating a project-level configuration file?" -~~~ps -stack exec "--" cabal --version -~~~ + See the [`stack init`](commands/init_command.md) command documentation. -This is known to be a problem on Windows 7, but seems to be fixed on Windows 10. +## CI-related -## Does Stack also install the system/C libraries that some Cabal packages depend on? +??? question "How do I use Stack with Travis CI?" -No, this is currently out of the scope of Stack's target set of features. -Instead of attempting to automate the installation of 3rd party dependencies, we -have the following approaches for handling system dependencies: + See the [Travis CI](topics/travis_ci.md) documentation. -* Nix and docker help make your build and execution environment deterministic - and predictable. This way, you can install system dependencies into a - container, and share this container with all developers. +??? question "How do I use Stack with Azure CI?" -* If you have installed some libraries into a non-standard location, use the - [`extra-lib-dirs`](yaml_configuration.md#extra-lib-dirs) option or the - [`extra-include-dirs`](yaml_configuration.md#extra-include-dirs) option to - specify it. + See the [Azure CI](topics/azure_ci.md) documentation. -In the future, Stack might give operating system-specific suggestions for how to -install system libraries. +## Linux-related -## How can I make Stack aware of my custom SSL certificates? +??? question "How do fix error [S-9443] for 'linux64-ncurses6'?" -### macOS + Most Linux distributions have standardized on providing `libtinfo.so.6`, + either directly or as a symbolic link to `libncursesw.so.6`. As such, there + are no GHC binary distributions that link to `libncursesw.so.6` after + GHC 8.2.2. -In principle, you can use the following command to add a certificate to your -system certificate keychain: + This error can be prevented by creating a symbolic link to + `libncursesw.so.6` using name `libtinfo.so.6`. Command: -~~~bash -sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain <certificate> -~~~ + ~~~bash + ln -s /usr/lib/libncursesw.so.6 /usr/lib/libtinfo.so.6 + ~~~ -Some users have reported issues with this approach, see issue -[#907](https://github.com/commercialhaskell/stack/issues/907) for more -information. + Root privileges may be required. -### Other *NIX OSs +## macOS-related -Use the `SYSTEM_CERTIFICATE_PATH` environment variable to point at the directory -where you keep your SSL certificates. +??? question "On macOS, how do I resolve linker errors when running `stack setup` or `stack build`?" -## How do I get `verbose` output from GHC when I build? + This is likely to be caused by having both a LLVM installation and default + Apple Clang compiler on the PATH. The symptom of this issue is a linker + error "bad relocation (Invalid pointer diff)". The compiler picks up + inconsistent versions of binaries and the mysterious error occurs. -Add `ghc-options: -vN` to the Cabal file or pass it via -`stack build --ghc-options="-v"`. + The workaround is to remove LLVM binaries from the PATH. -## Does Stack support the Hpack specification? +??? question "On macOS, how do I suppress `'-nopie'` warnings with `stack build`?" -Yes: + ~~~bash + clang: warning: argument unused during compilation: '-nopie' + [-Wunused-command-line-argument] + ~~~ -* If a package directory contains an [Hpack](https://github.com/sol/hpack) - `package.yaml` file, then Stack will use it to generate a Cabal file when - building the package. -* You can run `stack init` to initialize a `stack.yaml` file regardless of - whether your packages are declared with Cabal files or with Hpack - `package.yaml` files. -* You can use the `with-hpack` YAML configuration or command line option to - specify an Hpack executable to use instead of Stack's in-built Hpack - functionality. + This warning is shown when compiler support of `-no-pie` is expected but + unavailable. It's possible to bypass the warning for a specific version of GHC + by modifying a global setting: -## How do I resolve linker errors when running `stack setup` or `stack build` on macOS? + ~~~bash + # ~/.stack/programs/x86_64-osx/ghc-8.2.2/lib/ghc-8.2.2/settings + -- ("C compiler supports -no-pie", "YES"), + ++ ("C compiler supports -no-pie", "NO"), + ~~~ -This is likely to be caused by having both a LLVM installation and default Apple -Clang compiler on the PATH. The symptom of this issue is a linker error "bad -relocation (Invalid pointer diff)". The compiler picks up inconsistent versions -of binaries and the mysterious error occurs. + **Note that we're fixing `ghc-8.2.2` in this case; repeat for other versions as necessary.** + You should apply this fix for the version of GHC that matches your snapshot. -The workaround is to remove LLVM binaries from the PATH. + Issue [#4009](https://github.com/commercialhaskell/stack/issues/4009) goes into + further detail. -## How do I suppress `'-nopie'` warnings with `stack build` on macOS? +## Windows-related -~~~bash -clang: warning: argument unused during compilation: '-nopie' - [-Wunused-command-line-argument] -~~~ +??? question "What is licensing restrictions on Windows?" -This warning is shown when compiler support of `-no-pie` is expected but -unavailable. It's possible to bypass the warning for a specific version of GHC -by modifying a global setting: + Currently, on Windows, GHC produces binaries linked statically with + [GNU Multiple Precision Arithmetic Library](https://gmplib.org/) (GMP), which is + used by [integer-gmp](https://hackage.haskell.org/package/integer-gmp) library + to provide big integer implementation for Haskell. Contrary to the majority of + Haskell code licensed under permissive BSD3 license, GMP library is licensed + under LGPL, which means resulting binaries + [have to be provided with source code or object files](http://www.gnu.org/licenses/gpl-faq.html#LGPLStaticVsDynamic). + That may or may not be acceptable for your situation. Current workaround is to + use GHC built with alternative big integer implementation called + `integer-simple`, which is free from LGPL limitations as it's pure Haskell and + does not use GMP. Unfortunately it has yet to be available out of the box with + Stack. See issue [#399](https://github.com/commercialhaskell/stack/issues/399) + for the ongoing effort and information on workarounds. -~~~bash -# ~/.stack/programs/x86_64-osx/ghc-8.2.2/lib/ghc-8.2.2/settings --- ("C compiler supports -no-pie", "YES"), -++ ("C compiler supports -no-pie", "NO"), -~~~ +??? question "How to get a working executable on Windows?" -**Note that we're fixing `ghc-8.2.2` in this case; repeat for other versions as necessary.** -You should apply this fix for the version of GHC that matches your snapshot. + When executing a binary after building with `stack build` (e.g. for target + "foo"), the command `foo.exe` might complain about missing runtime libraries + (whereas `stack exec foo` works). -Issue [#4009](https://github.com/commercialhaskell/stack/issues/4009) goes into -further detail. + Windows is not able to find the necessary C++ libraries from the standard + prompt because they're not in the PATH environment variable. `stack exec` works + because it's modifying PATH to include extra things. -## How do I install GHC in Stack when it fails with the error: Missing ghc bindist for "linux64-ncurses6"? + Those libraries are shipped with GHC (and, theoretically in some cases, MSYS2). + The easiest way to find them is `stack exec which`. For example, command: -Example Error: + ~~~text + stack exec -- which libstdc++-6.dll + /c/Users/Michael/AppData/Local/Programs/stack/i386-windows/ghc-7.8.4/mingw/bin/libstdc++-6.dll + ~~~ -~~~text -No setup information found for ghc-8.6.4 on your platform. -This probably means a GHC bindist has not yet been added for OS key 'linux64-ncurses6'. -Supported versions: ghc-7.10.3, ghc-8.0.1, ghc-8.0.2, ghc-8.2.1, ghc-8.2.2 -~~~ + A quick workaround is adding this path to the PATH environment variable or + copying the files somewhere Windows finds them (see + https://msdn.microsoft.com/de-de/library/7d83bc18.aspx). -Most Linux distributions have standardized on providing libtinfo.so.6 (either -directly or as a symlink to libncursesw.so.6). As such, there aren't GHC 8.6.* -bindists that link to libncursesw.so.6 available. + See issue [#425](https://github.com/commercialhaskell/stack/issues/425). -So creating a symlink to libncursesw.so.6 as libtinfo.so.6 can prevent this -error (root privileges might be required). Command: + Another issue that may arise with building on Windows is as follows. The default + location of Stack's programs folder is `%LOCALAPPDATA\Programs\stack`. If there + is a space character in the `%LOCALAPPDATA%` path this may, in some + circumstances, cause problems with building packages that make use of the GNU + project's `autoconf` package and `configure` shell script files. It may be + necessary to override the default location of Stack's programs folder. See the + [local-programs-path](configure/yaml/non-project.md#local-programs-path) option + for more information. -~~~bash -ln -s /usr/lib/libncursesw.so.6 /usr/lib/libtinfo.so.6 -~~~ + See issue [#4726](https://github.com/commercialhaskell/stack/issues/4726).
− doc/ghc_command.md
@@ -1,21 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack ghc` command - -~~~text -stack ghc [-- ARGUMENT(S) (e.g. stack ghc -- X.hs -o x)] - [--[no-]ghc-package-path] [--[no-]stack-exe] [--package PACKAGE] - [--rts-options RTSFLAG] [--cwd DIR] -~~~ - -`stack ghc` has the same effect as, and is provided as a shorthand for, -[`stack exec ghc`](exec_command.md), with the exception of the `--package` -option. - -Pass the option `--package <package(s)>` to add the initial GHC argument -`-package-id=<unit_id>`, where `<unit_id>` is the unit ID of the specified -package in the installed package database. The option can be a list of package -names or package identifiers separated by spaces. The option can also be -specified multiple times. The approach taken to these packages is the same as if -they were specified as targets to -[`stack build`](build_command.md#target-syntax).
− doc/ghci.md
@@ -1,161 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack ghci` and `stack repl` commands - -~~~text -stack ghci [TARGET/FILE] [--pedantic] [--ghci-options OPTIONS] - [--ghc-options OPTIONS] [--flag PACKAGE:[-]FLAG] [--with-ghc GHC] - [--[no-]load] [--package PACKAGE] [--main-is TARGET] - [--load-local-deps] [--[no-]package-hiding] [--only-main] [--trace] - [--profile] [--no-strip] [--[no-]test] [--[no-]bench] -~~~ - -A read–evaluate–print loop (REPL) environment takes single user inputs, executes -them, and returns the result to the user. GHCi is GHC's interactive environment. -The `stack ghci` or `stack repl` commands, which are equivalent, allow you to -load components and files of your project into GHCi. - -The command accepts the same TARGET syntax as -[`stack build`](build_command.md#target-syntax). By default: - -* Stack loads up GHCi with all the library and executable components of all the - packages in the project. Pass the flag `--test` to include test suite - components (unlike `stack build`, test suites will not be run). Pass the flag - `--bench` to include benchmark components (unlike `stack build`, benchmarks - will not be run). - -It is also possible to specify a module source code file. For example: - -~~~text -stack ghci src/MyFile.hs -~~~ - -Stack will identify which component the file is associated with, and use the -options from that component. - -Pass the `--package` option to load GHCi with an additional package that is not -a direct dependency of your components. This option can be specified multiple -times. - -Pass the option `--flag <package_name>:<flag_name>` or -`--flag <package_name:-<flag_name>` to set or unset a Cabal flag. This option -can be specified multiple times. The same Cabal flag name can be set (or unset) -for multiple packages with: - -~~~text ---flag *:[-]<flag_name> -~~~ - -!!! note - - In order to set a Cabal flag for a GHC boot package, the package must either - be an extra-dep or the package version must be specified with the - `--package` option. - -By default: - -* Stack uses the GHC specified in Stack's configuration. Pass the `--with-ghc` - option with a file path to the executable to specify a different GHC - executable; - -* Stack performs an inital build step. Pass the `--no-build` flag to skip the - step. Pass the `--ghc-options` option to pass flags or options to GHC. Pass - the `--profile`, `--no-strip`, `--trace` flags for the same behaviour as in - the case of the `stack build` command. - - !!! info - - Not performing the initial build step speeds up the startup of GHCi. It - only works if the dependencies of the loaded packages have already been - built. - -* Stack runs GHCi via `ghc --interactive`. Pass the `--ghc-options` option to - pass flags or options to GHC (during the initial build step) and to GHCi. - Pass the `--pedantic` flag to pass the GHC options `-Wall` and `-Werror` to - GHCi (only). Pass the `--ghci-options` option to pass flags or options to - GHCi (only). - -* Stack configures GHCi to hide unnecessary packages, unless no packages are - targetted and no additional packages are specified. Pass the - `--package-hiding` flag to hide unnecessary packages or - `--no-package-hiding` flag not to hide unnecessary packages. - -* Stack loads and imports all of the modules for each target. Pass the - `--no-load` flag to skip the loading of modules. Pass the `--only-main` flag - to skip the loading of modules other than the main module. Pass the - `--load-local-deps` flag to include all local dependencies of targets. - - !!! info - - Not loading modules speeds up the startup of GHCi. Once in GHCi, you can - use `:load myModule` to load a specific module in your project. - - !!! info - - The `--only-main` flag can be useful if: - - 1. You're loading the project in order to run it in GHCi (e.g. via - `main`), and you intend to reload while developing. Without flag, - you will need to quit and restart GHCi whenever a module gets - deleted. With the flag, reloading should work fine in this case. - - 2. If many of your modules have exports named the same thing, then - you'll need to refer to them using qualified names. To avoid this, - use the `--only-main` flag to start with a blank slate and just - import the modules you are interested in. - -* If there are multiple definitions for the `Main` module, Stack will ask you - to select one from a list of options. Pass the `--main-is <target>` option - to specific which `Main` module to load. - -Stack combines all of the GHC options of components. - -!!! note - - Combining GHC options should work out when packages share similar - conventions. However, conflicts may arise, such as when one component - defines default extensions which aren't assumed by another. For example, - specifying `NoImplicitPrelude` in one component but not another is likely to - cause failures. GHCi will be run with `-XNoImplicitPrelude`, but it is - likely that modules in the other component assume that the `Prelude` is - implicitly imported. - -`stack ghci` configures GHCi by using a GHCi script file. Such files are located -in subdirectories of `<XDG_CACHE_HOME>/stack/ghci-script`, where -`<XDG_CACHE_HOME>` refers to the -[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) -for user-specific non-essential (cached) data. - -=== "Unix-like" - - The default for `<XDG_CACHE_HOME>` is `$HOME/.cache`. - -=== "Windows" - - On Windows, the default for `<XDG_CACHE_HOME>` is `%LOCALAPPDATA%`. - -## Running plain GHCi - -`stack ghci` always runs GHCi configured to load code from packages in your -project. In particular, this means it passes in flags like `-hide-all-packages` -and `-package-id=` in order to configure which packages are visible to GHCi. - -For doing experiments which just involve packages installed in your databases, -it may be useful to run GHCi plainly like: - -~~~text -stack exec ghci -~~~ - -This will run a plain GHCi in an environment which includes `GHC_PACKAGE_PATH`, -and so will have access to your databases. - -!!! note - - Running `stack ghci` on a pristine copy of the code doesn't currently build - libraries - (issue [#2790](https://github.com/commercialhaskell/stack/issues/2790)) or - internal libraries - (issue [#4148](https://github.com/commercialhaskell/stack/issues/4148)). It - is recommended to always use `stack build` before using `stack ghci`, until - these two issues are closed.
− doc/global_flags.md
@@ -1,351 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Stack's global flags and options - -Stack can also be configured by flags and options on the command line. Global -flags and options apply to all of Stack's commands. In addition, all of Stack's -commands accept the `--setup-info-yaml` and `--snapshot-location-base` options -and the `--help` flag. - -## `--allow-different-user` flag - -Restrictions: POSIX systems only - -Default: True, if inside Docker; false otherwise - -Enable/disable permitting users other than the owner of the -[Stack root](stack_root.md) directory to use a Stack installation. For further -information, see the documentation for the corresponding non-project specific -configuration [option](yaml_configuration.md#allow-different-user). - -## `--arch` option - -Pass the option `--arch <architecture>` to specify the relevant machine -architecture. For further information, see the documentation for the -corresponding non-project specific configuration -[option](yaml_configuration.md#arch). - -## `--color` or `-colour` options - -Pass the option `stack --color <when>` to specify when to use color in output. -For further information, see the documentation for the corresponding non-project -specific configuration [option](yaml_configuration.md#color). - -## `--compiler` option - -Pass the option `--compiler <compiler>` to specify the compiler. For further -information, see the [YAML configuration](yaml_configuration.md#compiler) -documentation. - -## `--custom-preprocessor-extensions` option - -Pass the option `--custom-preprocessor-extensions <extension>` to specify an -extension used for a custom preprocessor. For further information, see the -documentation for the corresponding non-project specific configuration -[option](yaml_configuration.md#custom-preprocessor-extensions). - -## `--docker*` flags and options - -Stack supports automatically performing builds inside a Docker container. For -further information see `stack --docker-help` or the -[Docker integratiom](docker_integration.md) documentation. - -## `--[no-]dump-logs` flag - -Default: Dump warning logs - -Enables/disables the dumping of the build output logs for project packages to -the console. For further information, see the documentation for the -corresponding non-project specific configuration -[option](yaml_configuration.md#dump-logs). - -## `--extra-include-dirs` option - -Pass the option `--extra-include-dirs <director>` to specify an extra directory -to check for C header files. The option can be specified multiple times. For -further information, see the documentation for the corresponding non-project -specific configuration [option](yaml_configuration.md#extra-include-dirs). - -## `--extra-lib-dirs` option - -Pass the option `--extra-lib-dirs <director>` to specify an extra directory -to check for libraries. The option can be specified multiple times. For further -information, see the documentation for the corresponding non-project specific -configuration [option](yaml_configuration.md#extra-lib-dirs). - -## `--ghc-build` option - -Pass the option `--ghc-build <build>` to specify the relevant specialised GHC -build. For further information, see the documentation for the corresponding -non-project specific configuration [option](yaml_configuration.md#ghc-build). - -## `--ghc-variant` option - -Pass the option `--ghc-variant <variant>` to specify the relevant GHC variant. -For further information, see the documentation for the corresponding non-project -specific configuration [option](yaml_configuration.md#ghc-variant). - -## `--hpack-numeric-version` flag - -Pass the flag `--hpack-numeric-version` to cause Stack to report the numeric -version of its built-in Hpack library to the standard output stream (e.g. -`0.35.0`) and quit. - -## `--[no-]install-ghc` flag - -Default: Enabled - -Enables/disables the download and instalation of GHC if necessary. For further -information, see the documentation for the corresponding non-project specific -configuration [option](yaml_configuration.md#install-ghc). - -## `--jobs` or `-j` option - -Pass the option `--jobs <number_of_jobs>` to specify the number of concurrent -jobs (Stack actions during building) to run. - -When [building GHC from source](yaml_configuration.md#building-ghc-from-source), -specifies the `-j[<n>]` flag of GHC's Hadrian build system. - -By default, Stack specifies a number of concurrent jobs equal to the number of -CPUs (cores) that the machine has. In some circumstances, that default can cause -some machines to run out of memory during building. If those circumstances -arise, specify `--jobs 1`. - -This configuration option is distinct from GHC's own `-j[<n>]` flag, which -relates to parallel compilation of modules within a package. - -For further information, see the documentation for the corresponding non-project -specific configuration option: [`jobs`](yaml_configuration.md#jobs). - -## `--local-bin-path` option - -Pass the option `--local-bin-path <directory>` to set the target directory for -[`stack build --copy-bins`](build_command.md#-no-copy-bins-flag) and -`stack install`. An absolute or relative path can be specified. A relative path -at the command line is always assumed to be relative to the current directory. - -For further information, see the documentation for the corresponding non-project -specific configuration [option](yaml_configuration.md#local-bin-path). - -## `--lock-file` option - -Default: `read-write`, if snapshot specified in YAML configuration file; -`read-only`, if a different snapshot is specified on the command line. - -Pass the option `--lock-file <mode>` to specify how Stack interacts with lock -files. Valid modes are: - -* `error-on-write`: Stack reports an error, rather than write a lock file; -* `ignore`: Stack ignores lock files; -* `read-only`: Stack only reads lock files; and -* `read-write`: Stack reads and writes lock files. - -## `--[no-]modify-code-page` flag - -Restrictions: Windows systems only - -Default: Enabled - -Enables/disables setting the codepage to support UTF-8. For further information, -see the documentation for the corresponding non-project specific configuration -[option](yaml_configuration.md#modify-code-page). - -## `--nix*` flags and options - -Stack can be configured to integrate with Nix. For further information, see -`stack --nix-help` or the [Nix integration](nix_integration.md) documentation. - -## `--numeric-version` flag - -Pass the flag `--numeric-version` to cause Stack to report its numeric version -to the standard output stream (e.g. `2.9.1`) and quit. - -## `--[no-]plan-in-log` flag - -[:octicons-tag-24: 2.13.1](https://github.com/commercialhaskell/stack/releases/tag/v2.13.1) - -Default: Disabled - -Enables/disables the logging of build plan construction in debug output. -Information about the build plan construction can be lengthy. If you do not need -it, it is best omitted from the debug output. - -## `--resolver` option - -A synonym for the [`--snapshot` option](#snapshot-option) to specify the -snapshot resolver. - -## `--[no-]rsl-in-log` flag - -[:octicons-tag-24: 2.9.1](https://github.com/commercialhaskell/stack/releases/tag/v2.9.1) - -Default: Disabled - -Enables/disables the logging of the raw snapshot layer (rsl) in debug output. -Information about the raw snapshot layer can be lengthy. If you do not need it, -it is best omitted from the debug output. - -## `--[no-]script-no-run-compile` flag - -Default: Disabled - -Enables/disables the use of options `--no-run --compile` with the -[`stack script` command](script_command.md). - -## `--silent` flag - -Equivalent to the `--verbosity silent` option. - -## `--[no-]skip-ghc-check` option - -Default: Disabled - -Enables/disables the skipping of checking the GHC version and architecture. For -further information, see the documentation for the corresponding non-project -specific configuration [option](yaml_configuration.md#skip-ghc-check). - -## `--[no-]skip-msys` option - -Restrictions: Windows systems only - -Default: Disabled - -Enables/disables the skipping of checking for the Stack-supplied MSYS2 (and -installing that MSYS2, if it is not installed) when Stack is setting up the -environment. For further information, see the documentation for the -corresponding non-project specific configuration -[option](yaml_configuration.md#skip-msys). - -## `--snapshot` option - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -Pass the option `--snapshot <snapshot>` to specify the snapshot. For further -information, see the [YAML configuration](yaml_configuration.md#snapshot) -documentation. - -At the command line (only): - -* `--snapshot lts-<major_version>` specifies the latest Stackage LTS Haskell - snapshot with the specified major version; -* `--snapshot lts` specifies, from those with the greatest major version, the - latest Stackage LTS Haskell snapshot; -* `--snapshot nightly` specifies the most recent Stackage Nightly snapshot; - and -* `--snapshot global` specifies the snapshot specified by the project-level - configuration file in the `global-project` directory in the - [Stack root](stack_root.md#global-project-directory). - -## `--stack-colors` or `--stack-colours` options - -Pass the option `--stack-colors <styles>` to specify Stack's output styles. For -further information, see the documentation for the corresponding non-project -specific configuration [option](yaml_configuration.md#stack-colors). - -## `--stack-root` option - -Overrides: `STACK_ROOT` environment variable - -Pass the option `--stack-root <absolute_path_to_the_Stack_root>` to specify the -path to the [Stack root](stack_root.md) directory. The path must be an absolute -one. - -## `--stack-yaml` option - -Default: `stack.yaml` - -Overrides: `STACK_YAML` enviroment variable - -Pass the option `--stack-yaml <file>` to specify Stack's project-level YAML -configuration file. - -## `--[no-]system-ghc` flag - -Default: Disabled - -Enables/disables the use of a GHC executable on the PATH, if one is available -and its version matches. - -## `--[no-]terminal` flag - -Default: Stack is running in a terminal (as detected) - -Enables/disables whether Stack is running in a terminal. - -## `--terminal-width` option - -Default: the terminal width (if detected); otherwise `100` - -Pass the option `--terminal-width <width>` to specify the width of the terminal, -used by Stack's pretty printed messages. - -## `--[no-]time-in-logs` flag - -Default: Enabled - -Enables/disables the inclusion of time stamps against logging entries when the -verbosity level is 'debug'. - -## `--verbose` or `-v` flags - -Equivalent to the `--verbosity debug` option. - -## `--verbosity` option - -Default: `info` - -Pass the option `--verbosity <log_level>` to specify the level for logging. -Possible levels are `silent`, `error`, `warn`, `info` and `debug`, in order of -increasing amounts of information provided by logging. - -## `--version` flag - -Pass the flag `--version` to cause Stack to report its version to standard -output and quit. For versions that are release candidates, the report will list -the dependencies that Stack has been compiled with. - -## `--with-gcc` option - -Pass the option `--with-gcc <path_to_gcc>` to specify use of a GCC executable. -For further information, see the documentation for the corresponding non-project -specific configuration [option](yaml_configuration.md#with-gcc). - -## `--with-hpack` option - -Pass the option `--with-hpack <hpack>` to specify use of an Hpack executable. -For further information, see the documentation for the corresponding -non-project specific configuration [option](yaml_configuration.md#with-hpack). - -## `--work-dir` option - -Default: `.stack-work` - -Overrides: [`STACK_WORK`](environment_variables.md#stack_work) environment -variable, and [`work-dir`](yaml_configuration.md) non-project specific -configuration option. - -Pass the option `--work-dir <relative_path_to_the_Stack_root>` to specify the -path to Stack's work directory, within a local project or package directory. The -path must be a relative one, relative to the the root directory of the project -or package. The relative path cannot include a `..` (parent directory) -component. - -## `--setup-info-yaml` command option - -Default: `https://raw.githubusercontent.com/commercialhaskell/stackage-content/master/stack/stack-setup-2.yaml` - -The `--setup-info-yaml <url>` command option specifies the location of a -`setup-info` dictionary. The option can be specified multiple times. - -## `--snapshot-location-base` command option - -Default: `https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master` - -The `--snapshot-location-base <url>` command option specifies the base location -of snapshots. - -## `--help` command flag - -If Stack is passed the `--help` command flag, it will output help for the -command.
doc/glossary.md view
@@ -8,7 +8,7 @@ |-------------------|----------------------------------------------------------| |Cabal |The Haskell Common Architecture for Building Applications and Libraries, provided by the [`Cabal` package](https://hackage.haskell.org/package/Cabal). Also referred to as Cabal (the library) to distinguish it from Cabal (the tool).| |Cabal file|A file containing a [package description](https://cabal.readthedocs.io/en/stable/cabal-package.html) used by Cabal, named `<package_name>.cabal`.| -|Cabal (the tool)|The Haskell build tool provided by the [`cabal-install` package](https://hackage.haskell.org/package/cabal-install).| +|Cabal (the tool)|The Haskell tool used for building provided by the [`cabal-install` package](https://hackage.haskell.org/package/cabal-install).| |CI |Continuous integration. | |CMake |A [system](https://cmake.org/) for managing build processes.| |`config.yaml` |A global and non-project-specific configuration file used by Stack.|
− doc/hoogle_command.md
@@ -1,33 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack hoogle` command - -~~~text -stack hoogle [-- ARGUMENT(S) (e.g. 'stack hoogle -- server --local')] - [--[no-]setup] [--rebuild] [--server] -~~~ - -Hoogle is a Haskell API search engine. `stack hoogle` runs Hoogle. Stack needs -Hoogle version 5 or greater. - -Stack will use a Hoogle database (`database.hoo`) specific to the project's -source map and the version of GHC, located in a subdirectory of subdirectory -`hoogle` of Stack's work directory for the project. - -By default: - -* if a `hoogle` executable is found on the `PATH`, Stack will try to use it. - Otherwise, Stack will try to identify an executable as a build target. If - the Hoogle database does not exist, Stack will generate it with - `hoogle generate --local`. `hoogle generate --local` queries `ghc-pkg` and - generates links for all packages which have documentation and Hoogle input - files (`*.txt`) generated. Pass the flag `--no-setup` to skip such setup; - -* the existing Hoogle database is used. Pass the flag `--rebuild` to trigger - the generation of a new Hoogle database (generated as above); and - -* `hoogle` is passed the specified arguments (if any). The arguments are - usually the subject of the search. Pass the flag `--server` to first pass - `server --local --port 8080` before those arguments. - `hoogle server --local --port 8080` starts a local Hoogle web server, using - port 8080, that allows the following of `file://` links.
− doc/hpc_command.md
@@ -1,167 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack hpc` commands - -~~~text -stack hpc COMMAND - -Available commands: - report Generate unified HPC coverage report from tix files - and project targets -~~~ - -Code coverage is a measure of the degree to which the source code of a program -is executed when a test suite is run. -[Haskell Program Coverage (HPC)](https://ku-fpg.github.io/software/hpc/) is a -code coverage tool for Haskell that is provided with GHC. Code coverage is -enabled by passing the flag `--coverage` to `stack build`. - -`stack hpc` provides commands specific to HPC. Command `stack hpc` for the -available commands. - -The following refers to the local HPC root directory. Its location can be -obtained by command: - -~~~text -stack path --local-hpc-root -~~~ - -## The `stack hpc report` command - -~~~text -stack hpc report [TARGET_OR_TIX] [--all] [--destdir DIR] [--open] -~~~ - -The `stack hpc report` command generates a report for a selection of targets and -`.tix` files. - -Pass the flag `--all` for a report that uses all stored results. - -Pass the flag `--open` to open the HTML report in your browser. - -## The `extra-tix-files` directory - -During the execution of the build, you can place additional tix files in the -`extra-tix-files` subdirectory in the local HPC root directory, in order for -them to be included in the unified report. A couple caveats: - -1. These tix files must be generated by executables that are built against the - exact same library versions. Also note that, on subsequent builds with - coverage, the local HPC root directory will be recursively deleted. It - just stores the most recent coverage data. - -2. These tix files will not be considered by `stack hpc report` unless listed - explicitly by file name. - -## Examples - -If we have three different packages with test suites, packages `A`, `B`, and -`C`, the default unified report will have coverage from all three. If we want a -unified report with just two, we can instead command: - -~~~text -stack hpc report A B -~~~ - -This will output to the standard output stream a summary report for the combined -coverage from `A` and `B`'s test suites. It will also log the path to the HTML -for the corresponding full report. - -This command also supports taking extra `.tix` files. If you've also built an -executable, against exactly the same library versions of `A`, `B`, and `C`, then -you could command the following: - -~~~text -stack exec -- an-exe -stack hpc report A B C an-exe.tix -~~~ - -or, equivalently: - -~~~text -stack exec -- an-exe -stack hpc report --all an-exe.tix -~~~ - -This report will consider all test results as well as the newly generated -`an-exe.tix` file. - -## Usage - -`stack test --coverage` is quite streamlined for the following use-case: - -1. You have test suites which exercise your project packages. - -2. These test suites link against your library, rather than building the - library directly. Coverage information is only given for libraries, ignoring - the modules which get compiled directly into your executable. A common case - where this doesn't happen is when your test suite and library both have - something like `hs-source-dirs: src/`. In this case, when building your test - suite you may also be compiling your library, instead of just linking - against it. - -When your project has these properties, you will get the following: - -1. Summary coverage reports, sent to the standard output stream in the build - output, and a log of the paths to the HTML for the corresponding full - reports. - -2. A summary unified report, sent to the standard output stream, and a log of - the path to the HTML for the corresponding full report. These reports - consider the coverage on all local libraries, based on all of the tests that - were run. - -3. An index of all generated HTML reports, in `index.html` in the local - HPC root directory, and a log of the path to the HTML for that index. - -## Implementation details - -Most users can get away with just understanding the above documentation. -However, advanced users may want to understand exactly how `--coverage` works: - -1. The GHC option `-fhpc` gets passed to all project packages. This tells GHC to - output executables that track coverage information and output them to `.tix` - files. `the-exe-name.tix` files will get written to the working directory of - the executable. - - When switching on this flag, it will usually cause all project packages to be - rebuilt (see issue - [#1940](https://github.com/commercialhaskell/stack/issues/1940)). - -2. Before the build runs with `--coverage`, the contents of the local HPC root - directory gets deleted. This prevents old reports from getting mixed - with new reports. If you want to preserve report information from multiple - runs, copy the contents of this path to a new directory. - -3. Before a test run, if a `test-name.tix` file exists in the package directory, - it will be deleted. - -4. After a test run, it will expect a `test-name.tix` file to exist. This file - will then get loaded, modified, and outputted to - `pkg-name/test-name/test-name.tix` in the local HPC root directory. - - The `.tix` file gets modified to remove coverage file that isn't associated - with a library. So, this means that you won't get coverage information for - the modules compiled in the `executable` or `test-suite` stanza of your Cabal - file. This makes it possible to directly union multiple `*.tix` files from - different executables (assuming they are using the exact same versions of the - project packages). - - If there is enough popular demand, it may be possible in the future to give - coverage information for modules that are compiled directly into the - executable. See issue - [#1359](https://github.com/commercialhaskell/stack/issues/1359). - -5. Once we have a `.tix` file for a test, we also generate a summary report and - a corresponding full report using HTML. The summary report is sent to the - standard output stream. The index of the test-specific HTML report is - available at `pkg-name/test-name/index.html` in the local HPC root directory. - -6. After the build completes, if there are multiple output `*.tix` files, they - get combined into a unified report. The index of this report will be - available at `combined/all/index.html` in the local HPC root directory. - -7. Finally, an index of the resulting coverage reports is generated. It links to - the individual coverage reports (one for each test-suite), as well as the - unified report. This index is available at `index.html` in the local HPC root - directory.
− doc/ide_command.md
@@ -1,72 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack ide` commands - -~~~text -stack ide COMMAND - -Available commands: - packages List all available local loadable packages - targets List all available Stack targets -~~~ - -The `stack ide` commands provide information that may be of use in an -integrated development environment (IDE). See `stack ide` for the available -commands. - -## The `stack ide packages` command - -~~~text -stack ide packages [--stdout] [--cabal-files] -~~~ - -`stack ide packages` lists all available project packages that are loadable. - -By default: - -* its output is sent to the standard error stream. Pass the flag `--stdout` to - change to the standard output stream; and -* the output is the package name (without its version). Pass the flag - `--cabal-files` to change to the full path to the package's Cabal file. - -## The `stack ide targets` command - -~~~text -stack ide targets [--exes] [--tests] [--benchmarks] [--stdout] -~~~ - -`stack ide targets` lists all available Stack targets. Alternatively, pass one -or more of the flags `--exes`, `--tests` and `--benchmarks` to list only targets -of those component types. - -By default, its output is sent to the standard error stream. Pass the flag -`--stdout` to change to the standard output stream. - -For example, for the Stack project itself, command: - -~~~text -cd stack -stack ide targets -~~~ - -and the output from the second command is: - -~~~text -stack:lib -stack:exe:stack -stack:exe:stack-integration-test -stack:test:stack-unit-test -~~~ - -or command: - -~~~text -stack ide targets --exes -~~~ - -and the output is: - -~~~text -stack:exe:stack -stack:exe:stack-integration-test -~~~
− doc/init_command.md
@@ -1,42 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack init` command - -~~~text -stack init [DIR(S)] [--omit-packages] [--force] [--ignore-subdirs] -~~~ - -`stack init` initialises Stack's default project-level YAML configuration file -(`stack.yaml`) for an existing project, based on the Cabal file or -`package.yaml` file for each of its packages. - -By default: - -* Stack searches for Cabal and `package.yaml` files in the current directory. - Specify one or more directories as arguments to cause Stack to search them; - -* Stack also searches for Cabal and `package.yaml` files in subdirectories. Pass - the flag `--ignore-subdirs` to ignore subdirectories; - -* Stack will not overwrite an existing `stack.yaml` file. Pass the flag - `--force` to allow overwriting; and - -* Stack will not initialise if there are conflicting or incompatable user - packages. Pass the flag `--omit-packages` to cause Stack to ignore such - matters while initialising. - -If a snapshot is specified at the command line, `stack init` will try to use it. -For further information, see the documentation for the -[`--snapshot`](global_flags.md#-snapshot-option) and -[`--resolver`](global_flags.md#-resolver-option) options. - -Otherwise, `stack init` will try to use the following Stackage snapshots in -order of preference, using the first that is compatable: the most recent LTS -Haskell, the most recent Stackage Nightly, and other LTS Haskell (most recent -first). - -!!! note - - If Cabal (the tool) has been used in the directory, consider commanding - `cabal clean` before applying `stack init`, in case Cabal has created any - unintended Cabal files.
doc/install_and_upgrade.md view
@@ -1,713 +1,840 @@ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> -# Install or upgrade - -## Install Stack - -Stack can be installed on most Linux distributions, macOS and Windows. It will -require at least about 5 GB of disk space, of which about 3 GB is for a single -version of GHC and about 2 GB is for Stack's local copy of the Hackage package -index. - -Stack is open to supporting more operating systems. To request support for an -operating system, please submit an -[issue](https://github.com/commercialhaskell/stack/issues/new) at Stack's -GitHub repository. - -!!! info - - In addition to the methods described below, Stack can also be installed - using the separate [GHCup](https://www.haskell.org/ghcup/) installer for - Haskell-related tools. GHCup provides Stack for some combinations of machine - architecture and operating system not provided elsewhere. Unlike Stack, - other build tools do not automatically install GHC. GHCup can be used to - install GHC for those other tools. By default, the script to install GHCup - (which can be run more than once) also configures Stack so that if Stack - needs a version of GHC, GHCup takes over obtaining and installing that - version. - -!!! info "Releases on GitHub" - - Stack executables are also available on the - [releases](https://github.com/commercialhaskell/stack/releases) page of - Stack's GitHub repository. - -!!! info "`https://get.haskellstack.org/stable` URLs" - - URLs with the format - `https://get.haskellstack.org/stable/<PLATFORM>.<EXTENSION>` point to the - latest stable release. See the manual download links for examples. - -=== "Linux" - - For most Linux distributions, the easiest way to install Stack directly - (rather than use GHCup) is to command: - - ~~~text - curl -sSL https://get.haskellstack.org/ | sh - ~~~ - - or: - - ~~~text - wget -qO- https://get.haskellstack.org/ | sh - ~~~ - - !!! note - - The script at [get.haskellstack.org](https://get.haskellstack.org/) will - ask for root access using `sudo`. It needs such access in order to use - your platform's package manager to install dependencies and to install - to `/usr/local/bin`. If you prefer more control, follow the manual - installation instructions for your platform below. - - ### Manual download - - Manual download for Linux distributions depends on your machine - architecture, x86_64 or AArch64/ARM64. - - === "x86_64" - - * Click - [:material-cloud-download-outline:](https://get.haskellstack.org/stable/linux-x86_64.tar.gz) - to download an archive file with the latest release. - - * Extract the archive and place the `stack` executable somewhere on your - PATH (see the [Path](#path) section below). - - * Ensure you have the required system dependencies installed. These - include GCC, GNU Make, xz, perl, libgmp, libffi, and zlib. We also - recommend Git and GPG. - - The installation of system dependencies will depend on the package - manager for your Linux distribution. Notes are provided for Arch Linux, - CentOS, Debian, Fedora, Gentoo and Ubuntu. - - === "Arch Linux" - - ~~~text - sudo pacman -S make gcc ncurses git gnupg xz zlib gmp libffi zlib - ~~~ - - === "CentOS" - - ~~~text - sudo yum install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg - ~~~ - - === "Debian" - - ~~~text - sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase - ~~~ - - === "Fedora" - - ~~~text - sudo dnf install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg - ~~~ - - === "Gentoo" - - Ensure you have the `ncurses` package with `USE=tinfo`. Without it, - Stack will not be able to install GHC. - - === "Ubuntu" - - ~~~text - sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase - ~~~ - - === "AArch64" - - * Click - [:material-cloud-download-outline:](https://get.haskellstack.org/stable/linux-aarch64.tar.gz) - to download an archive file with the latest release. - - * Extract the archive and place the `stack` executable somewhere on your - PATH (see the [Path](#path) section below). - - * Ensure you have the required system dependencies installed. These - include GCC, GNU Make, xz, perl, libgmp, libffi, and zlib. We also - recommend Git and GPG. - - The installation of system dependencies will depend on the package - manager for your Linux distribution. Notes are provided for Arch Linux, - CentOS, Debian, Fedora, Gentoo and Ubuntu. - - === "Arch Linux" - - ~~~text - sudo pacman -S make gcc ncurses git gnupg xz zlib gmp libffi zlib - ~~~ - - === "CentOS" - - ~~~text - sudo yum install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg - ~~~ - - === "Debian" - - ~~~text - sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase - ~~~ - - === "Fedora" - - ~~~text - sudo dnf install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg - ~~~ - - === "Gentoo" - - Ensure you have the `ncurses` package with `USE=tinfo`. Without it, - Stack will not be able to install GHC. - - === "Ubuntu" - - ~~~text - sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase - ~~~ - - ### Linux packages - - Some Linux distributions have official or unofficial packages for Stack, - including Arch Linux, Debian, Fedora, NixOS, openSUSE/SUSE Linux Enterprise, - and Ubuntu. However, the Stack version available as a Linux package may lag - behind Stack's current version and, in some cases, the lag may be - significant. - - !!! info "Linux packages that lag behind Stack's current version" - - If Stack version available as a Linux package lags behind Stack's - current version, using `stack upgrade --binary-only` is recommended - after installing it. - - === "Arch Linux" - - The Arch extra package repository provides an official x86_64 - [package](https://www.archlinux.org/packages/extra/x86_64/stack/). - You can install it with the command: - - ~~~text - sudo pacman -S stack - ~~~ - - The Arch User Repository (AUR) also provides: - - * a [`stack-bin` package](https://aur.archlinux.org/packages/stack-bin); - and - - * a [`stack-static` package](https://aur.archlinux.org/packages/stack-static) - - === "Debian" - - There are Debian - [packages](https://packages.debian.org/search?keywords=haskell-stack&searchon=names&suite=all§ion=all) - for Buster and up. However, the distribution's Stack version lags - behind. - - === "Fedora" - - Fedora includes Stack, but its Stack version may lag behind. - - === "NixOS" - - Users who follow the `nixos-unstable` channel or the Nixpkgs `master` - branch can install the latest Stack release into their profile with the - command: - - ~~~text - nix-env -f "<nixpkgs>" -iA stack - ~~~ - - Alternatively, the package can be built from source as follows. - - 1. Clone the git repo, with the command: - - ~~~text - git clone https://github.com/commercialhaskell/stack.git - ~~~ - - 2. Create a `shell.nix` file with the command: - - ~~~text - cabal2nix --shell ./. --no-check --no-haddock > shell.nix - ~~~ - - Note that the tests fail on NixOS, so disable them with - `--no-check`. Also, Haddock currently doesn't work for Stack, so - `--no-haddock` disables it. - - 3. Install Stack to your user profile with the command: - - ~~~text - nix-env -i -f shell.nix - ~~~ - - For more information on using Stack together with Nix, please see the - [NixOS manual section on Stack](http://nixos.org/nixpkgs/manual/#how-to-build-a-haskell-project-using-stack). - - === "SUSE" - - There is also an unofficial package for openSUSE or SUSE Linux - Enterprise. Its Stack version may lag behind. To install it: - - === "openSUSE Tumbleweed" - - ~~~text - sudo zypper in stack - ~~~ - - === "openSUSE Leap" - - ~~~text - sudo zypper ar http://download.opensuse.org/repositories/devel:/languages:/haskell/openSUSE_Leap_42.1/devel:languages:haskell.repo - sudo zypper in stack - ~~~ - - === "SUSE Linux Enterprise 12" - - ~~~text - sudo zypper ar http://download.opensuse.org/repositories/devel:/languages:/haskell/SLE_12/devel:languages:haskell.repo - sudo zypper in stack - ~~~ - - === "Ubuntu" - - There are Ubuntu - [packages](http://packages.ubuntu.com/search?keywords=haskell-stack&searchon=names&suite=all§ion=all) - for Ubuntu 20.04 and up. - - It is possible to set up auto-completion of Stack commands. For further - information, see the [shell auto-completion](shell_autocompletion.md) - documentation. - -=== "macOS" - - Most users of Stack on macOS will also have up to date tools for software - development (see [Xcode Command Line Tools](#xcode-command-line-tools) - below). - - From late 2020, Apple began a transition from Mac computers with Intel - processors (Intel-based Mac) to - [Mac computers with Apple silicon](https://support.apple.com/en-gb/HT211814). - - === "Intel-based" - - Intel-based Mac computers have processors with x86_64 architectures. For - most Intel-based Mac computers, the easiest way to install Stack - directly (rather than use GHCup) is to command: - - ~~~text - curl -sSL https://get.haskellstack.org/ | sh - ~~~ - - or: - - ~~~text - wget -qO- https://get.haskellstack.org/ | sh - ~~~ - - !!! note - - The script at [get.haskellstack.org](https://get.haskellstack.org/) - will ask for root access using `sudo`. It needs such access in order - to use your platform's package manager to install dependencies and - to install to `/usr/local/bin`. If you prefer more control, follow - the manual installation instructions below. - - !!! info - - We generally test on the current version of macOS and do our best to - keep it compatible with the three most recent major versions. Stack - may also work on older versions. - - ### Manual download - - * Click - [:material-cloud-download-outline:](https://get.haskellstack.org/stable/osx-x86_64.tar.gz) - to download an archive file with the latest release for x86_64 - architectures. - - * Extract the archive and place `stack` somewhere on your PATH (see the - [Path](#path) section below). - - * Now you can run Stack from the command line in a terminal. - - === "Apple silicon" - - Mac computers with Apple silicon have an M1, M1 Pro, M1 Max, M1 Ultra or - M2 chip. These chips use an architecture known as ARM64 or AArch64. - - For Mac computers with Apple silicon, the easiest way to install Stack - directly (rather than use GHCup) is to command: - - ~~~text - curl -sSL https://get.haskellstack.org/ | sh - ~~~ - - or: - - ~~~text - wget -qO- https://get.haskellstack.org/ | sh - ~~~ - - !!! note - - The script at [get.haskellstack.org](https://get.haskellstack.org/) - will ask for root access using `sudo`. It needs such access in order - to use your platform's package manager to install dependencies and - to install to `/usr/local/bin`. If you prefer more control, follow - the manual installation instructions below. - - The installation of Stack or some packages (e.g. `network`) requiring C - source compilation might fail with `configure: error: C compiler cannot - build executables`. In that case you should pass `-arch arm64` as part - of the `CFLAGS` environment variable. This setting will be picked up by - the C compiler of your choice. - - ~~~bash - # Assuming BASH below - - # passing CFLAGS in-line with the command giving rise to the error - CFLAGS="-arch arm64 ${CFLAGS:-}" some_command_to_install_stack - CFLAGS="-arch arm64 ${CFLAGS:-}" stack [build|install] - - # -- OR -- - - # ~/.bash_profile - # NOTE: only do this if you do not have to cross-compile, or remember to unset - # CFLAGS when needed - export CFLAGS="-arch arm64 ${CFLAGS:-}" - ~~~ - - The setting instructs the C compiler to compile objects for ARM64. These - can then be linked with libraries built for ARM64. Without the - instruction, the C compiler, invoked by Cabal running in x86-64, would - compile x86-64 objects and attempt to link them with existing ARM64 - libraries, resulting in the error above. - - ### Manual download - - * Click - [:material-cloud-download-outline:](https://get.haskellstack.org/stable/osx-aarch64.tar.gz) - to download an archive file with the latest release for AArch64 - architectures. - - * Extract the archive and place `stack` somewhere on your PATH (see the - [Path](#path) section below). - - * Now you can run Stack from the command line in a terminal. - - ### LLVM - - The documentation for each version of GHC identifies the versions of - LLVM that are supported. That is summarised in the table below for - recent versions of GHC: - - |GHC version|LLVM versions| - |-----------|-------------| - |9.8.2 |11 to 15 | - |9.6.5 |11 to 15 | - |9.4.8 |10 to 14 | - |9.2.8 |9 to 12 | - |9.0.2 |9, 10 or 12 | - |8.10.7 |9 to 12 | - |8.8.4 |7 | - |8.6.5 |6 | - |8.4.4 |5 | - - ### Using Homebrew - - [Homebrew](https://brew.sh/) is a popular package manager for macOS. If you - have its `brew` tool installed, you can just command: - - ~~~text - brew install haskell-stack - ~~~ - - * The Homebrew formula and bottles are **unofficial** and lag slightly - behind new Stack releases, but tend to be updated within a day or two. - - * Normally, Homebrew will install from a pre-built binary (aka "pour from a - bottle"), but if it starts trying to build everything from source (which - will take hours), see - [their FAQ on the topic](https://github.com/Homebrew/brew/blob/master/docs/FAQ.md#why-do-you-compile-everything). - - ### Xcode Command Line Tools - - macOS does not come with all the tools required for software development but - a collection of useful tools, known as the Xcode Command Line Tools, is - readily available. A version of that collection is provided with each - version of Xcode (Apple’s integrated development environment) and can also - be obtained from Apple separately from Xcode. The collection also includes - the macOS SDK (software development kit). The macOS SDK provides header - files for macOS APIs. - - If you use a command that refers to a common Xcode Command Line Tool and - the Xcode Command Line Tools are not installed, macOS may prompt you to - install the tools. - - macOS also comes with a command line tool, `xcode-select`, that can be used - to obtain the Xcode Command Line Tools. Command `xcode-select --print-path` - to print the path to the currently selected (active) developer directory. If - the directory does not exist, or is empty, then the Xcode Command Line Tools - are not installed. - - If the Xcode Command Line Tools are not installed, command - `xcode-select --install` to open a user interface dialog to request - automatic installation of the tools. - - An upgrade of macOS may sometimes require the existing Xcode Command Line - Tools to be uninstalled and an updated version of the tools to be installed. - The existing tools can be uninstalled by deleting the directory reported by - `xcode-select --print-path`. - - If, after the installation of Stack, running `stack setup` fails with - `configure: error: cannot run C compiled programs.` that indicates that the - Xcode Command Line Tools are not installed. - - If building fails with messages that `*.h` files are not found, that may - also indicate that Xcode Command Line Tools are not up to date. - - Xcode 10 provided an SDK for macOS 10.14 (Mojave) and - [changed the location](https://developer.apple.com/documentation/xcode-release-notes/xcode-10-release-notes#Command-Line-Tools) - of the macOS system headers. As a workaround, an extra package was provided - by Apple which installed the headers to the base system under - `/usr/include`. - - ### Auto-completion of Stack commands - - It is possible to set up auto-completion of Stack commands. For further - information, see the [shell auto-completion](shell_autocompletion.md) - documentation. - -=== "Windows" - - On 64-bit Windows, the easiest way to install Stack directly (rather than - use GHCup) is to download and use the - [Windows installer](https://get.haskellstack.org/stable/windows-x86_64-installer.exe). - - !!! info "Stack root" - - By default, the Windows installer will set the Stack root by setting the - `STACK_ROOT` environment variable to `C:\sr`. - - !!! warning "Long user PATH environment variable" - - The Windows installer for Stack 2.9.1, 2.9.3 and 2.11.1 (only) will - replace the user `PATH` environment variable (rather than append to it) - if a 1024 character limit is exceeded. If the content of your existing - user `PATH` is long, preserve it before running the installer. - - !!! note "Anti-virus software" - - Systems with antivirus software may need to add Stack to the list of - 'trusted' applications. - - You may see a "Windows Defender SmartScreen prevented an unrecognized - app from starting" warning when you try to run the installer. If so, - click on **More info**, and then click on the **Run anyway** button that - appears. - - We recommend installing to the default location with the installer, as that - will make `stack install` and `stack upgrade` work correctly out of the box. - - ### Manual download - - * Click - [:material-cloud-download-outline:](https://get.haskellstack.org/stable/windows-x86_64.zip) - to download an archive file with the latest release. - - * Unpack the archive and place `stack.exe` somewhere on your PATH (see the - [Path](#path) section below). - - * Now you can run Stack from the command line in a terminal. - -## Path - -You can install Stack by copying the executable file anywhere on your PATH. A -good place to install is the same directory where Stack itself will install -executables, which depends on the operating system: - -=== "Unix-like" - - Stack installs executables to: - - ~~~text - $HOME/.local/bin - ~~~ - - If you don't have that directory in your PATH, you may need to update your - PATH. That can be done by editing the `~/.bashrc` file. - -=== "Windows" - - Stack installs executables to: - - ~~~text - %APPDATA%\local\bin - ~~~ - - For example: `C:\Users\<user-name>\AppData\Roaming\local\bin`. - - If you don't have that directory in your PATH, you may need to update your - PATH. That can be done by searching for 'Edit Environment variables for your - account' under Start. - -!!! note - - If you used [GHCup](https://www.haskell.org/ghcup/) to install Stack, GHCup - puts executable files in the `bin` directory in the GHCup root directory. - -## China-based users - -If you're attempting to install Stack from within China: - -* As of 24 February 2020, the download link has limited connectivity from within - mainland China. If this is the case, please proceed by manually downloading - (ideally via a VPN) and installing Stack per the instructions found on this - page pertinent to your operating system. - -* After installation, your `config.yaml` file will need to be configured before - Stack can download large files consistently from within China (without - reliance on a VPN). Please add the following to the bottom of the - `config.yaml` file: - -~~~yaml -###ADD THIS IF YOU LIVE IN CHINA -setup-info-locations: -- "http://mirrors.tuna.tsinghua.edu.cn/stackage/stack-setup.yaml" -urls: - latest-snapshot: http://mirrors.tuna.tsinghua.edu.cn/stackage/snapshots.json - -package-indices: -- download-prefix: http://mirrors.tuna.tsinghua.edu.cn/hackage/ -~~~ - -## Using an HTTP proxy - -To use Stack behind a HTTP proxy with IP address *IP* and port *PORT*, first set -up an environment variable `http_proxy` and then run the Stack command. For -example: - -=== "Unix-like" - - ~~~text - export http_proxy=IP:PORT - stack install - ~~~ - - On most operating systems, it is not mandatory for programs to follow the - "system-wide" HTTP proxy. Some programs, such as browsers, do honor this - "system-wide" HTTP proxy setting, while other programs, including Bash, do - not. That means configuring "http proxy setting" in your System Preferences - (macOS) would not result in Stack traffic going through the proxy. - -=== "Windows" - - ~~~text - $Env:http_proxy=IP:PORT - stack install - ~~~ - - It is not mandatory for programs to follow the "system-wide" HTTP proxy. - Some programs, such as browsers, do honor this "system-wide" HTTP proxy - setting, while other programs do not. That means configuring - "http proxy setting" in your Control Panel would not result in Stack traffic - going through the proxy. - -## Upgrade Stack - -There are different approaches to upgrading Stack, which vary as between -Unix-like operating systems (including macOS) and Windows. - -!!! note - - If you used [GHCup](https://www.haskell.org/ghcup/) to install Stack, you - should also use GHCup to upgrade Stack. GHCup uses an executable named - `stack` to manage versions of Stack, through a file `stack.shim`. Stack will - likely overwrite the executable on upgrade. - -=== "Unix-like" - - There are essentially four different approaches: - - 1. The `stack upgrade` command, which downloads a Stack executable, or - builds it from source, and installs it to Stack's 'local-bin' directory - (see `stack path --local-bin`). If different and permitted, it also - installs a copy in the directory of the current Stack executable. (If - copying is not permitted, copy `stack` from Stack's 'local-bin' - directory to the system location afterward.) You can use `stack upgrade` - to get the latest official release, and `stack upgrade --git` to install - from GitHub and live on the bleeding edge. Make sure the location of the - Stack executable is on the PATH. See the [Path](#Path) section above. - - 2. If you're using a package manager and are happy with sticking with the - officially released binaries from the distribution (which may the lag - behind the latest version of Stack significantly), simply follow your - normal package manager strategies for upgrading. For example: - - ~~~text - apt-get update - apt-get upgrade - ~~~ - - 3. The `get.haskellstack.org` script supports the `-f` argument to - over-write the current Stack executable. For example, command: - - ~~~text - curl -sSL https://get.haskellstack.org/ | sh -s - -f - ~~~ - - or: - - ~~~text - wget -qO- https://get.haskellstack.org/ | sh -s - -f - ~~~ - - 4. Manually follow the steps above to download the newest executable from - the GitHub releases page and replace the old executable. - -=== "Windows" - - There are essentially two different approaches: - - 1. The `stack upgrade` command, which downloads a Stack executable, or - builds it from source, and installs it to Stack's 'local-bin' directory - (see `stack path --local-bin`). If different and permitted, it also - installs a copy in the directory of the current Stack executable. (If - copying is not permitted, copy `stack` from Stack's 'local-bin' - directory to the system location afterward.) You can use `stack upgrade` - to get the latest official release, and `stack upgrade --git` to install - from GitHub and live on the bleeding edge. Make sure the location of the - Stack executable is on the PATH. See the [Path](#Path) section above. - - 2. Manually follow the steps above to download the newest executable from - the GitHub releases page and replace the old executable. - -## Install earlier versions - -To install a specific version of Stack, navigate to the desired version on the -[GitHub release page](https://github.com/commercialhaskell/stack/releases), and -click the appropriate link under its "Assets" drop-down menu. - -Alternatively, use the URL -`https://github.com/commercialhaskell/stack/releases/download/vVERSION/stack-VERSION-PLATFORM.EXTENSION`. -For example, the tarball for Stack version 2.1.0.1, osx-x86_64 is at -`https://github.com/commercialhaskell/stack/releases/download/v2.1.0.1/stack-2.1.0.1-osx-x86_64.tar.gz`. - -Here's a snippet for `appveyor.yml` files, borrowed from `dhall`'s -[`appveyor.yml`](https://github.com/dhall-lang/dhall-haskell/blob/1079b7a3a7a6922f72a373e47daf6f1b74f128b1/appveyor.yml). -Change the values of PATH and VERSION as needed. - -~~~yaml -install: - - set PATH=C:\Program Files\Git\mingw64\bin;%PATH% - - curl --silent --show-error --output stack.zip --location "https://github.com/commercialhaskell/stack/releases/download/v%STACK_VERSION%/stack-%STACK_VERSION%-windows-x86_64.zip" - - 7z x stack.zip stack.exe - - stack setup > nul - - git submodule update --init --recursive -~~~ +# Setting up + +The goal of setting up is a `stack` executable file on the PATH. When Stack is +used, it sets other things up as needed. + +*[PATH]: An environment variable that specifies a list of directories searched for executable files. + +??? question "How do I know if Stack is on the PATH?" + + Command `stack`. If Stack is available, that should output information about + how to use it. + +??? question "How do I find where Stack is located?" + + === "Unix-like" + + Command `which -a stack`. + + === "Windows" + + Command `where.exe stack`. + +??? question "How do I find what version of Stack is available?" + + Command `stack --version` or `stack --numeric-version`. + +??? question "If I don't use GHCup, is there a preferred location for Stack?" + + You can put the `stack` executable file anywhere on your PATH. However, a + good location is the directory where Stack itself will install executables. + That location depends on the operating system: + + === "Unix-like" + + Stack installs executables to: + + ~~~text + $HOME/.local/bin + ~~~ + + If you don't have that directory in your PATH, you may need to update + your PATH. That can be done by editing the `~/.bashrc` file. + + === "Windows" + + Stack installs executables to: + + ~~~text + %APPDATA%\local\bin + ~~~ + + For example: `C:\Users\<user-name>\AppData\Roaming\local\bin`. + + If you don't have that directory in your PATH, you may need to update + your PATH. That can be done by searching for 'Edit Environment variables + for your account' under Start. + + !!! note + + If you used GHCup to install Stack, GHCup puts executable files in the + `bin` directory in the GHCup root directory. + +To get and use Stack, some other things need to be in place first: + +<div class="grid cards" markdown> + +- :material-laptop:{ .lg .middle } __A computer__ + + --- + + Stack will need at least about 5 GB of disk space[^1]. It will help to know + what platform your computer provides. + + [^1]: + About 3 GB for a single version of GHC and about 2 GB for a local copy + of the Hackage package index. + + *[platform]: Machine architecture (eg x86_64, AArch64) and operating system (eg Linux distribution, macOS, Windows). + +- :material-wifi:{ .lg .middle } __Access to the Internet__ + + --- + + Stack will need to fetch files from remote locations. + +- :octicons-terminal-24:{ .lg .middle } __Terminal software__ + + --- + + Stack is used at the command line. Your operating system likely provides + terminal software and alternatives may be available. + +- :material-text-box-edit-outline:{ .lg .middle } __A code editor__ + + --- + + You can use any editor program that can edit text files but code editors + with extensions for Haskell code files are recommended. + +</div> + +## Install Stack + +Stack can be installed on most Linux distributions, macOS and Windows. + +??? question "What about other operating systems?" + + Stack is open to supporting more operating systems. To request support for + an operating system, please submit an + [issue](https://github.com/commercialhaskell/stack/issues/new) at Stack's + GitHub repository. + +Stack can be installed directly or by using the GHCup tool. + +=== "Directly" + + Stack can be installed on various operating systems. + + ??? question "Where can binary distributions for Stack be found?" + + Stack executables are available on the + [releases](https://github.com/commercialhaskell/stack/releases) page of + Stack's GitHub repository. + + URLs with the format + `https://get.haskellstack.org/stable/<PLATFORM>.<EXTENSION>` point to + the latest stable release. The manual download links use those URLs. + + ??? question "Does the `sh` installation script have flags and options?" + + The `sh` installation script recognises the following optional flags and + options: `-q` suppresses output and specifies non-intervention (likely a + prerequisite for the use of the script in CI environments); `-f` forces + installation, even if an existing Stack executable is detected; and + `-d <directory>` specifies a destination directory for the Stack + executable. + + === "Linux" + + For most Linux distributions, on x86_64 or AArch64 machine + architectures, the easiest way to install Stack is to command either: + + ~~~text + curl -sSL https://get.haskellstack.org/ | sh + ~~~ + + or: + + ~~~text + wget -qO- https://get.haskellstack.org/ | sh + ~~~ + + These commands download a script file and run it using `sh`. + + ??? question "Will the installation script need root access?" + + The script at [get.haskellstack.org](https://get.haskellstack.org/) + will ask for root access using `sudo`. It needs such access in order + to use your platform's package manager to install dependencies and + to install to `/usr/local/bin`. If you prefer more control, follow + the manual installation instructions for your platform below. + + ??? question "Can I download Stack manually?" + + Yes. Manual download for Linux distributions depends on your machine + architecture, x86_64 or AArch64/ARM64. + + === "x86_64" + + * Click + [:material-cloud-download-outline:](https://get.haskellstack.org/stable/linux-x86_64.tar.gz) + to download an archive file with the latest release. + + * Extract the archive and place the `stack` executable file + somewhere on your PATH. + + * Ensure you have the required system dependencies installed. + These include GCC, GNU Make, xz, perl, libgmp, libffi, and + zlib. We also recommend Git and GPG. + + The installation of system dependencies will depend on the + package manager for your Linux distribution. Notes are provided + for Arch Linux, CentOS, Debian, Fedora, Gentoo and Ubuntu. + + === "Arch Linux" + + ~~~text + sudo pacman -S make gcc ncurses git gnupg xz zlib gmp libffi zlib + ~~~ + + === "CentOS" + + ~~~text + sudo yum install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg + ~~~ + + === "Debian" + + ~~~text + sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase + ~~~ + + === "Fedora" + + ~~~text + sudo dnf install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg + ~~~ + + === "Gentoo" + + Ensure you have the `ncurses` package with `USE=tinfo`. Without + it, Stack will not be able to install GHC. + + === "Ubuntu" + + ~~~text + sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase + ~~~ + + === "AArch64" + + * Click + [:material-cloud-download-outline:](https://get.haskellstack.org/stable/linux-aarch64.tar.gz) + to download an archive file with the latest release. + + * Extract the archive and place the `stack` executable file + somewhere on your PATH. + + * Ensure you have the required system dependencies installed. + These include GCC, GNU Make, xz, perl, libgmp, libffi, and + zlib. We also recommend Git and GPG. + + The installation of system dependencies will depend on the + package manager for your Linux distribution. Notes are provided + for Arch Linux, CentOS, Debian, Fedora, Gentoo and Ubuntu. + + === "Arch Linux" + + ~~~text + sudo pacman -S make gcc ncurses git gnupg xz zlib gmp libffi zlib + ~~~ + + === "CentOS" + + ~~~text + sudo yum install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg + ~~~ + + === "Debian" + + ~~~text + sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase + ~~~ + + === "Fedora" + + ~~~text + sudo dnf install perl make automake gcc gmp-devel libffi zlib zlib-devel xz tar git gnupg + ~~~ + + === "Gentoo" + + Ensure you have the `ncurses` package with `USE=tinfo`. Without it, + Stack will not be able to install GHC. + + === "Ubuntu" + + ~~~text + sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbase + ~~~ + + ??? question "Can I use a Linux package to get Stack?" + + Some Linux distributions have official or unofficial packages for + Stack, including Arch Linux, Debian, Fedora, NixOS, openSUSE/SUSE + Linux Enterprise, and Ubuntu. However, the Stack version available + as a Linux package may lag behind Stack's current version and, in + some cases, the lag may be significant. + + !!! info "Linux packages that lag behind Stack's current version" + + If Stack version available as a Linux package lags behind + Stack's current version, using `stack upgrade --binary-only` is + recommended after installing it. + + === "Arch Linux" + + The Arch extra package repository provides an official x86_64 + [package](https://www.archlinux.org/packages/extra/x86_64/stack/). + You can install it with the command: + + ~~~text + sudo pacman -S stack + ~~~ + + The Arch User Repository (AUR) also provides: + + * a [`stack-bin` package](https://aur.archlinux.org/packages/stack-bin); + and + + * a [`stack-static` package](https://aur.archlinux.org/packages/stack-static) + + === "Debian" + + There are Debian + [packages](https://packages.debian.org/search?keywords=haskell-stack&searchon=names&suite=all§ion=all) + for Buster and up. However, the distribution's Stack version + lags behind. + + === "Fedora" + + Fedora includes Stack, but its Stack version may lag behind. + + === "NixOS" + + Users who follow the `nixos-unstable` channel or the Nixpkgs + `master` branch can install the latest Stack release into their + profile with the command: + + ~~~text + nix-env -f "<nixpkgs>" -iA stack + ~~~ + + Alternatively, the package can be built from source as follows. + + 1. Clone the git repo, with the command: + + ~~~text + git clone https://github.com/commercialhaskell/stack.git + ~~~ + + 2. Create a `shell.nix` file with the command: + + ~~~text + cabal2nix --shell ./. --no-check --no-haddock > shell.nix + ~~~ + + Note that the tests fail on NixOS, so disable them with + `--no-check`. Also, Haddock currently doesn't work for + Stack, so `--no-haddock` disables it. + + 3. Install Stack to your user profile with the command: + + ~~~text + nix-env -i -f shell.nix + ~~~ + + For more information on using Stack together with Nix, please + see the + [NixOS manual section on Stack](http://nixos.org/nixpkgs/manual/#how-to-build-a-haskell-project-using-stack). + + === "SUSE" + + There is also an unofficial package for openSUSE or SUSE Linux + Enterprise. Its Stack version may lag behind. To install it: + + === "openSUSE Tumbleweed" + + ~~~text + sudo zypper in stack + ~~~ + + === "openSUSE Leap" + + ~~~text + sudo zypper ar http://download.opensuse.org/repositories/devel:/languages:/haskell/openSUSE_Leap_42.1/devel:languages:haskell.repo + sudo zypper in stack + ~~~ + + === "SUSE Linux Enterprise 12" + + ~~~text + sudo zypper ar http://download.opensuse.org/repositories/devel:/languages:/haskell/SLE_12/devel:languages:haskell.repo + sudo zypper in stack + ~~~ + + === "Ubuntu" + + There are Ubuntu + [packages](http://packages.ubuntu.com/search?keywords=haskell-stack&searchon=names&suite=all§ion=all) + for Ubuntu 20.04 and up. + + ??? question "Can I set up auto-completion of Stack commands?" + + Yes. For further information, see the + [shell auto-completion](topics/shell_autocompletion.md) + documentation. + + === "macOS" + + Most users of Stack on macOS will also have up to date tools for + software development. + + ??? question "What if I am not sure that I have those tools?" + + macOS does not come with all the tools required for software + development but a collection of useful tools, known as the Xcode + Command Line Tools, is readily available. A version of that + collection is provided with each version of Xcode (Apple’s + integrated development environment) and can also be obtained from + Apple separately from Xcode. The collection also includes the macOS + SDK (software development kit). The macOS SDK provides header files + for macOS APIs. + + If you use a command that refers to a common Xcode Command Line Tool + and the Xcode Command Line Tools are not installed, macOS may prompt + you to install the tools. + + macOS also comes with a command line tool, `xcode-select`, that can + be used to obtain the Xcode Command Line Tools. Command + `xcode-select --print-path` to print the path to the currently + selected (active) developer directory. If the directory does not + exist, or is empty, then the Xcode Command Line Tools are not + installed. + + If the Xcode Command Line Tools are not installed, command + `xcode-select --install` to open a user interface dialog to request + automatic installation of the tools. + + An upgrade of macOS may sometimes require the existing Xcode Command + Line Tools to be uninstalled and an updated version of the tools to + be installed. The existing tools can be uninstalled by deleting the + directory reported by `xcode-select --print-path`. + + If, after the installation of Stack, running `stack setup` fails + with: + ~~~text + configure: error: cannot run C compiled programs. + ~~~ + + that indicates that the Xcode Command Line Tools are not installed. + + If building fails with messages that `*.h` files are not found, that + may also indicate that Xcode Command Line Tools are not up to date. + + Xcode 10 provided an SDK for macOS 10.14 (Mojave) and + [changed the location](https://developer.apple.com/documentation/xcode-release-notes/xcode-10-release-notes#Command-Line-Tools) + of the macOS system headers. As a workaround, an extra package was + provided by Apple which installed the headers to the base system + under `/usr/include`. + + ??? question "What versions of the LLVM compiler and toolchain are supported?" + + The documentation for each version of GHC identifies the versions of + LLVM that are supported. That is summarised in the table below for + recent versions of GHC: + + |GHC version|LLVM versions| + |-----------|-------------| + |9.8.2 |11 to 15 | + |9.6.6 |11 to 15 | + |9.4.8 |10 to 14 | + |9.2.8 |9 to 12 | + |9.0.2 |9, 10 or 12 | + |8.10.7 |9 to 12 | + |8.8.4 |7 | + |8.6.5 |6 | + |8.4.4 |5 | + + From late 2020, Apple began a transition from Mac computers with Intel + processors (Intel-based Mac) to + [Mac computers with Apple silicon](https://support.apple.com/en-gb/HT211814). + + === "Intel-based" + + Intel-based Mac computers have processors with x86_64 architectures. + For most Intel-based Mac computers, the easiest way to install Stack + is to command either: + + ~~~text + curl -sSL https://get.haskellstack.org/ | sh + ~~~ + + or: + + ~~~text + wget -qO- https://get.haskellstack.org/ | sh + ~~~ + + These commands download a script file and run it using `sh`. + + ??? question "Will the installation script need root access?" + + The script at + [get.haskellstack.org](https://get.haskellstack.org/) + will ask for root access using `sudo`. It needs such access in + order to use your platform's package manager to install + dependencies and to install to `/usr/local/bin`. If you prefer + more control, follow the manual installation instructions below. + + ??? question "Can I download Stack manually?" + + Yes: + + * Click + [:material-cloud-download-outline:](https://get.haskellstack.org/stable/osx-x86_64.tar.gz) + to download an archive file with the latest release for x86_64 + architectures. + + * Extract the archive and place `stack` somewhere on your PATH. + + Now you can run Stack from the command line in a terminal. + + === "Apple silicon" + + Mac computers with Apple silicon have an M series chip. These chips + use an architecture known as ARM64 or AArch64. + + For Mac computers with Apple silicon, the easiest way to install + Stack is to command either: + + ~~~text + curl -sSL https://get.haskellstack.org/ | sh + ~~~ + + or: + + ~~~text + wget -qO- https://get.haskellstack.org/ | sh + ~~~ + + These commands download a script file and run it using `sh`. + + ??? question "Will the installation script need root access?" + + The script at + [get.haskellstack.org](https://get.haskellstack.org/) + will ask for root access using `sudo`. It needs such access in + order to use your platform's package manager to install + dependencies and to install to `/usr/local/bin`. If you prefer + more control, follow the manual installation instructions below. + + ??? question "What if I get error `C compiler cannot build executables`?" + + The installation of Stack or some packages (e.g. `network`) + requiring C source compilation might fail with: + + ~~~text + configure: error: C compiler cannot build executables + ~~~ + + In that case you should pass `-arch arm64` as part of the + `CFLAGS` environment variable. This setting will be picked up by + the C compiler of your choice. + + ~~~bash + # Assuming BASH below + + # passing CFLAGS in-line with the command giving rise to the error + CFLAGS="-arch arm64 ${CFLAGS:-}" some_command_to_install_stack + CFLAGS="-arch arm64 ${CFLAGS:-}" stack [build|install] + + # -- OR -- + + # ~/.bash_profile + # NOTE: only do this if you do not have to cross-compile, or remember to unset + # CFLAGS when needed + export CFLAGS="-arch arm64 ${CFLAGS:-}" + ~~~ + + The setting instructs the C compiler to compile objects for + ARM64. These can then be linked with libraries built for ARM64. + Without the instruction, the C compiler, invoked by Cabal + running in x86-64, would compile x86-64 objects and attempt to + link them with existing ARM64 libraries, resulting in the error + above. + + ??? question "Can I download Stack manually?" + + Yes: + + * Click + [:material-cloud-download-outline:](https://get.haskellstack.org/stable/osx-aarch64.tar.gz) + to download an archive file with the latest release for + AArch64 architectures. + + * Extract the archive and place `stack` somewhere on your PATH. + + Now you can run Stack from the command line in a terminal. + + ??? question "Can I use the Homebrew package manager to get Stack?" + + [Homebrew](https://brew.sh/) is a popular package manager for macOS. + If you have its `brew` tool installed, you can just command: + + ~~~text + brew install haskell-stack + ~~~ + + * The Homebrew formula and bottles are **unofficial** and lag + slightly behind new Stack releases, but tend to be updated within + a day or two. + + * Normally, Homebrew will install from a pre-built binary (aka "pour + from a bottle"), but if it starts trying to build everything from + source (which will take hours), see + [their FAQ on the topic](https://github.com/Homebrew/brew/blob/master/docs/FAQ.md#why-do-you-compile-everything). + + ??? question "Can I set up auto-completion of Stack commands?" + + Yes. For further information, see the + [shell auto-completion](topics/shell_autocompletion.md) + documentation. + + === "Windows" + + Most computers using Windows have a x86_64 machine architecture. More + recently, Microsoft has provided Windows on Arm that runs on other + processors. + + === "x86_64" + + On 64-bit Windows, the easiest way to install Stack is to download + and use the + [Windows installer](https://get.haskellstack.org/stable/windows-x86_64-installer.exe). + + !!! info "Stack root" + + By default, the Windows installer will set the + [Stack root](topics/stack_root.md) by setting the `STACK_ROOT` + environment variable to `C:\sr`. + + !!! note "Anti-virus software" + + Systems with antivirus software may need to add Stack to the + list of 'trusted' applications. + + You may see a "Windows Defender SmartScreen prevented an + unrecognized app from starting" warning when you try to run the + installer. If so, click on **More info**, and then click on the + **Run anyway** button that appears. + + !!! warning "Long user PATH environment variable" + + The Windows installer for Stack 2.9.1, 2.9.3 and 2.11.1 (only) + will replace the user `PATH` environment variable (rather than + append to it) if a 1024 character limit is exceeded. If the + content of your existing user `PATH` is long, preserve it before + running the installer. + + We recommend installing to the default location with the installer, + as that will make `stack install` and `stack upgrade` work correctly + out of the box. + + ??? question "Can I download Stack manually?" + + Yes: + + * Click + [:material-cloud-download-outline:](https://get.haskellstack.org/stable/windows-x86_64.zip) + to download an archive file with the latest release. + + * Unpack the archive and place `stack.exe` somewhere on your + PATH. + + Now you can run Stack from the command line in a terminal. + + === "Windows on Arm" + + The GHC project does not yet provide a version of GHC that runs on + Windows on Arm. + + ??? note "China-based users: download" + + As of 24 February 2020, the download link has limited connectivity from + within mainland China. If you experience this, please proceed by + manually downloading (ideally via a VPN) and installing Stack following + the instructions on this page that apply to your operating system. + +=== "GHCup" + + The separate [GHCup](https://www.haskell.org/ghcup/) project provides a tool + that can be used to install Stack and other Haskell-related tools, including + GHC and + [Haskell Language Server](https://github.com/haskell/haskell-language-server) + (HLS). HLS is a program that is used by Haskell extensions for popular code + editors. + + GHCup provides Stack for some combinations of machine architecture and + operating system not provided elsewhere. + + By default, the script to install GHCup (which can be run more than once) + also configures Stack so that if Stack needs a version of GHC, GHCup takes + over obtaining and installing that version. + +??? note "China-based users: configuration" + + After installation, Stack will need to be configured before it can download + large files consistently from within China (without reliance on a VPN). + Please add the following to the bottom of the + [global configuration file](configure/yaml/index.md) (`config.yaml`): + + ~~~yaml + ###ADD THIS IF YOU LIVE IN CHINA + setup-info-locations: + - "http://mirrors.tuna.tsinghua.edu.cn/stackage/stack-setup.yaml" + urls: + latest-snapshot: http://mirrors.tuna.tsinghua.edu.cn/stackage/snapshots.json + + package-index: + - download-prefix: http://mirrors.tuna.tsinghua.edu.cn/hackage/ + ~~~ + +??? question "What if I am using an HTTP proxy?" + + To use Stack behind a HTTP proxy with IP address *IP* and port *PORT*, first + set up an environment variable `http_proxy` and then run the Stack command. + For example: + + === "Unix-like" + + ~~~text + export http_proxy=IP:PORT + stack install + ~~~ + + On most operating systems, it is not mandatory for programs to follow + the 'system-wide' HTTP proxy. Some programs, such as browsers, do honor + this 'system-wide' HTTP proxy setting, while other programs, including + Bash, do not. That means configuring 'http proxy setting' in your System + Preferences (macOS) would not result in Stack traffic going through the + proxy. + + === "Windows" + + ~~~text + $Env:http_proxy=IP:PORT + stack install + ~~~ + + It is not mandatory for programs to follow the 'system-wide' HTTP proxy. + Some programs, such as browsers, do honor this 'system-wide' HTTP proxy + setting, while other programs do not. That means configuring + 'http proxy setting' in your Control Panel would not result in Stack + traffic going through the proxy. + +## Upgrade Stack + +The Stack project recommends the use of the latest released version of Stack. + +If Stack is already installed, upgrading it depends on whether you are using +Stack or GHCup to manage versions of Stack. + +=== "Stack" + + ??? warning "If you use GHCup to manage versions of Stack, use it consistently" + + If you used GHCup to install Stack, you should also use GHCup to upgrade + Stack. + + GHCup uses an executable named `stack` to manage versions of Stack, + through a file `stack.shim`. Stack will likely overwrite the executable + on upgrade. + + There are different approaches to upgrading Stack, which vary as between + Unix-like operating systems (including macOS) and Windows. + + === "Unix-like" + + There are essentially four different approaches: + + <div class="grid cards" markdown> + + - __Use the `stack upgrade` command__ + + --- + + For further information, see the + [`stack upgrade`](commands/upgrade_command.md) documentation. + + - __Manual download__ + + --- + + Follow the steps above to download manually the newest executable + and replace the old executable. + + - __Use the `sh` installation script__ + + --- + + Use the `get.haskellstack.org` script with its `-f` flag to + overwrite the current Stack executable. For example, command + either: + + ~~~text + curl -sSL https://get.haskellstack.org/ | sh -s - -f + ~~~ + + or: + + ~~~text + wget -qO- https://get.haskellstack.org/ | sh -s - -f + ~~~ + + - __Use a package manager__ + + --- + + Follow your normal package manager approach to upgrading. For + example: + + ~~~text + apt-get update + apt-get upgrade + ~~~ + + Be aware that officially released binaries from the distribution may + lag behind the latest version of Stack significantly. + + </div> + + === "Windows" + + There are essentially two different approaches: + + <div class="grid cards" markdown> + + - __Use the `stack upgrade` command__ + + --- + + For further information, see the + [`stack upgrade`](commands/upgrade_command.md) documentation. + + - __Manual download__ + + --- + + Follow the steps above to download manually the newest executable + and replace the old executable. + + </div> + +=== "GHCup" + + The separate [GHCup](https://www.haskell.org/ghcup/) project provides + guidance about how to use GHCup to manage versions of tools such as Stack.
− doc/list_command.md
@@ -1,66 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack list` command - -[:octicons-tag-24: 2.7.1](https://github.com/commercialhaskell/stack/releases/tag/v2.7.1) - -~~~text -stack list [PACKAGE] -~~~ - -`stack list <package_name>` will send to the standard output stream the latest -version of the package from Hackage. If the package name cannot be found on -Hackage, even after updating the package index, suggestions (not necessarily -good ones) will be made about the intended package name. - -`stack --snapshot <snapshot> list <package_name>` will send to the standard -output stream the version of the package in the specified snapshot, unless the -package comes with GHC on Unix-like operating systems. If the package name -cannot be found in the snapshot, the command will fail, identifying only the -package(s) that did not appear in the snapshot. - -More than one package name can be specified. - -`stack --snapshot <snapshot> list` will send to the standard output stream a -list of all the packages in the specified snapshot, except those which come with -GHC on Unix-like operating systems. - -For example: - -~~~text -stack list base unix Win32 acme-missiles pantry -base-4.19.0.0 -unix-2.8.5.0 -Win32-2.13.4.0 -acme-missiles-0.3 -pantry-0.9.3.1 - -stack list paltry -Could not find package paltry, updating -... -Package index cache populated -Error: [S-4926] - * Could not find package paltry on Hackage. Perhaps you meant one of: - pantry, pretty, pasty, xattr, alloy, para, pappy, alure, polar and - factory. - -stack --snapshot lts-22.21 list base unix Win32 acme-missiles pantry -Error: [S-4926] - * Package does not appear in snapshot: base. - * Package does not appear in snapshot: unix. - * Package does not appear in snapshot: Win32. - * Package does not appear in snapshot: acme-missiles. - -stack --snapshot lts-22.21 list base unix Win32 pantry -base-4.18.2.1 -unix-2.8.4.0 -Win32-2.13.3.0 -pantry-0.9.3.2 - -stack --snapshot lts-22.21 list -AC-Angle-1.0 -ALUT-2.4.0.3 -... -zstd-0.1.3.0 -zxcvbn-hs-0.3.6 -~~~
− doc/lock_files.md
@@ -1,185 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Lock Files - -Stack attempts to provide reproducible build plans. This involves reproducibly -getting the exact same contents of source packages and configuration options -(like Cabal flags and GHC options) for a given set of input files. There are a -few problems with making this work: - -* Entering all of the information to fully provide reproducibility is tedious. - This would include things like Hackage revisions, hashes of remote tarballs, - etc. Users don't want to enter this information. -* Many operations in Stack rely upon a "snapshot hash," which transitively - includes the completed information for all of these dependencies. If any of - that information is missing when parsing the `stack.yaml` file or snapshot - files, it could be expensive for Stack to calculate it. - -To address this, we follow the (fairly standard) approach of having a -_lock file_. The goal of the lock file is to cache completed locations of -project, snapshot packages and snapshots themselves so that: - -* These files can be stored in source control -* Users on other machines can reuse these lock files and get identical build - plans given that the used project packages and local snapshots are the same on - those machines -* Rerunning `stack build` in the future is deterministic in the build plan, not - depending on mutable state in the world like Hackage revisions - - !!! note - - If, for example, a tarball available remotely is deleted or the hash - changes, it will not be possible for Stack to perform the build. - However, by deterministic, we mean it either performs the same build or - fails, never accidentally doing something different. - -This document explains the contents of a lock file, how they are used, and how -they are created and updated. - -## stack.yaml and snapshot files - -Relevant to this discussion, Stack's project-level configuration file -(`stack.yaml`, by default) specifies: - -* the parent snapshot (the [`snapshot`](yaml_configuration.md#snapshot) or - [`resolver`](yaml_configuration.md#resolver) key) -* extra-deps - -Some of this information can be incomplete. Consider this `stack.yaml` file: - -~~~yaml -snapshot: lts-19.22 -packages: -- . -extra-deps: -- acme-missiles-0.3 -~~~ - -This information is _incomplete_. For example, the extra-deps may change in the -future. Instead, you could specify enough information in the `stack.yaml` file -to fully resolve that package. That looks like: - -~~~yaml -extra-deps: -- hackage: acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1,613 - pantry-tree: - size: 226 - sha256: 614bc0cca76937507ea0a5ccc17a504c997ce458d7f2f9e43b15a10c8eaeb033 -~~~ - -The `lts-19.22` information is also incomplete. While we assume in general that -Haskell LTS snapshots never change, there's nothing that prohibits that from -happening. Instead, the complete version of that key is: - -~~~yaml -snapshot: -- url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/22.yaml - size: 619399 - sha256: 5098594e71bdefe0c13e9e6236f12e3414ef91a2b89b029fd30e8fc8087f3a07 -~~~ - -Users don't particularly feel like writing all of that. Therefore, it's common -to see _incomplete_ information in a `stack.yaml` file. - -## Recursive snapshot layers - -Snapshot files can be _recursive_, where `stack.yaml` refers to `foo.yaml`, -which refers to `bar.yaml`, which refers to `baz.yaml`. A local snapshot file -can refer to a remote snapshot file (available via an HTTP(S) URL). - -We need to encode information from _all_ of these snapshot layers and the -`stack.yaml` file in the lock file, to ensure that we can detect if anything -changes. - -## Performance - -In addition to acting as a pure correctness mechanism, the design of a lock file -given here also works as a performance improvement. Instead of requiring that -all snapshot files be fully parsed on each Stack invocation, we can store -information in the lock file and bypass parsing of the additional files in the -common case of no changes. - -## Lock file contents - -The lock file contains the following information: - -* Completed package locations for extra-deps and packages in snapshot files - - !!! note - - This only applies to _immutable_ packages. Mutable packages are not - included in the lock file. - -* Completed information for the snapshot locations - -It looks like the following: - -~~~yaml -# Lock file, some message about the file being auto-generated -snapshots: - # Starts with the snapshot specified in stack.yaml, - # then continues with the snapshot specified in each - # subsequent snapshot file - - original: - foo.yaml # raw content specified in a snapshot file - completed: - file: foo.yaml - sha256: XXXX - size: XXXX - - original: - lts-13.9 - completed: - size: 496662 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/13/9.yaml - sha256: 83de9017d911cf7795f19353dba4d04bd24cd40622b7567ff61fc3f7223aa3ea - -packages: -- original: https://hackage.haskell.org/package/acme-missiles-0.3.tar.gz - completed: - size: 1442 - url: https://hackage.haskell.org/package/acme-missiles-0.3.tar.gz - name: acme-missiles - version: '0.3' - sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b - pantry-tree: - size: 226 - sha256: 614bc0cca76937507ea0a5ccc17a504c997ce458d7f2f9e43b15a10c8eaeb033 -~~~ - -## Creation procedure - -Whenever a project-level configuration file (`stack.yaml`, by default) is -loaded, Stack checks for a lock file in the same file path, with a `.lock` -extension added. For example, if you command: - -~~~text -stack --stack-yaml my-stack.yaml build -~~~ - -or - -~~~text -stack --stack-yaml my-stack.yaml build --dry-run -~~~ - -then Stack will use a lock file in the location `my-stack.yaml.lock`. For the -rest of this document, we'll assume that the files are simply `stack.yaml` and -`stack.yaml.lock`. - -If the lock file does not exist, subject to Stack's -[`--lock-file`](global_flags.md#-lock-file-option) option, it will be -created by: - -* Loading the `stack.yaml` -* Loading all snapshot files -* Completing all missing information -* Writing out the new `stack.yaml.lock` file to the disk - -## Update procedure - -Whenever a project-level configuration file (`stack.yaml`, by default) is -loaded, all completed package or snapshot locations (even those completed using -information from a lock file) get collected to form a new lock file in memory. -Subject to Stack's [`--lock-file`](global_flags.md#-lock-file-option) option, -that new lock file is compared against the one on disk and, if there are any -differences, written out to the disk.
− doc/ls_command.md
@@ -1,244 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack ls` commands - -~~~text -stack ls COMMAND - -Available commands: - dependencies View the dependencies - snapshots View snapshots (local by default) - stack-colors View Stack's output styles - stack-colours View Stack's output styles (alias for 'stack-colors') - tools View Stack's installed tools -~~~ - -The `stack ls` commands list different types of information. Command `stack ls` -for the available commands. - -## The `stack ls dependencies` command - -Either - -~~~text -stack ls dependencies COMMAND - -Available commands: - cabal Print dependencies as exact Cabal constraints - json Print dependencies as JSON - text Print dependencies as text (default) - tree Print dependencies as tree -~~~ - -or - -~~~text -stack ls dependencies [--separator SEP] [--[no-]license] [--filter ITEM] - [--[no-]external] [--[no-]include-base] [--depth DEPTH] - [--prune PACKAGES] [TARGET] [--flag PACKAGE:[-]FLAG] - [--test] [--bench] [--global-hints] -~~~ - -`stack ls dependencies` lists all of the packages and versions used for a -project. All project packages are considered by default, but a target can be -specified as an argument. For further information, see the -[target syntax](build_command.md#target-syntax) documentation. - -Subcommands specify the format of the output, as follows: - -* `cabal` lists the packages in the format of exact Cabal constraints. - - ~~~text - stack ls dependencies cabal [--[no-]external] [--[no-]include-base] - [--depth DEPTH] [--prune PACKAGES] [TARGET] - [--flag PACKAGE:[-]FLAG] [--test] [--bench] - [--global-hints] - ~~~ - - For example (extract): - - ~~~text - constraints: - , Cabal ==3.6.3.0 - , Cabal-syntax ==3.6.0.0 - , Glob ==0.10.2 - ~~~ - -* `json` lists dependencies in JSON format (an array of objects). - - ~~~text - stack ls dependencies json [--[no-]external] [--[no-]include-base] - [--depth DEPTH] [--prune PACKAGES] [TARGET] - [--flag PACKAGE:[-]FLAG] [--test] [--bench] - [--global-hints] - ~~~ - - For example (extract): - - ~~~text - [{"dependencies":["base","bytestring"],"license":"BSD3","location":{"type":"hackage","url":"https://hackage.haskell.org/package/zlib-0.6.3.0"},"name":"zlib","version":"0.6.3.0"}, - ~~~ - - Each object has the following keys: - - ~~~json - name: zlib - version: 0.6.3.0 - location: - type: hackage - url: https://hackage.haskell.org/package/zlib-0.6.3.0 - licence: BSD3 - dependencies: - - base - - bytestring - ~~~ - -* `text` (the default) lists the packages, each on a separate line. - - ~~~text - stack ls dependencies text [--separator SEP] [--[no-]license] [--filter ITEM] - [--[no-]external] [--[no-]include-base] - [--depth DEPTH] [--prune PACKAGES] [TARGET] - [--flag PACKAGE:[-]FLAG] [--test] [--bench] - [--global-hints] - ~~~ - - For example (extract): - - ~~~text - Cabal 3.6.3.0 - Cabal-syntax 3.6.0.0 - Glob 0.10.2 - ~~~ - -* `tree` lists dependencies in the format of a tree. - - ~~~text - stack ls dependencies tree [--separator SEP] [--[no-]license] [--[no-]external] - [--[no-]include-base] [--depth DEPTH] - [--prune PACKAGES] [TARGET] [--flag PACKAGE:[-]FLAG] [--test] [--bench] [--global-hints] - ~~~ - - For example (extract): - - ~~~text - Packages - └─┬ stack 2.10.0 - ├─┬ Cabal 3.6.3.0 - │ ├─┬ Win32 2.12.0.1 - │ │ ├─┬ base 4.16.3.0 - │ │ │ ├─┬ ghc-bignum 1.2 - │ │ │ │ └─┬ ghc-prim 0.8.0 - │ │ │ │ └── rts 1.0.2 - │ │ │ ├─┬ ghc-prim 0.8.0 - ~~~ - -The `--separator` option, with the `text` or `tree` subcommand, specifies the -separator between the package name and its version. The default is a space -character. - -Set the `--license` flag, after the `text` or `tree` subcommand, to replace each -package's version with its licence. (Consistent with the Cabal package -description format specification, only the American English spelling (license) -is accepted.) - -The `--filter` option, with the `text` subcommand, specifies an item to be -filtered out from the results, if present. An item can be `$locals` (for all -project packages) or a package name. It can be specified multiple times. - -!!! note - - The special value `$locals` will need to be enclosed with single quotes to - distinguish it from a shell variable. - -Set the `--no-external` flag to exclude external dependencies. - -Set the `--no-include-base` flag to exclude dependencies on the `base` package. - -The `--depth` option limits the depth of dependency resolution. - -The `--prune <packages>` option prunes the specified packages and their -dependencies from the tree of packages used to generate the output, where -`<packages>` is a comma separated list of package names. - -The `--flag` option allows Cabal flags to be specified. - -Pass the `--test` flag to consider the dependencies of test suite components. - -Pass the `--bench` flag to consider the dependencies of benchmark components. - -Pass the `--global-hints` flag to use a hints file for global packages. The -command then does not require an installed GHC. - -## The `stack ls snapshots` command - -~~~text -stack ls snapshots [COMMAND] [-l|--lts] [-n|--nightly] - -Available commands: - local View local snapshots - remote View remote snapshots -~~~ - -`stack ls snapshots` will list all the local snapshots by default. You can also -view the remote snapshots using `stack ls snapshots remote`. It also supports -options for viewing only lts (`-l`) and nightly (`-n`) snapshots. - -## The `stack ls stack-colors` command - -~~~text -stack ls stack-colors [--[no-]basic] [--[no-]sgr] [--[no-]example] -~~~ - -The British English spelling is also accepted (`stack ls stack-colours`). - -`stack ls stack-colors` will list all of Stack's output styles. A number of -different formats for the output are available, see -`stack ls stack-colors --help`. - -The default is a full report, with the equivalent SGR instructions and an -example of the applied style. The latter can be disabled with flags `--no-sgr` -and `--no-example`. - -The flag `--basic` specifies a more basic report, in the format that is accepted -by Stack's command line option `--stack-colors` and the YAML configuration key -`stack-colors`. - -## The `stack ls tools` command - -~~~text -stack ls tools [--filter TOOL_NAME] -~~~ - -`stack ls tools` will list Stack's installed tools. On Unix-like operating -systems, they will be one or more versions of GHC. On Windows, they will include -MSYS2. For example, on Windows the command: - -~~~text -stack ls tools -~~~ - -yields output like: - -~~~text -ghc-9.4.1 -ghc-9.2.4 -ghc-9.0.2 -msys2-20210604 -~~~ - -The `--filter <tool_name>` option will filter the output by a tool name (e.g. -'ghc', 'ghc-git' or 'msys2'). The tool name is case sensitive. For example the -command: - -~~~text -stack ls tools --filter ghc -~~~ - -yields output like: - -~~~text -ghc-9.4.1 -ghc-9.2.4 -ghc-9.0.2 -~~~
+ doc/maintainers/7zip.md view
@@ -0,0 +1,92 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Upgrading 7-Zip + +When installing GHC or MSYS2 on Windows, Stack will also install +[7-Zip](https://www.7-zip.org/). 7-Zip is a file archiver and is used by Stack +to extract files from archives. This section explains the steps required to +upgrade the 7-Zip version used by Stack. The 7-Zip functionality used by Stack +is mature and stable. It is anticipated that the Stack-supplied 7-Zip will not +need to be updated frequently. On 10 September 2022, it was updated from 7-Zip +9.20 (released on 18 November 2010) to 7-Zip 22.01 (released on 15 July 2022). + +1. Download the latest installer for 64-bit x64 Windows from 7-Zip's website. + +2. Run the installer and install to the default location + (`C:\C:\Program Files\7-Zip`). The four relevant files from those installed + will be: + + ~~~text + 7z.exe # 7-Zip Console + 7z.dll # 7-Zip Engine + license.txt # 7-Zip License + readme.txt # 7-Zip Overview + ~~~ + +3. In the + [commercialhaskell/stackage-content](https://github.com/commercialhaskell/stackage-content) + GitHub repository, create a new draft release tagged and named `7z-XX.YY`, + where `XX.YY` is the 7-Zip version number. + +4. Upload the four relevant files in step 2 above into the draft release. + +5. Provide a description for the release. For example: + + ~~~text + 7-Zip 22.01 (2022-07-15) for Windows 64-bit x64. + ~~~ + +6. Publish the release. + +7. Changes need to be made to the + [stackage-content/stack/stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/blob/master/stack/stack-setup-2.yaml) + file, to switch over to using the newly uploaded files. For example + (extract): + + ~~~yaml + sevenzexe-info: + url: "https://github.com/commercialhaskell/stackage-content/releases/download/7z-22.01/7z.exe" + content-length: 545280 + sha256: 254cf6411d38903b2440819f7e0a847f0cfee7f8096cfad9e90fea62f42b0c23 + + sevenzdll-info: + url: "https://github.com/commercialhaskell/stackage-content/releases/download/7z-22.01/7z.dll" + content-length: 1814016 + sha256: 73578f14d50f747efa82527a503f1ad542f9db170e2901eddb54d6bce93fc00e + ~~~ + + The `content-length:` key's value is the size of the file in bytes. It can + be obtained from the `Length` field of the `dir` command. The `sha256:` + key's value can be obtained from the commands (in PowerShell): + + ~~~text + (Get-FileHash 7z.exe -Algorithm SHA256).Hash.ToLower() + (Get-FileHash 7z.dll -Algorithm SHA256).Hash.ToLower() + ~~~ + + The `sha256:` key only accepts lowercase hash results as values. + +8. The changed `stack-setup-2.yaml` file should be tested locally. This can be + done by: + + * temporarily disabling the existing local copy of 7-Zip by changing the + name of the `7z.exe` and `7z.dll` files in the `stack path --programs` + directory; + + * identifying a version of GHC not already installed in the + `stack path --programs` directory; and + + * executing the command: + + ~~~text + stack --snapshot <snapshot> setup --setup-info-yaml <path to local copy of stack-setup-2.yaml> + ~~~ + + where `<snapshot>` requires the missing version of GHC. + + If all is well, the command should proceed to download the missing version + of GHC, download the `7z.exe` and `7z.dll` files, and use the 7-Zip version + to extract files from the GHC archive. + +9. Raise a pull request on `commercialhaskell/stackage-contents` for the + changes to the locally-tested `stack-setup-2.yaml` file.
+ doc/maintainers/archive/README.md view
@@ -0,0 +1,4 @@+# README + +The `doc/maintainers/archive` directory contains documentation that appears to +have been superceded but is preserved in case it is, in fact, useful.
+ doc/maintainers/archive/releases.md view
@@ -0,0 +1,308 @@+# Archive - from releases.md + +## Build Linux static binary distribution with Nix + +**NOTE: We have switched back to Alpine Linux for building static binaries, done by CI. Leaving this section for future reference.** + +These instructions are tested on Ubuntu 16.04, but theoretically should work on +any Linux distribution. + +- Install nix (tested with v2.0.4 and v2.1.2, but should work with any) + + ~~~sh + curl https://nixos.org/nix/install | sh + ~~~ + +- Install and authenticate cachix (first two steps at https://cachix.org/ after + signing up) + + +- Add nh2's cache: + + ~~~sh + cachix use static-haskell-nix + ~~~ + + !!! note + + To clear cache index, use `rm $HOME/.cache/nix/binary-cache-v5.sqlite*` + (useful if someone else uploads new stuff to the cache and you want to use + it right away). The recent `narinfo-cache-positive`/`negative-ttl` options + might also help. + +- Check out Stack commit to be released to `~/stack-release` (or elsewhere, in + which case adjust following instructions) + +- `rm -f ~/stack-release/*.cabal`, to ensure it's regenerated + +- clone https://github.com/nh2/static-haskell-nix recursively (last known to + work with commit 725ceb2479637b3b3ab29298a1bc0e48c54984c9) + +- in `static-stack` directory, run (from `static-stack/README.md`): + + ~~~sh + $(nix-build --no-link -A run-stack2nix-and-static-build-script --argstr stackDir ~/stack-release) + ~~~ + +- Run integration tests against the static binary [TODO: improve this process by + adding full support in `release.hs` or the integration tests for testing a + binary built elsewhere] + + - In `~/stack-release`, run + `stack build --flag stack:integration-tests stack:stack-integration-test` + - Copy binary built above to place where `stack build` normally puts the + `stack binary` (e.g. + `cp /nix/store/7vl1xvlbbqjvf864inz5vw7z2z1k4nmw-stack-2.1.0.1/bin/stack /home/vagrant/stack-release/.stack-work/install/x86_64-linux/custom-snapshot-for-building-stack-with-ghc-8.2.2-PyNP5UoO8Ott/8.2.2/bin/stack`; + figure it out using `stack exec which stack`) + - Run `stack exec stack-integration-test` + +- Copy the binary built above (in `/nix/store/XXX-stack-X.Y.Z/bin/stack`) to + `~/stack-release/_release/bin/stack-X.Y.Z-linux-x86_64/stack` (replace `X.Y.Z` + with the version, and the `/nix/store/*` path with that output at the end of + the previous command) + +- Package, sign, and upload to GitHub using Stack's release script in the stack + directory: + + ~~~sh + cd ~/stack-release + stack etc/scripts/release.hs --no-test-haddocks --binary-variant=static --build-args=--dry-run upload + ~~~ + + (adding `--build-args=--dry-run` ensures the binary you copied will be used rather than building a new one) + +- Download the bindist from GitHub and double check that the `stack` in it is + actually static (use `ldd /path/to/stack`) and that `--version` reports + correctly (and not dirty). + +## Setting up a Windows VM for releases + +These instructions are a bit rough, but has the steps to get the Windows machine +set up. + +## Using Virtualbox + + 1. Download Virtualbox VM image: + https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/mac/ + + 2. Launch the VM using Virtualbox and the image downloaded + + 3. Adjust settings: + * Number of CPUs: at least half the host's + * Memory: at least 3 GB + * Video RAM: the minimum recommended by Virtualbox + * Enable 3D and 2D accelerated mode (this makes programs with lots of + console output much faster) + * Enabled shared clipboard (in VM window, Devices->Shared + Clipboard->Both Directions) + +Now continue to the **General Windows setup** subsection below. + +## Using ESXi + +1. Download the **MSEdge on Win10** VM for **VMWare (Windows, Mac)**. +2. Unzip the file downloaded file +3. Upload the VMDK file to the ESXi datastore +4. SSH into ESXi CLI and run: + - `vmkfstools -i /vmfs/volumes/datastore1/win10-msedge/MSEdge-Win10-VMWare-disk1-ORIG.vmdk /vmfs/volumes/datastore1/win10-msedge/MSEdge-Win10-VMWare-disk1.vmdk -d thin`. + This converts the disk to a format that is compatible with ESXi. You may + have to run `esxcli system module load -m multiextent` first (see + https://www.virtuallyghetto.com/2012/09/2gbsparse-disk-format-no-longer-working.html). + - `vmkfstools -X 80G /vmfs/volumes/datastore1/win10-msedge/MSEdge-Win10-VMWare-disk1.vmdk`. + This makes the disk twice as large, which helps avoid running out of disk + space. +5. In the ESXi web UI: + - Create a new VM + - Give is 8192 MB of memory + - Give it 4 virtual CPUs + - Remove the default hard disk + - Add an **Existing hard disk** + - Select `/datastore1/win10-msedge/MSEdge-Win10-VMWare-disk1.vmdk` + - Power on the VM + - In Windows settings: + - Search for "disk management" + - Extend the partition to take the whole disk. + - In all likelihood, you will want to search for "remote desktop" and enable + remote desktop. Then you can connect to the VM using Microsoft Remote + Desktop instead of using it from within the ESXi web UI. + +Now continue to the **General Windows setup** subsection below. + +## General Windows setup + + 5. In **Settings**->**Update & Security**->**Windows Update**->**Advanced options**: + * Change **Choose how updates are installed** to **Notify to schedule restart** + * Check **Defer upgrades** (this avoids rebooting in the middle of the stack + build) + + 6. In **Settings**->**System**->**Power & sleep** + + * Disable turning off the screen or going to sleep when plugged in + + 7. Install msysgit: https://msysgit.github.io/ + + 8. Install TortoiseHG: https://tortoisehg.bitbucket.io/download/index.html + + 9. Install nsis-2.46.5-Unicode-setup.exe from http://www.scratchpaper.com/ + +10. Install Stack using the Windows 64-bit installer + + a. Restart any command prompts to ensure they get new `%STACK_ROOT%` value. + +11. Visit https://hackage.haskell.org/ in Edge to ensure system has correct CA + certificates + +13. Run in command prompt: + + ~~~text + md C:\p + md C:\tmp + cd /d C:\p + ~~~ + +14. Create `C:\p\env.bat`: + + ~~~text + SET TEMP=C:\tmp + SET TMP=C:\tmp + SET PATH=C:\Users\IEUser\AppData\Roaming\local\bin;"c:\Program Files\Git\usr\bin";"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin";%PATH% + ~~~ + +15. Run `C:\p\env.bat` (do this every time you open a new command prompt) + +16. `stack exec -- gpg --import`, and paste in the your GPG secret key (must be + done using `stack exec` because that uses the right keyring for the embedded + MSYS2 GPG; you can get the key from another machine with + `gpg --export-secret-keys --armor <KEY ID>`) + +17. Run in command prompt (adjust the `user.email` and `user.name` settings): + + ~~~text + git config --global user.email manny@fpcomplete.com + git config --global user.name "Emanuel Borsboom" + git config --global push.default simple + git config --global core.autocrlf true + git clone https://github.com/borsboom/stack-installer.git + git clone -b stable --reference C:\p\stack-release https://github.com/commercialhaskell/stack.git stack-release + cd stack-release + stack install cabal-install + ~~~ + +## Setting up an ARM VM for releases + +1. Use Scaleway to start ARMv7 and ARM64 VMs. + +2. Select Ubuntu Xenial as the operating system + +3. Install the correct version of LLVM: `sudo apt-get install -y llvm-3.9` + (appropriate for GHC 8.2, might need different version for other GHCs) + +4. Symlink opt-3.X to `opt`: `sudo ln -s opt-3.9 /usr/bin/opt` (adjust the + version if you installed a different one above) + +5. Switch to gold linker: + + ~~~sh + update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20 + update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.bfd" 10 + update-alternatives --config ld + ~~~ + +6. Add swap space: + + ~~~sh + dd if=/dev/zero of=/swapfile1 bs=1024 count=4194304 + mkswap /swapfile1 + swapon /swapfile1 + echo '/swapfile1 none swap sw 0 0' >>/etc/fstab + ~~~ + +7. Install additional tools: + + ~~~Sh + apt-get update && apt-get install -y unzip gpg + ~~~ + +8. Import your GPG key (`gpg --import` and paste the private key) + +9. Git settings (adjust for your preferences/email/name) + + ~~~text + git config --global push.default simple + git config --global user.email "manny@fpcomplete.com" + git config --global user.name "Emanuel Borsboom" + ~~~ + +10. Install tools used during building and dependencies packages + + ~~~text + sudo apt-get install -y g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg + ~~~ + +11. Install clang+llvm + + NOTE: the Debian jessie `llvm` package does not work (executables built with + it just exit with "schedule: re-entered unsafely."). + + The version of LLVM needed depends on the version of GHC you need. + + * GHC 8.2.2 (the standard for building Stack) + + ~~~sh + wget http://llvm.org/releases/3.9.1/clang+llvm-3.9.1-armv7a-linux-gnueabihf.tar.xz && \ + sudo tar xvf clang+llvm-3.9.1-armv7a-linux-gnueabihf.tar.xz -C /opt + ~~~ + + Run this now and add it to the `.profile`: + + ~~~sh + export PATH="$HOME/.local/bin:/opt/clang+llvm-3.9.1-armv7a-linux-gnueabihf/bin:$PATH" + ~~~ + + * GHC 7.10.3 + + ~~~sh + wget http://llvm.org/releases/3.5.2/clang+llvm-3.5.2-armv7a-linux-gnueabihf.tar.xz && \ + sudo tar xvf clang+llvm-3.5.2-armv7a-linux-gnueabihf.tar.xz -C /opt + ~~~ + + Run this now and add it to the `.profile`: + + ~~~sh + export PATH="$HOME/.local/bin:/opt/clang+llvm-3.5.2-armv7a-linux-gnueabihf/bin:$PATH" + ~~~ + +12. Install Stack + + Binary: get an + [existing `stack` binary](https://github.com/commercialhaskell/stack/releases) + and put it in `~/.local/bin`. + + From source, using Cabal (the tool): + + ~~~sh + wget http://downloads.haskell.org/~ghc/7.10.3/ghc-7.10.3-armv7-deb8-linux.tar.xz && \ + tar xvf ghc-7.10.3-armv7-deb8-linux.tar.xz && \ + cd ghc-7.10.3 && \ + ./configure --prefix=/opt/ghc-7.10.3 && \ + sudo make install && \ + cd .. + export PATH="/opt/ghc-7.10.3/bin:$PATH" + wget https://www.haskell.org/cabal/release/cabal-install-1.24.0.0/cabal-install-1.24.0.0.tar.gz &&&&& \ + tar xvf cabal-install-1.24.0.0.tar.gz && \ + cd cabal-install-1.24.0.0 && \ + EXTRA_CONFIGURE_OPTS="" ./bootstrap.sh && \ + cd .. && \ + export PATH="$HOME/.cabal/bin:$PATH" && \ + cabal update + ~~~ + + Edit `~/.cabal/config`, and set `executable-stripping: False` and + `library-stripping: False`. + + ~~~sh + cabal unpack stack && \ + cd stack-* && \ + cabal install && \ + mv ~/.cabal/bin/stack ~/.local/bin + ~~~
+ doc/maintainers/docker.md view
@@ -0,0 +1,180 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Docker images + +Each Stackage LTS release has two corresponding docker images in the +[fpco/stack-build](https://hub.docker.com/r/fpco/stack-build/) and +[fpco/stack-build-small](https://hub.docker.com/r/fpco/stack-build-small/) +repositories. The former contains every system library needed to build any +package in the snapshot, while the latter only contains a minimal set of system +libraries for basic programs. + +The Dockerfiles for building these images are in +[stackage/automated/dockerfiles](https://github.com/commercialhaskell/stackage/tree/master/automated/dockerfiles/). +There is also a +[build.sh](https://github.com/commercialhaskell/stackage/tree/master/automated/dockerfiles/build.sh) +script to help with building and pushing the images (see the +[README](https://github.com/commercialhaskell/stackage/tree/master/automated/dockerfiles/README.md) +for usage instructions). + +## Build images for new minor LTS snapshot + +In most cases, a new minor LTS snapshot just needs the previous LTS image to be +re-tagged and pushed. If the image needs a patch for the new minor LTS snapshot, +see the next section. + +Below, replace `<N>.<M>` with the minor LTS snapshot version. + +- Check out the `stable` branch of the + [Stack repository](https://github.com/commercialhaskell/stack/). + +- Build and push the images (both standard and `small` variants) using the + [build.sh](https://github.com/commercialhaskell/stackage/tree/master/automated/dockerfiles/build.sh) + script: + + ~~~text + ./build.sh --push lts-<N>.<M> + ./build.sh --push --small lts-<N>.<M> + ~~~ + +## Patch images for new minor LTS snapshot + +Below, replace `<N>.<M>` with the minor LTS snapshot version. and `<N>.<M-1>` +with the previous minor LTS snapshot version. + +- Check out the `stable` branch of the + [Stack repository](https://github.com/commercialhaskell/stack/). + +- In `stackage/automated/dockerfiles`, create a new `lts-<N>.<M>` directory. + +- Create `lts-<N>.<M>/Dockerfile`, starting with: + + ~~~dockerfile + FROM $DOCKER_REPO:lts-<N>.<M-1> + ~~~ + +- Add layers for any changes that need to be made to the image. + +- Build the new image using the + [build.sh](https://github.com/commercialhaskell/stackage/tree/master/automated/dockerfiles/build.sh) + script: + + ~~~text + ./build.sh lts-<N>.<M> + ./build.sh --small lts-<N>.<M> + ~~~ + +- Test the new image. For example, command: + + ~~~text + stack --snapshot=lts-<N>.<M> new image-test + cd image-test + stack --docker build + ~~~ + + This should use the image you just built. Make sure you test that the new + image actually contains the desired changes. + +- Follow the process in the previous section to push the images. + +## Build images for new major LTS snapshot release + +### Test a Dockerfile prior to new major LTS snapshot release + +Replace `<N>` with major version of new LTS snapshot, and `<N-1>` with previous +major LTS snapshot version. + +- Check out the `stable` branch of the + [Stack repository](https://github.com/commercialhaskell/stack/). + +- In `stackage/automated/dockerfiles`, create a new `lts-<N>.0` directory. + +- Copy `lts-<N-1>.0/Dockerfile` to `lts-<N>.0/Dockerfile`. + +- Check the `FROM` statement, make sure the Ubuntu version matches the Ubuntu + version used in the + [Stackage Dockerfile](https://github.com/commercialhaskell/stackage/blob/master/Dockerfile). + +- Update `GHC_VERSION` to match the version used by the + [latest nightly snapshot](https://www.stackage.org/nightly). + +- Set `LTS_SLUG` to the + [latest nightly snapshot](https://www.stackage.org/nightly) (this will be + temporary until the major LTS snapshot is actually released, at which point it + will be updated to `lts-<N>.0`). + +- Update `PID1_VERSION` and `STACK_VERSION` to the latest versions of those + tools. + +- Make sure `CUDA_VERSION` and `JVM_PATH` match what + [debian-bootstrap.sh](https://github.com/commercialhaskell/stackage/blob/master/debian-bootstrap.sh) + uses. + +- Update `LLVM_PATH` to the version required for the GHC version. This will be + shown on the download page for the GHC version, which you can reach from + https://www.haskell.org/ghc/. It should match the base directory used in + `CLANG_PURE_LLVM_INCLUDE_DIR` in + [debian-bootstrap.sh](https://github.com/commercialhaskell/stackage/blob/master/debian-bootstrap.sh) + (leaving off the `/include` suffix). + +- Update `BOOTSTRAP_COMMIT` to the Git commit ID of the latest + [debian-bootstrap.sh](https://github.com/commercialhaskell/stackage/blob/master/debian-bootstrap.sh). + +- Check for any other `lts-<N>.*/Dockerfile`s and make sure + `lts-<N>.0/Dockerfile` includes anything that was updated in those, if they're + still relevant for LTS-15 (note that a newer + [debian-bootstrap.sh](https://github.com/commercialhaskell/stackage/blob/master/debian-bootstrap.sh) + may already include those changes, so check there first). + +### Perform basic tests + +- Build the image: `docker build -t local/stack-build lts-<N>.0/`. + +- Ensure that all the directories listed in `PATH`, `CUDA_PATH`, and `CPATH` and + any other path-like environment variables actually exist in the image. + +- Try building a test package with the new image. Command: + + ~~~text + stack --snapshot=nightly new image-test` + cd image-test + stack --docker --docker-image=local/stack-build build + ~~~ + + This should build without needing to install GHC. + +- Build the "small" variant. Command: + + ~~~text + docker build -t local/stack-build-small --build-arg "VARIANT=small" lts-<N>.0/ + ~~~ + +- Try building a test package with the new small image. Command: + + ~~~text + stack --snapshot=nightly new small-image-test + cd small-image-test + stack --docker --docker-image=local/stack-build-small build + ~~~ + + This should build without needing to install GHC. + +### Build real image once major LTS snapshot has been released + +- Update `LTS_SLUG` to `lts-<N>.0` + +- Update `BOOTSTRAP_COMMIT` to the git commit ID of the latest + [debian-bootstrap.sh](https://github.com/commercialhaskell/stackage/blob/master/debian-bootstrap.sh). + +- Repeat the tests above, except use `lts-<N>.0` instead of `nightly`. + +- Build and push the real images (both standard and `small` variants) using the + [build.sh](https://github.com/commercialhaskell/stackage/tree/master/automated/dockerfiles/build.sh) + script: + + ~~~text + ./build.sh --push lts-<N>.0 + ./build.sh --push --small lts-<N>.0 + ~~~ + +- Commit and push the new Dockerfile to the `stable` branch.
+ doc/maintainers/docker_images.md view
@@ -0,0 +1,34 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Docker images + +Docker Hub includes Docker images under +[`fpco/stack-build'](https://hub.docker.com/r/fpco/stack-build). + +To update those images with a new version of Stack: + +1. Under + [commercialhaskell/stackage/automated/dockerfiles](https://github.com/commercialhaskell/stackage/tree/master/automated/dockerfiles/), + add `lts-X.Y/Dockerfile` (where `X.Y` is the latest Stackage Haskell LTS + version), containing (where `X.Z` is the previous Haskell LTS version, + and `X.Y.Z` is the newly released Stack version): + + ~~~dockerfile + FROM $DOCKER_REPO:lts-X.Z + ARG STACK_VERSION=X.Y.Z + RUN wget -qO- https://github.com/commercialhaskell/stack/releases/download/v$STACK_VERSION/stack-$STACK_VERSION-linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C /usr/local/bin '*/stack' + ~~~ + +2. Run `./build.sh lts-X.Y`. Then test that the new image has the new + version of Stack. For example, command: + + ~~~text + docker run --rm fpco/stack-build:lts stack --version + ~~~ + +3. Use the following commands to push the new image to the registry: + + ~~~text + ./build.sh --push lts-X.Y + ./build.sh --push --small lts-X.Y + ~~~
+ doc/maintainers/ghc.md view
@@ -0,0 +1,124 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Adding a new GHC version + +* Push new tag to our fork. Command: + + ~~~text + git clone git@github.com:commercialhaskell/ghc.git + cd ghc + git remote add upstream https://gitlab.haskell.org/ghc/ghc.git + git fetch upstream + git push origin ghc-X.Y.Z-release + ~~~ + +* [Publish a new GitHub release](https://github.com/commercialhaskell/ghc/releases/new) + with tag `ghc-X.Y.Z-release` and same name, with description noting where the + binidsts are mirrored from. For example: + + ~~~text + Unless otherwise indicated, bindists are mirrored from https://downloads.haskell.org/~ghc/ + * FreeBSD bindists are mirrored from http://distcache.FreeBSD.org/local-distfiles/arrowd/stack-bindists + * musl bindists are mirrored from https://github.com/redneb/ghc-alt-libc/releases + ~~~ + +* Download all the relevant GHC bindists from their sources, and upload them to + the just-created GitHub release (see + [stack-setup-2.yaml](https://github.com/fpco/stackage-content/blob/master/stack/stack-setup-2.yaml) + for the ones we used in the last GHC release). + + In the case of macOS, repackage the `.xz` bindist as a `.bz2`, since macOS + does not include `xz` by default or provide an easy way to install it. + + The script at `etc/scripts/mirror-ghc-bindists-to-github.sh` will help with + this. See the comments within the script. + +* [Edit stack-setup-2.yaml](https://github.com/fpco/stackage-content/edit/master/stack/stack-setup-2.yaml) + and add the new bindists, pointing to the GitHub release version. Be sure to + update the `content-length` and `sha1` values. + + Before committing, test using a command like: + + ~~~text + stack --snapshot=ghc-X.Y.Z setup --setup-info-yaml=path/to/stackage-content/stack/stack-setup-2.yaml + ~~~ + +* In [stackage-content](https://github.com/fpco/stackage-content), command: + + ~~~text + cd stack + ./update-global-hints.hs ghc-X.Y.Z + ~~~ + + and commit the changes. + +## Building GHC + +**NOTE: We are no longer building custom GHC bindists. This section remains for future reference, but GHC's build system has changed substantially since it was written.** + +TODO: look into using +https://github.com/bgamari/ghc-utils/blob/master/rel-eng/bin-release.sh, which +is the script used to official bindists. + +On systems with a small `/tmp`, you should set TMP and TEMP to an alternate +location. + +Setup the system based on these +[instructions](https://gitlab.haskell.org/ghc/ghc/wikis/building/preparation/linux). +On Ubuntu (`docker run -ti --rm ubuntu:16.04`): + +~~~text +apt-get update +apt-get install -y ghc alex happy make autoconf g++ git vim xz-utils automake libtool gcc libgmp-dev ncurses-dev libtinfo-dev python3 +~~~ + +On Void Linux (`docker run -ti --rm voidlinux/voidlinux bash`) command: + +~~~text +xbps-install -S curl gcc make xz ghc autoconf git vim automake gmp-devel ncurses-devel python3 cabal-install +cabal update +cabal install alex happy +~~~ + +For GHC >= 7.10.2, set the `GHC_VERSION` environment variable to the version to +build: + +* `export GHC_VERSION=8.2.2` +* `export GHC_VERSION=8.2.1` +* `export GHC_VERSION=8.0.2` +* `export GHC_VERSION=8.0.1` +* `export GHC_VERSION=7.10.3a` +* `export GHC_VERSION=7.10.2` + +then, from +[here](https://gitlab.haskell.org/ghc/ghc/wikis/building/quick-start), command: + +~~~text +git config --global url."git://github.com/ghc/packages-".insteadOf git://github.com/ghc/packages/ +git clone -b ghc-${GHC_VERSION}-release --recursive https://gitlab.haskell.org/ghc/ghc.git ghc-${GHC_VERSION} +cd ghc-${GHC_VERSION}/ +cp mk/build.mk.sample mk/build.mk +sed -i 's/^#BuildFlavour *= *perf$/BuildFlavour = perf/' mk/build.mk +./boot +./configure --enable-tarballs-autodownload +sed -i 's/^TAR_COMP *= *bzip2$/TAR_COMP = xz/' mk/config.mk +make -j$(cat /proc/cpuinfo|grep processor|wc -l) +make binary-dist +~~~ + +GHC 7.8.4 is slightly different. Command: + +~~~text +export GHC_VERSION=7.8.4 +git config --global url."git://github.com/ghc/packages-".insteadOf git://github.com/ghc/packages/ +git clone -b ghc-${GHC_VERSION}-release --recursive https://gitlab.haskell.org/ghc/ghc.git ghc-${GHC_VERSION} +cd ghc-${GHC_VERSION}/ +./sync-all --extra --nofib -r git://git.haskell.org get -b ghc-7.8 +cp mk/build.mk.sample mk/build.mk +sed -i 's/^#BuildFlavour *= *perf$/BuildFlavour = perf/' mk/build.mk +perl boot +./configure +sed -i 's/^TAR_COMP *= *bzip2$/TAR_COMP = xz/' mk/config.mk +make -j$(cat /proc/cpuinfo|grep processor|wc -l) +make binary-dist +~~~
+ doc/maintainers/haskellstack.org.md view
@@ -0,0 +1,173 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# HaskellStack.org + +The domain https://docs.haskellstack.org hosts online documentation for the +Stack project, using [Read the Docs](https://readthedocs.org/) with +[MkDocs](https://www.mkdocs.org/) and the Material for MkDocs +[theme](https://squidfunk.github.io/mkdocs-material/). + +The domain https://get.haskellstack.org provides URLs that redirect to URLs +used to install the Stack executable. + +## Read the Docs + +The Read the Docs project is named +['The Haskell Tool Stack'](https://readthedocs.org/projects/stack/). + +The set up on the Read the Docs web site involves two page redirects when there +are HTTP 404 Not Found errors: + + / -> /README/ + /README/ -> / + +The 'Home' MkDocs page is `doc/README.md`. + +The `/ -> /README/` redirect ensures that +https://docs.haskellstack.org/en/stable/ (for example) will, if not found, +redirect to https://docs.haskellstack.org/en/stable/README/. + +The `/README/ -> /` redirect ensures that +https://docs.haskellstack.org/en/latest/README/ (for example) will, if not +found, redirect to https://docs.haskellstack.org/en/latest/. + +MkDocs rendering of `README.md` differed before and after MkDocs 1.0. Prior to +MkDocs 1.0, `README.md` rendered to `/README/index.html`. From MkDocs 1.0, +`README.md` rendered to `/index.html`. The two redirects above ensure that the +Read the Docs flyout works when moving between different versions of the home +page using the flyout. + +Stack moved from MkDocs 0.17.3 to MkDocs 1.3.1 after publishing the +documentation for Stack 2.7.5. + +A configuration file, `.readthedocs.yaml` is included in the repository root +directory. See https://docs.readthedocs.io/en/stable/config-file/v2.html. It +specifies a Python requirements file in `doc/requirements.txt`. + +## MkDocs + +The `doc/requirements.txt` file pins the version of MkDocs. As at +2 September 2021 it is set to: + + mkdocs==1.3.1 + +A configuration file, `mkdocs.yml` is included in the repository root directory. +See https://www.mkdocs.org/user-guide/configuration/. + +`site_dir: _site` specifies the directory where the output HTML and other files +are created. This directory is added to the `.gitignore` file. + +MkDocs 1.3.0 replaced the `pages:` key with the `nav:` key. + +## Material for MkDocs + +Stack moved from the default `readthedocs` theme to Material for MkDocs after +publishing the documentation for Stack 2.7.5. The new theme has extensive online +documentation and features that the default theme lacked. + +The Material for MkDocs theme is loaded in the `doc/requirements.txt` file: + + mkdocs-material + +The theme is specified in the `mkdocs.yml` file: + +~~~yaml +theme: + name: material + palette: + primary: 'deep purple' + accent: 'deep purple' + icon: + logo: material/language-haskell +~~~ + +Read the Docs requires [JQuery](https://jquery.com/) for its JavaScript code to +inject the flyout menu. Material for MkDocs does not come with JQuery. So, the +following is required in the `mkdocs.yml` file: + +~~~yaml +extra_javascript: +- 'https://code.jquery.com/jquery-3.6.1.min.js' +~~~ + +The Read the Docs flyout is formatted with a `font-size` that is 90% of the +`body` `font-size`. Material for MkDocs has a `body` `font-size` that is +`0.5rem`, which is small. A little additional CSS is added to the `extra.css` +file, to force the final `font-size` to be `0.7rem`. That size is consistent +with that of other elements in the theme. + +~~~css +body { + font-size: 0.777778rem; +} +~~~ + +Material for MkDocs default suggestions for syntax highlighting in code blocks +are applied. They are specified in the `mkdocs.yml` file as: + +~~~yaml +markdown_extensions: +- pymdownx.highlight: + anchor_linenums: true +- pymdownx.inlinehilite +- pymdownx.snippets +- pymdownx.superfences +~~~ + +Other extensions to the basic Markdown syntax used include: + +* Admonitions + + !!! info + + This is an example of an 'info' admonition. + +* Content tabs, which can be nested + + !!! info + + Content tabs are used so that users of different operating systems, or + different distributions of Linux, can be presented with content specific + to their needs. + +* icons and emojis + + !!! info + + The `octicons-tag-24` icon (:octicons-tag-24:) is used to refer to + versions of Stack. The `material-cloud-download-outline` icon + (:material-cloud-download-outline:) is used to signify a download link. + The `octicons-beaker-24` icon (:octicons-beaker-24:) is used with + 'Experimental' to signify that a feature is experimental. + +## Testing online documentation + +Online documentation can be tested by establishing a branch on the repository +that is then configured on the Read the Docs web site as 'Active' but +'Hidden' - for example branch `mkdocs-test`. As the branch is 'Hidden' it does +not appear in the Read the Docs flyout or search results. + +## get.haskellstack.org redirects + +The https://get.haskellstack.org redirects are implemented with +[CloudFlare Pages](https://developers.cloudflare.com/pages/platform/redirects/) +and a `_redirects` file in the root of the +`commercialhaskell/get-haskellstack-org` GitHub +[repository](https://github.com/commercialhaskell/get-haskellstack-org). + +Each redirect is defined as a line in the file with format: + +~~~text +[source] [destination] +~~~ + +'Splats' are used in redirects. On matching, a splat (asterisk, `*`) will greedily match all characters and the matched value can be used in the redirect location with `:splat`. + +For example, for Stack 2.9.1: + +~~~text +/stable/* https://github.com/commercialhaskell/stack/releases/download/v2.9.1/stack-2.9.1-:splat +/upgrade/linux-x86_64-static.tar.gz https://github.com/commercialhaskell/stack/releases/download/v2.9.1/stack-2.9.1-linux-x86_64.tar.gz +/upgrade/* https://github.com/commercialhaskell/stack/releases/download/v2.9.1/stack-2.9.1-:splat +/ https://raw.githubusercontent.com/commercialhaskell/stack/stable/etc/scripts/get-stack.sh +~~~
+ doc/maintainers/msys.md view
@@ -0,0 +1,115 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Upgrading MSYS2 + +When installing GHC on Windows, Stack will also install +[MSYS2](http://www.msys2.org/). MSYS2 provides a Unix shell and environment, and +is necessary for such things as running configure scripts. This section explains +the steps required to upgrade the MSYS2 version used by Stack. + +1. Download latest installer(s) from MSYS2's website. Historically, there were + separate installers for 32 bit (`i686`) and 64 bit (`x86_64`). On + 17 May 2020, the MSYS2 project announced it did not plan to release any + further `i686` installers. An installer is an executable, versioned by a + date in the format YYYYMMDD - for example, `msys2-x86_64-20220503.exe`. + +2. Run the installer and install to the default location (`C:\msys64` for the + 64 bit version; the location for the 32 bit version was `C:\msys32`). Do not + use the installed version; it will create a `.bash_history` file if you do. + +3. Create an `.tar.xz` archive file for each relevant directory (eg + `C:\msys64`). That is best done using the same `7z` executable in Stack's + 'programs' directory (`stack path --programs`) that will be used to extract + files from the archive. That can be done in two steps: the first to create a + `.tar` archive, and the second to create a `.tar.xz` archive. If the current + working directory is Stack's 'programs' directory: + + ~~~text + ./7z a msys2-YYYYMMDD-x86_64.tar C:\msys64 + ./7z a msys2-YYYYMMDD-x86_64.tar.xz msys2-YYYYMMDD-x86_64.tar + rm msys2-YYYYMMDD-x86_64.tar # Tidy up + ~~~ + + !!! note + + Previously, the advice was that creating the archive file required a + version of [`tar`](https://www.gnu.org/software/tar/tar.html) that + supported the compression option `--xz`. The version of `tar` that is + supplied with Windows (`C:\Windows\System32\tar.exe`) does not support + that option, but MSYS2 can supply a + [version](https://packages.msys2.org/package/tar) that does (using its + `pacman` tool). Using the existing Stack-supplied MSYS2, in PowerShell + and located in a folder with write permissions (so the `.tar.xz` file + can be created), it was advised to command: + + ~~~text + stack exec -- pacman -S tar + stack exec -- tar cJf msys2-YYYYMMDD-x86_64.tar.xz C:\msys64 + ~~~ + + However, in the case of `msys2-20220503` that resulted in an archive + that could not extracted on a terminal that did not have elevated rights + ('Run as administrator') due to errors + `ERROR: Cannot create symbolic link : A required privilege is not held by the client`. + +4. Test that the Stack-supplied `7z` executable can extract the files in the + archive that has been created without error: + + ~~~test + ./7z x msys2-YYYYMMDD-x86_64.tar.xz + ./7z x msys2-YYYYMMDD-x86_64.tar + ~~~ + +5. Create a new release tagged and named `msys2-YYYYMMDD` in the `master` + branch of the + [commercialhaskell/stackage-content](https://github.com/commercialhaskell/stackage-content) + GitHub repository, uploading the tarball file(s) into that release. + +6. Changes need to be made to the + [stackage-content/stack/stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/blob/master/stack/stack-setup-2.yaml) + file, to switch over to using the newly uploaded files. For example + (extract): + + ~~~yaml + # For upgrade instructions, see: https://github.com/commercialhaskell/stack/blob/stable/doc/maintainers/msys.md + msys2: + windows32: + version: "20200517" + url: "https://github.com/fpco/stackage-content/releases/download/20200517/msys2-20200517-i686.tar.xz" + content-length: 79049224 + sha256: 9152ddf50c6bacfae33c1436338235f8db4b10d73aaea63adefd96731fb0bceb + windows64: + version: "20220503" + url: "https://github.com/commercialhaskell/stackage-content/releases/download/msys2-20220503/msys2-20220503-x86_64.tar.xz" + content-length: 93835868 + sha256: c918f66e984f70add313ee3a5c5b101132cd93d5a3f8e3555e129e2d3dcb3718 + ~~~ + + The `content-length:` key's value is the size of the file in bytes. It can + be obtained from the `Length` field of the `dir` command. The `sha256:` + key's value can be obtained from the command (in PowerShell): + + ~~~text + (Get-FileHash msys2-YYYYMMDD-x86_64.tar.xz -Algorithm SHA256).Hash.ToLower() + ~~~ + + The `sha256:` key only accepts lowercase hash results as values. + +7. The changed `stack-setup-2.yaml` file should be tested locally. This can be + done by: + + * temporarily disabling the existing local copy of MSYS2 by changing the + name of the `msys2-YYYYMMDD.installed` file in the `stack path --programs` + directory; and + + * executing the command: + + ~~~text + stack setup --setup-info-yaml <path to local copy of stack-setup-2.yaml> + ~~~ + + If all is well, the command should proceed to download the updated version + of MSYS2 that has been specified. + +8. Raise a pull request on `commercialhaskell/stackage-contents` for the + changes to the locally-tested `stack-setup-2.yaml` file.
+ doc/maintainers/releases.md view
@@ -0,0 +1,700 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Releases + +!!! todo "To do - Simplify the branch or version structure" + + Just release from the `master` branch (but keep the `stable` branch + tracking the latest stable release plus updates to documentation). + +## Version scheme + +A Stack package or executable may have a version with three or four components: +`X.Y.Z` or `X.Y.Z.A`. + +### Development or stable versions + +* Versions with an _even_ `Y` component are development versions (the `master` + branch) +* Versions with an _odd_ `Y` component are stable versions (the `stable` branch, + or in a `rc/vX.Y` release candidate branch for not-yet-released versions) + +### Unreleased or released versions + +* Versions with an _even_ `Z` component are unreleased versions (including + release candidates) +* Versions with an _odd_ `Z` component are released versions +* Except for the `release` branch (which matches exactly the most recent + release), all branches must have an even `Z` component +* Branches other than `stable`, `release`, and a `rc/vX.Y` release candidate + will always have a `0` `Z` component + +### Use of a fourth component + +* Release candidate binaries will be released with an odd `A` component +* Hackage-only dependency compatibility patch releases add a `A` component + (e.g. `v2.5.5.1`, in the `release` branch) +* Pre-release unstable binaries will be released with the date as the `A` + component (e.g. `2.14.0.20240126`) + +Examples: + +* `2.15.0.0`: `v2.15.x` series pre-release branch (`rc/v2.15` branch) +* `2.15.0.1`: first release candidate for first release of `v2.15.x` series + (`rc/v2.15` branch) +* `2.15.0.2`: continuing development on pre-release branch +* `2.15.0.3`: second release candidate for first release of `v2.15.x` series + (`rc/v2.15` branch) +* `2.15.1`: first release of the `2.15.x` series (`release` branch) +* `2.15.2`: development for second release of `2.15.x` series + (`stable` branch) +* `2.15.2.1`: first release candidate for second release of `2.15.x` series + (`rc/v2.15` branch) +* `2.15.3`: second release of `2.15.x` series (`release` branch) +* `2.15.3.1`: first Hackage-only patch of `2.15.3` (`release` branch) +* `2.15.3.2`: second Hackage-only patch of `2.15.3` (`release` branch) +* `2.14.0`: unstable development code (`master` branch) +* `2.14.0.20240126`: pre-release snapshot of unstable version (`master` branch) + +## Pre-release checks + +1. Check for any P0 and P1 issues that should be dealt with before release. + +2. Check for un-merged pull requests that should be merged before release. + +3. Ensure the `release` and `stable` branches are merged to the `master` + branch. + +4. Check the copyright dates, and update if needed. + +5. Check the backwards compatability section of `CONTRIBUTING.md` is up to + date. + +6. Ensure CI matrices in docs (travis-complex, appveyor, azure) have current + stackage snapshots and GHC versions (e.g. + https://github.com/commercialhaskell/stack/pull/4565/files) + +7. Update any `stack-*.yaml` that uses a `nightly` snapshot to the latest + nightly (go over the extra-deps too) and ensure the project builds and tests + pass. For example, command: + + ~~~text + stack build --stack-yaml=… --haddock --test --bench --no-run-benchmarks + ~~~ + +8. The Windows installer is built using an + [NSIS compiler](https://nsis.sourceforge.io/Main_Page). Check that the NSIS + compiler that will be used is capable of handling + [large strings](https://nsis.sourceforge.io/Special_Builds). + +9. Ensure the integration tests pass on Linux, macOS and Windows. + +10. Some people prefer, or need, to build Stack with Cabal (the tool). Check + that `cabal.project` is up to date (the specified `with-compiler:`). Check + that `cabal.config` is up to date and is not missing dependencies relevant + on Windows and non-Windows operating systems, following the instructions in + `cabal.project`. + +## Release preparation + +### A: In the `master` branch + +* `package.yaml`: bump to the next release candidate version (bump the second + component to the next odd number, ensure the third component is `0`, and add + patchlevel `0`; e.g. from `2.14.0` to `2.15.0.0`). + + !!! attention + + Be sure to update also `stack.cabal` (for example by using + `stack build --dry-run`). + +* `ChangeLog.md`: Check for any entries that snuck into the previous version's + changes due to merges (`git diff origin/stable HEAD ChangeLog.md`) + +### B: Create a new release candidate branch + +Cut a new release candidate (RC) branch named `rc/vX.Y` from the `master` +branch. + +### C: Return to the `master` branch + +1. `package.yaml`: bump version to the next unstable version (bump the second + component to the next even number, ensure the third component is `0`; e.g. + from `2.15.0` to `2.16.0`). + + !!! attention + + Be sure to update also `stack.cabal` (for example by using + `stack build --dry-run`). + +2. `Changelog.md`: + * Change the title of the existing **Unreleased changes** section to what + will be the next final (non-RC) release (e.g. `v2.15.1`). + * Add new "Unreleased changes" section: + + ~~~markdown + ## Unreleased changes + + Release notes: + + **Changes since vX.Y.Z:** + + Major changes: + + Behavior changes: + + Other enhancements: + + Bug fixes: + ~~~ + +3. `cabal.config`: Ensure the `stack` constraint is set to the same version as + in the `package.yaml`. + +### D: In the release candidate branch + +1. Review documentation for any changes that need to be made: + + * Ensure all the documentation pages are listed in the `mkdocs.yaml` file. + Use `git diff --stat origin/stable..HEAD doc/` to look for new or + deleted files. + * Any new documentation pages should have the "may not be correct for the + released version of Stack" warning at the top. + * Search for old Stack version, unstable Stack version, and the next + "obvious" possible versions in sequence, and `UNRELEASED` and replace + with next release version (`X.Y.1`, where Y is odd). + + !!! attention + + Do **NOT** update the repository's issue and pull request templates + (in the `.github` directory) to point at the new release version + yet! + + * Search for old snapshots, set to latest snapshot (e.g. in documentation + where it references the "currently the latest LTS") + * Look for any links to "latest" (`latest/`) documentation, replace with + version tag + +2. Check for any platform entries that need to be added to (or removed from): + + * [releases.yaml](https://github.com/fpco/stackage-content/blob/master/stack/releases.yaml), + * [install_and_upgrade.md](https://github.com/commercialhaskell/stack/blob/master/doc/install_and_upgrade.md), + * [get-stack.sh](https://github.com/commercialhaskell/stack/blob/master/etc/scripts/get-stack.sh), + * [doc/README.md](https://github.com/commercialhaskell/stack/blob/master/doc/README.md), + and + * `get.haskellstack.org` redirects. + +3. Re-do the pre-release checks (see the section above). + +4. Update `package.yaml` and `ChangeLog.md`. This step differs between a first, + second etc release candidate and a final release. + + === "First RC" + + * `package.yaml`: bump to first odd patchlevel version (e.g. + `X.Y.0.1`). + + * `ChangeLog.md`: Rename the “Unreleased changes” section to the same + version as `package.yaml`, and mark it clearly as a release + candidate (e.g. `vX.Y.0.1 (release candidate)`). Remove any empty + sections. + + === "Second, third etc RC" + + * `package.yaml`: bump to next odd patchlevel version (e.g. + `X.Y.0.3`). + + * `ChangeLog.md`: Rename the “Unreleased changes” section to the same + version as `package.yaml`, and mark it clearly as a release + candidate (e.g. `vX.Y.0.3 (release candidate)`). Remove any empty + sections. + + === "Final Release" + + * `package.yaml`: bump version to odd last component and no patchlevel + (e.g. from `X.Y.0.2` to `X.Y.1`). + + * `ChangeLog.md`: consolidate all the release candidate changes into a + single section for the final release version. + + !!! attention + + After updating `package.yaml`, be sure to update also `stack.cabal` (for + example by using `stack build --dry-run`). + +5. Ensure the `stack ==` constraint in `cabal.config` is set to be equal to the + same version as `package.yaml`. + +6. Follow the steps in the *Release process* section below that apply. + +## Release process + +The release process differs between a first, second etc release candidate and a +final release. + +=== "First, second etc RC" + + ### A: Integration tests workflow passes + + Ensure that the GitHub + [Integration Tests workflow](https://github.com/commercialhaskell/stack/actions?query=workflow%3A%22Integration+tests%22) + passes on the branch that you are releasing. + + This workflow will run automatically for the `rc/*` branch. + + ### B: Push a Git tag + + Push a Git tag. The tag should be `rc/vX.Y.Z.A`, with `X.Y.Z.A` matching the + version in `package.yaml`. + + For example, command: + + ~~~text + git tag -m rc/vX.Y.Z.A rc/vX.Y.Z.A + git push origin rc/vX.Y.Z.A + ~~~ + + ### C: Edit the draft GitHub release, and publish it + + Wait for the GitHub + [Integration Tests workflow](https://github.com/commercialhaskell/stack/actions?query=workflow%3A%22Integration+tests%22) + to complete for the branch you just created. This will create a draft GitHub + release and upload the bindists (plus signatures and hashes) to it. + + Edit the draft + [GitHub release](https://github.com/commercialhaskell/stack/releases/): + + * Add `(release candidate)` to the name field and ensure that + *This is a pre-release* is checked. + * Add the ChangeLog to the description. + + Publish the GitHub release. + + ### D: Consider adding other platforms to the GitHub release + + The + [Integration Tests workflow](https://github.com/commercialhaskell/stack/actions?query=workflow%3A%22Integration+tests%22) + is limited to the platforms supported by the GitHub-hosted runners + (currently, x86_64 and macOS/AArch64) and any self-hosted runners + (currently, only Linux/AArch64). However, it is possible to edit the GitHub + release to include binary distributions for other platforms. The + prerequisites are: + + * a computer with that platform (operating system, machine architecture); + * a sufficiently-recent existing version of Stack for that platform; + * a tool to print SHA checksums, such as `shasum` on Linux and macOS; and + * the GNU Privacy Guard tool (`gpg`), which has had imported the private key + used to sign Stack executables (see further below). + + The steps are similar to those in the workflow: + + 1. Change to the root directory of the Stack project. + + 2. `stack etc/scripts/release.hs check`, to check before building. + + 3. `stack etc/scripts/release.hs build`, to build. The output 'assets' + (`stack-<version>-<os>-<architecture> ...`) will be in + the `_release` directory in the root directory of the Stack project. + + 4. For each of the output assets, create a corresponding SHA 256 file with + a `.sha256` extension. For example (where `<asset>` is the name of the + file): + + ~~~text + shasum -a 256 <asset> > <asset>.sha256 + ~~~ + + 5. For each of the output assets, create a corresponding ASCII-armored + signature file with an `.asc` extension using `gpg`. For example (where + `<asset>` is the name of the file): + + ~~~text + gpg --digest-algo=sha512 --detach-sig --armor -u 0x575159689BEFB442 <asset> + ~~~ + + 6. Edit the GitHub release to include the output assets and their + corresponding `.sha256` and `.asc` files. + + The private key used to sign Stack executables can be exported from a + version of `gpg` to which it has previously been imported with: + + ~~~text + gpg --armor --export-secret-key 0x575159689BEFB442 + ~~~ + + The private key, so obtained, can be imported into `gpg` by: + + 1. Commanding `gpg --import`. + + 2. Pasting the private key. + + 3. Entering Ctrl+D and Enter. + + ### E: Update versions and `ChangeLog.md` for 'unreleased' + + In the `rc/vX.Y` branch: + + * `package.yaml`: bump the version number. Bump the fourth component to an + even number (e.g. from `2.15.0.1` to `2.15.0.2`). + + !!! attention + + Be sure to update also `stack.cabal` (for example by using + `stack build --dry-run`). + + * `ChangeLog.md`: Add an “Unreleased changes” section (update the “changes + since” version): + + ~~~markdown + ## Unreleased changes + + Release notes: + + **Changes since vX.Y.Z:** + + Major changes: + + Behavior changes: + + Other enhancements: + + Bug fixes: + ~~~ + + ### F: Request update of GHCup's metadata + + Raise a pull request at the + [`haskell/ghcup-metadata`](https://github.com/haskell/ghcup-metadata) GitHub + repository to request an addition to GHCup's latest metadata configuration + file for prereleases, tagged as the latest prerelease. In the metadata, + change the tags for any past Stack prereleases to indicate that they are no + longer the latest prerelease. + + ### G: Announce the release candidate + + Announce the release candidate to the following mailing lists + + * haskell-cafe@haskell.org + + !!! note + + You have to be a member of the mailing list to post to it. See the + list's + [interface](https://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe) + + * haskell-stack@googlegroups.com + + !!! note + + Members of the group can post but posts from new members are held + for moderation. + + * commercialhaskell@googlegroups.com + + !!! note + + Members of the group can post but posts from new members are held + for moderation. + + Announce the release candidate on the + [Haskell Community](https://discourse.haskell.org/c/announcements/10/l/latest). + + Announce the release candidate in the `#stack-users` channel of the Haskell + Foundation's Slack workspace. + + Announce the release candidate in the + [Haskell Stack room](https://matrix.to/#/#haskell-stack:matrix.org) + (address `#haskell-stack:matrix.org`) on [Matrix](https://matrix.org/). + + Announce the release candidate in Reddit's + [Haskell](https://www.reddit.com/r/haskell/) community. + + In each case, use the subject (change 'first' to 'second' etc for subsequent + release candidates): + + * `ANN: first release candidate for stack-X.Y.Z` + + In the message, include: + + * a link to the release on GitHub + (`https://github.com/commercialhaskell/stack/releases/tag/rc/vX.Y.Z.A`) to + download it + * the release description from Github. + +=== "Final Release" + + ### A: Integration tests workflow passes + + Ensure that the GitHub + [Integration Tests workflow](https://github.com/commercialhaskell/stack/actions?query=workflow%3A%22Integration+tests%22) + passes on the branch that you are releasing. + + This workflow will run automatically for `rc/*` branches. + + ### B: Push a Git tag + + Push a Git tag. The tag should be `vX.Y.Z`, where `X.Y.Z` matches the + version in `package.yaml`. + + For example, command: + + ~~~text + git tag -m vX.Y.Z vX.Y.Z + git push origin vX.Y.Z + ~~~ + + ### C: Edit the draft GitHub release, and publish it + + Wait for the GitHub + [Integration Tests workflow](https://github.com/commercialhaskell/stack/actions?query=workflow%3A%22Integration+tests%22) + to complete for the tag you just created. This will create a draft GitHub + release and upload the bindists (plus signatures and hashes) to it. + + Edit the draft + [GitHub release](https://github.com/commercialhaskell/stack/releases/): + + * Add the ChangeLog to the description. + * Get the list of contributors to the release and add it to the + description. For example, command: + + === "Unix-like" + + ~~~text + git shortlog -s origin/release..HEAD|sed 's/^[0-9 \t]*/* /'|LC_ALL=C sort -f + ~~~ + + === "Windows (with PowerShell)" + + ~~~text + (git shortlog -s origin/release..HEAD) -Replace '^[0-9 \t]*', '* ' | Sort-Object + ~~~ + + Publish the GitHub release. + + ### D: Consider adding other platforms to the GitHub release + + The + [Integration Tests workflow](https://github.com/commercialhaskell/stack/actions?query=workflow%3A%22Integration+tests%22) + is limited to the platforms supported by the GitHub-hosted runners + (currently, x86_64 and macOS/AArch64) and any self-hosted runners + (currently, only Linux/AArch64). However, it is possible to edit the GitHub + release to include binary distributions for other platforms. The + prerequisites are: + + * a computer with that platform (operating system, machine architecture); + * a sufficiently-recent existing version of Stack for that platform; + * a tool to print SHA checksums, such as `shasum` on Linux and macOS; and + * the GNU Privacy Guard tool (`gpg`), which has had imported the private key + used to sign Stack executables (see further below). + + The steps are similar to those in the workflow: + + 1. Change to the root directory of the Stack project. + + 2. `stack etc/scripts/release.hs check`, to check before building. + + 3. `stack etc/scripts/release.hs build`, to build. The output 'assets' + (`stack-<version>-<os>-<architecture> ...`) will be in + the `_release` directory in the root directory of the Stack project. + + 4. For each of the output assets, create a corresponding SHA 256 file with + a `.sha256` extension. For example (where `<asset>` is the name of the + file): + + ~~~text + shasum -a 256 <asset> > <asset>.sha256 + ~~~ + + 5. For each of the output assets, create a corresponding ASCII-armored + signature file with an `.asc` extension using `gpg`. For example (where + `<asset>` is the name of the file): + + ~~~text + gpg --digest-algo=sha512 --detach-sig --armor -u 0x575159689BEFB442 <asset> + ~~~ + + 6. Edit the GitHub release to include the output assets and their + corresponding `.sha256` and `.asc` files. + + The private key used to sign Stack executables can be exported from a + version of `gpg` to which it has previously been imported with: + + ~~~text + gpg --armor --export-secret-key 0x575159689BEFB442 + ~~~ + + The private key, so obtained, can be imported into `gpg` by: + + 1. Commanding `gpg --import`. + + 2. Pasting the private key. + + 3. Entering Ctrl+D and Enter. + + ### E: Upload to Hackage and reset branches + + Upload the `stack` package to Hackage with the command: + + ~~~text + stack upload . --pvp-bounds=lower + ~~~ + + Reset the `release` branch to the released commit. For example, with the + commands: + + ~~~text + git checkout release + git merge --ff-only vX.Y.Z + git push origin release + ~~~ + + Update the `stable` branch to the released commit. For example, with the + commands: + + ~~~text + git checkout stable + git merge --ff-only vX.Y.Z + git push origin stable + ~~~ + + Merge any changes made in the RC, `release` or `stable` branches to the + `master` branch. Be careful about version and `ChangeLog.md`. It is best to + do this by making a `ci/merge-stable-to-master` branch and waiting for CI to + pass, then merging. If anything is complicated to merge, consider making it + a pull request and getting it reviewed rather than merging immediately. + + Delete the RC branch, both locally and on the remote. For example with the + commands: + + ~~~text + git branch -d rc/vX.Y + git push origin :rc/vX.Y + ~~~ + + ### F: Activate the version on Read The Docs + + Activate the version for new release tag, on + [readthedocs.org](https://readthedocs.org/projects/stack/versions/). + + Ensure that the `stable` documentation has updated. + + ### G: Update get.haskellstack.org redirects + + Update the https://get.haskellstack.org redirects by updating the + `_redirects` file in the root of the + `commercialhaskell/get-haskellstack-org` GitHub + [repository](https://github.com/commercialhaskell/get-haskellstack-org). + + For further information, see the + [get.haskellstack.org redirects](haskellstack.org.md#gethaskellstackorg-redirects) + documentation. + + Test with the commands: + + === "Unix-like" + + ~~~text + curl -vL https://get.haskellstack.org/stable/linux-x86_64.tar.gz >/dev/null + curl -vL https://get.haskellstack.org/upgrade/linux-x86_64.tar.gz >/dev/null + ~~~ + + === "Windows (with PowerShell)" + + ~~~text + curl -vL https://get.haskellstack.org/stable/linux-x86_64.tar.gz >NUL + curl -vL https://get.haskellstack.org/upgrade/linux-x86_64.tar.gz >NUL + ~~~ + + and make sure it redirects to the new version. + + ### H: Update versions and `ChangeLog.md` for 'unreleased' + + In the `stable` branch: + + * `package.yaml`: bump the version number. Bump the third component to an + even number (e.g. from `2.15.1` to `2.15.2`). + + !!! attention + + Be sure to update also `stack.cabal` (for example by using + `stack build --dry-run`). + + * `ChangeLog.md`: Add an “Unreleased changes” section (update the “changes + since” version): + + ~~~markdown + ## Unreleased changes + + Release notes: + + **Changes since vX.Y.Z:** + + Major changes: + + Behavior changes: + + Other enhancements: + + Bug fixes: + ~~~ + + ### I: Update the repository's issue and pull request templates + + The repository's issue and pull request templates are the `.github` + directory. Update them to refer to the new release version (`X.Y.Z`). + + ### J: Request update of GHCup's metadata + + Raise a pull request at the + [`haskell/ghcup-metadata`](https://github.com/haskell/ghcup-metadata) GitHub + repository to request an addition to GHCup's latest metadata configuration + files for releases and 'vanilla' releases, tagged as the latest release. + (The GHCup project will decide whether, and when, to recommend the release.) + In the metadata, change the tags for any past Stack releases to indicate + that they are no longer the latest release. + + ### K: Announce the release + + Announce the release to the following mailing lists + + * haskell-cafe@haskell.org + + !!! note + + You have to be a member of the mailing list to post to it. See the + list's + [interface](https://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe) + + * haskell-stack@googlegroups.com + + !!! note + + Members of the group can post but posts from new members are held + for moderation. + + * commercialhaskell@googlegroups.com + + !!! note + + Members of the group can post but posts from new members are held + for moderation. + + Announce the release on the + [Haskell Community](https://discourse.haskell.org/c/announcements/10/l/latest). + + Announce the release in the `#stack-users` channel of the Haskell + Foundation's Slack workspace. + + Announce the release in the + [Haskell Stack room](https://matrix.to/#/#haskell-stack:matrix.org) + (address `#haskell-stack:matrix.org`) on [Matrix](https://matrix.org/). + + Announce the release in Reddit's + [Haskell](https://www.reddit.com/r/haskell/) community. + + In each case, use the subject: + * `ANN: stack-X.Y.Z` + + In the message, include: + + * the release description from Github.
+ doc/maintainers/self-hosted_runners.md view
@@ -0,0 +1,87 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Self-hosted runners + +[GitHub Actions](https://docs.github.com/en/actions) is used to do CI on Stack. +The `linux-arm64` job of the `integration-tests.yml` workflow runs on a +self-hosted runner for Linux and ARM64. + +The current basic setup is: + +* FP Complete has an Oracle Cloud account that provides a free tier that + includes a really powerful ARM64 machine; +* within Oracle Cloud, FP Complete are running an Ubuntu/ARM64 instance; and +* on that instance, FP Complete are running the GitHub Runner software. + +The runner name is `stack-github-action3` and the machine name is +`stack-github-action3`. + +Occasionally Oracle will turn off the machine because: + +* Oracle thinks it is not being used (because of the free tier); and/or +* other things, like disk space filling up. + +The disk space can fill up due to obsolete Docker images, versions of GHC +installed by Stack or obsolete snapshots created by Stack. + +## Managing the `stack-github-action3` runner + +With the appropriate authority installed on the server, a maintainer can manage +the runner remotely using SSH, with command +`ssh ubuntu@arm-runner.stackage.org`. + +!!! info + + The authority is the addition of the maintainer's SSH public key to the end + of file `~/.ssh/authorized_keys` on the server. + +This is best done using [`tmux`](https://github.com/tmux/tmux/wiki), a terminal +multiplexer, as follows: +~~~sh +$ # In a shell, command tmux to create a new session with a single window with a +$ # single pane (a pseudo terminal). The session will be displayed on the screen +$ # by a client: +$ tmux new-session +$ # Send the following command to that pseudo terminal, to connect to the +$ # remote host: +$ ssh ubuntu@arm-runner.stackage.org +$ # In the remote host, change to the actions-runner directory: +$ cd actions-runner +$ # In the remote host, start the runner: +$ ./run.sh +$ # Detach the current client from the session by the key combination of +$ # 'C-b' 'd' (where 'C-b' is CTRL+b). The session will continue to run in the +$ # background: +$ C-b d +~~~ + +The available disk space can be queried with command `df -h`; the relevant entry +is for filesystem `/dev/sda1`. + +If the available space is low, that may be due to unncessary GHC versions +installed in Stack's `programs` directory. + +## The `ghc-arm-5` runner + +From 9 February 2024, the Haskell Foundation sought to provide an alternative +runner named `ghc-arm-5` but that was based on NixOS and proved to be +incompatible. + +## Alternatives to the self-hosted runners + +One alternative to the self-hosted runners is to build statically-linked Stack +executables for Linux/AArch64 on macOS/AArch64. This can be done thanks to +the multi-architecture Docker images built and published by Olivier Benz, at +https://gitlab.com/benz0li/ghc-musl. + +GitHub provides a GitHub-hosted macOS/AArch64 runner (`macOS-14`). +Unfortunately, that is macOS/M1 and the M1 machine architecture does not support +nested virtualisation. This rules out using Docker, as the runner is itself a +virtual machine. + +However, this solution can be applied locally and the build outputs for the +Linux/AArch64 platform added manually to the result of the GitHub workflow. + +The experimental Haskell script `etc/scripts/release-linux-aarch64.hs` is +intended to facilitate the building of statically-linked Stack executables for +Linux/AArch64 on macOS/AArch64.
+ doc/maintainers/stack_errors.md view
@@ -0,0 +1,674 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +## Stack's errors + +In connection with considering Stack's support of the +[Haskell Error Index](https://errors.haskell.org/) initiative, this page seeks +to take stock of the errors that Stack itself can raise, by reference to the +`master` branch of the Stack repository. Last updated: 2024-06-03. + +* `Stack.main`: catches exceptions from action `commandLineHandler`. + + - `ExitCode` + - `throwIO` + +* `Stack.main`: catches exceptions from action `run`: + + - `ExitCode` (`exitWith`) + - `PrettyException` (`exitFailure`) + - `SomeException` (`exitFailure`) + + The following types are instances of `Control.Exception.Exception` and + `Show`. Some are instances of `Stack.Prelude.PrettyException`. Some data + constructors have strict fields but that is not documented below: + + - `Control.Concurrent.ExecuteException` + + ~~~haskell + [S-2816] = InconsistentDependenciesBug + ~~~ + + - `GHC.GHC.Utils.GhcPkg.Main.Compat` + + ~~~haskell + [S-6512] = CannotParse String String String + [S-3384] | CannotOpenDBForModification FilePath IOException + [S-1430] | SingleFileDBUnsupported FilePath + [S-5996] | ParsePackageInfoExceptions String + [S-3189] | CannotFindPackage PackageArg (Maybe FilePath) + [S-9323] | CannotParseRelFileBug String + [S-7651] | CannotParseDirectoryWithDBug String + ~~~ + + - `Options.Applicative.Builder.Extra.OptionsApplicativeExtraException` + + ~~~haskell + [S-2797] = FlagNotFoundBug + ~~~ + + - `Stack.Build.CabalVersionPrettyException` + + ~~~haskell + [S-5973] = CabalVersionNotSupported Version + ~~~ + + - `Stack.Build.ConstructPlan.NotOnlyLocal` + + ~~~haskell + [S-1727] = NotOnlyLocal [PackageName] [Text] + ~~~ + + - `Stack.BuildPlan.BuildPlanException` + + ~~~haskell + [S-7571] = UnknownPackages (Path Abs File) (Map PackageName (Maybe Version, Set PackageName)) (Map PackageName (Set PackageIdentifier)) + [S-2045] | SnapshotNotFound SnapName + [S-8559] | NeitherCompilerOrSnapshotSpecified Text + [S-5743] | DuplicatePackagesBug + ~~~ + + - `Stack.CLI.CliPrettyException` + + ~~~haskell + [S-4639] = NoArgumentsBug + ~~~ + + - `Stack.Clean.CleanException` + + ~~~haskell + [S-9463] = NonLocalPackages [PackageName] + [S-6321] | DeletionFailures [(Path Abs Dir, SomeException)] + ~~~ + + - `Stack.Config.Docker.ConfigDockerException` + + ~~~haskell + [S-8575] = SnapshotNotSupportedException (Maybe Project) (Maybe AbstractSnapshot) + ~~~ + + - `Stack.Config.Nix.ConfigNixException` + + ~~~haskell + [S-2726] = NixCannotUseShellFileAndPackagesException + [S-9317] | GHCMajorVersionUnspecified + [S-8605] | OnlyGHCSupported + ~~~ + + - `Stack.ConfigCmd.ConfigCmdException` + + ~~~haskell + [S-3136] = NoProjectConfigAvailable + ~~~ + + - `Stack.Constants.ConstantsException` + + ~~~haskell + [S-6057] = WiredInPackagesNotParsedBug + ~~~ + + - `Stack.Coverage.CoveragePrettyException` + + ~~~haskell + [S-6361] = NonTestSuiteTarget PackageName + [S-2321] | NoTargetsOrTixSpecified + [S-9975] | NotLocalPackage PackageName + ~~~ + + - `Stack.DependencyGraph.DependencyGraphException` + + ~~~haskell + [S-7071] = DependencyNotFoundBug GhcPkgId + [S-7151] | PackageNotFoundBug PackageName + ~~~ + + - `Stack.Exec.ExecException` + + ~~~haskell + [S-1541] = InvalidPathForExec FilePath + ~~~ + + - `Stack.Exec.ExecPrettyException` + + ~~~haskell + [S-8251] = PackageIdNotFoundBug String + [S-2483] | ExecutableToRunNotFound + [S-8600] | NoPackageIdReportedBug + [S-7371] | InvalidExecTargets [Text] + ~~~ + + - `Stack.GhcPkg` + + `[S-6716]` used in `unregisterGhcPkgIds` + + - `Stack.Ghci.GhciException` + + ~~~haskell + [S-6716] = InvalidPackageOption String + [S-9632] | LoadingDuplicateModules + [S-3600] | MissingFileTarget String + [S-9906] | Can'tSpecifyFilesAndTargets + [S-5188] | Can'tSpecifyFilesAndMainIs + ~~~ + + - `Stack.Ghci.GhciPrettyException` + + ~~~haskell + [S-6948] = GhciTargetParseException [StyleDoc] + [S-1939] | CandidatesIndexOutOfRangeBug + ~~~ + + - `Stack.Hoogle.HoogleException` + + ~~~haskell + [S-9669] = HoogleOnPathNotFoundBug + ~~~ + + - `Stack.Hoogle.HooglePrettyException` + + ~~~haskell + [S-1329] = HoogleNotFound StyleDoc + [S-3025] | HoogleDatabaseNotFound + ~~~ + + - `Stack.Init.InitException` + + ~~~haskell + [S-2747] | NoPackagesToIgnoreBug + ~~~ + + - `Stack.Init.InitPrettyException` + + ~~~haskell + [S-8332] = SnapshotDownloadFailure SomeException + [S-8009] | ConfigFileAlreadyExists FilePath + [S-5267] | PackageNameInvalid [FilePath] + [S-1833] | NoMatchingSnapshot (NonEmpty SnapName) + [S-6395] | SnapshotMismatch RawSnapshotLocation String + [S-2422] | SnapshotPartial RawSnapshotLocation String + ~~~ + + - `Stack.List.ListPrettyException` + + ~~~haskell + [S-4926] = CouldNotParsePackageSelectors [StyleDoc] + ~~~ + + - `Stack.Lock.LockPrettyException` + + ~~~haskell + [S-1353] = WritingLockFileError (Path Abs File) Locked + ~~~ + + - `Stack.Ls.LsException` * + + ~~~haskell + [S-3421] = ParseFailure [Value] + ~~~ + + - `Stack.New.NewPrettyException` + + ~~~haskell + [S-2135] = ProjectDirAlreadyExists String (Path Abs Dir) + [S-1688] | DownloadTemplateFailed Text String VerifiedDownloadException + [S-3650] | LoadTemplateFailed TemplateName FilePath + [S-9582] | ExtractTemplateFailed TemplateName FilePath String + [S-9490] | TemplateInvalid TemplateName StyleDoc + [S-5682] | MagicPackageNameInvalid String + [S-3113] | AttemptedOverwrites [Path Abs File] + ~~~ + + - `Stack.Nix.NixException` + + ~~~haskell + [S-7384] = CannotDetermineProjectRoot + ~~~ + + - `Stack.PackageDump.PackageDumpException` + + ~~~haskell + [S-4257] = MissingSingleField Text (Map Text [Line]) + [S-2016] | Couldn'tParseField Text [Line] + ~~~ + + - `Stack.Query.QueryException` + + ~~~haskell + [S-4419] = SelectorNotFound [Text] + [S-8422] | IndexOutOfRange [Text] + [S-4360] | NoNumericSelector [Text] + [S-1711] | CannotApplySelector Value [Text] + ~~~ + + - `Stack.Runners.RunnersException` + + ~~~haskell + [S-7144] = CommandInvalid + [S-8314] | DockerAndNixInvalid + [S-8641] | NixWithinDockerInvalid + [S-5107] | DockerWithinNixInvalid + ~~~ + + - `Stack.SDist.SDistPrettyException` + + ~~~haskell + [S-6439] = CheckException (NonEmpty PackageCheck) + [S-9595] | CabalFilePathsInconsistentBug (Path Abs File) (Path Abs File) + [S-7875] | ToTarPathException + ~~~ + + - `Stack.Script.ScriptException` + + ~~~haskell + [S-4994] = MutableDependenciesForScript [PackageName] + [S-1691] | AmbiguousModuleName ModuleName [PackageName] + [S-5067] | ArgumentsWithNoRunInvalid + [S-9469] | NoRunWithoutCompilationInvalid + [S-5055] | FailedToParseScriptFileAsDirBug (Path Rel File) + [S-9464] | FailedToParseFileAsDirBug (Path Abs Dir) + ~~~ + + - `Stack.Setup.PerformPathCheckingException` + + ~~~haskell + [S-1991] = ProcessExited ExitCode String [String] + ~~~ + + - `Stack.Setup.SetupException` + + ~~~haskell + [S-2076] = WorkingDirectoryInvalidBug + [S-3967] | StackBinaryArchiveZipUnsupportedBug + ~~~ + + - `Stack.Setup.SetupPrettyException` + + ~~~haskell + [S-7441] = GHCInstallFailed SomeException StyleDoc String [String] (Path Abs Dir) (Path Abs Dir) (Path Abs Dir) + [S-2476] | InvalidGhcAt (Path Abs File) SomeException + [S-4764] | ExecutableNotFound [Path Abs File] + [S-9953] | SandboxedCompilerNotFound [String] [Path Abs Dir] + [S-1852] | UnsupportedSetupCombo OS Arch + [S-2126] | MissingDependencies [String] + [S-9443] | UnknownCompilerVersion (Set Text) WantedCompiler (Set ActualCompiler) + [S-6810] | UnknownOSKey Text + [S-5159] | GHCSanityCheckCompileFailed SomeException (Path Abs File) + [S-8948] | RequireCustomGHCVariant + [S-2905] | ProblemWhileDecompressing (Path Abs File) + [S-9561] | SetupInfoMissingSevenz + [S-7748] | UnsupportedSetupConfiguration + [S-5308] | MSYS2NotFound Text + [S-5127] | UnwantedCompilerVersion + [S-1540] | UnwantedArchitecture + [S-8668] | GHCInfoNotValidUTF8 UnicodeException + [S-4878] | GHCInfoNotListOfPairs + [S-2965] | GHCInfoMissingGlobalPackageDB + [S-5219] | GHCInfoMissingTargetPlatform + [S-8299] | GHCInfoTargetPlatformInvalid String + [S-2574] | CabalNotFound (Path Abs File) + [S-8488] | GhcBootScriptNotFound + [S-1128] | HadrianScriptNotFound + [S-1906] | URLInvalid String + [S-1648] | UnknownArchiveExtension String + [S-4509] | Unsupported7z + [S-3158] | TarballInvalid String + [S-5252] | TarballFileInvalid String (Path Abs File) + [S-1827] | UnknownArchiveStructure (Path Abs File) + [S-9476] | StackReleaseInfoNotFound String + [S-4461] | StackBinaryArchiveNotFound [String] + [S-6617] | HadrianBindistNotFound + [S-7227] | DownloadAndInstallCompilerError + [S-6636] | StackBinaryArchiveUnsupported Text + [S-7871] | StackBinaryNotInArchive String Text + [S-5046] | FileTypeInArchiveInvalid Entry Text + [S-4132] | BinaryUpgradeOnOSUnsupported OS + [S-3249] | BinaryUpgradeOnArchUnsupported Arch + [S-4230] | ExistingMSYS2NotDeleted (Path Abs Dir) IOException + ~~~ + + - `Stack.StackException` + + ~~~haskell + [S-2186] = InvalidReExecVersion String String + ~~~ + + - `Stack.Storage.User.StorageUserException` + + ~~~haskell + [S-8196] = CompilerFileMetadataMismatch + [S-5378] | GlobalPackageCacheFileMetadataMismatch + [S-2673] | GlobalDumpParseFailure + [S-8441] | CompilerCacheArchitectureInvalid Text + ~~~ + + - `Stack.Templates.TemplatesPrettyException` + + ~~~haskell + [S-8143] = DownloadTemplatesHelpFailed HttpException + [S-6670] | TemplatesHelpEncodingInvalid String UnicodeException + ~~~ + + - `Stack.Types.Build.BuildException` + + ~~~haskell + [S-7178] = Couldn'tFindPkgId PackageName + [S-3127] | Couldn'tParseTargets [Text] + [S-2154] | UnknownTargets (Set PackageName) (Map PackageName Version) (Path Abs File) + [S-1995] | TestSuiteFailure PackageIdentifier (Map Text (Maybe ExitCode)) (Maybe (Path Abs File)) ByteString + [S-3819] | TestSuiteTypeUnsupported TestSuiteInterface + [S-5797] | LocalPackageDoesn'tMatchTarget PackageName Version Version + [S-3118] | NoSetupHsFound (Path Abs Dir) + [S-4925] | InvalidGhcOptionsSpecification [PackageName] + [S-7987] | TestSuiteExeMissing Bool String String String + [S-8027] | CabalCopyFailed Bool String + [S-5510] | LocalPackagesPresent [PackageIdentifier] + [S-7168] | CouldNotLockDistDir (Path Abs File) + [S-7868] | TaskCycleBug PackageIdentifier + [S-8923] | PackageIdMissingBug PackageIdentifier + [S-7371] | AllInOneBuildBug + [S-6739] | MultipleResultsBug PackageName [DumpPackage] + [S-3121] | TemplateHaskellNotFoundBug + [S-6901] | HaddockIndexNotFound + [S-5452] | ShowBuildErrorBug + [S-2696] | CallStackEmptyBug + ~~~ + + - `Stack.Types.Build.BuildPrettyException` + + ~~~haskell + [S-4804] = ConstructPlanFailed [ConstructPlanException] (Path Abs File) (Path Abs Dir) ParentMap (Set PackageName) (Map PackageName [PackageName]) + [S-7282] | ExecutionFailure [SomeException] + [S-7011] | CabalExitedUnsuccessfully ExitCode PackageIdentifier (Path Abs File) [String] (Maybe (Path Abs File)) [Text] + [S-6374] | SetupHsBuildFailure ExitCode (Maybe PackageIdentifier) (Path Abs File) [String] (Maybe (Path Abs File)) [Text] + [S-8506] | TargetParseException [StyleDoc] + [S-7086] | SomeTargetsNotBuildable [(PackageName, NamedComponent)] + [S-8664] | InvalidFlagSpecification [UnusedFlags] + [S-8100] | GHCProfOptionInvalid + [S-1727] | NotOnlyLocal [PackageName] [Text] + [S-6362] | CompilerVersionMismatch (Maybe (ActualCompiler, Arch)) (WantedCompiler, Arch) GHCVariant CompilerBuild VersionCheck WantedCompilerSetter Text + ~~~ + + - `Stack.Types.Compiler.CompilerException` + + ~~~haskell + [S-7903] = GhcjsNotSupported + [S-7972] | PantryException PantryException + ~~~ + + - `Stack.Types.Config.Exception.ConfigException` + + ~~~haskell + [S-8981] | ParseCustomSnapshotException Text ParseException + [S-2206] | NoProjectConfigFound (Path Abs Dir) (Maybe Text) + [S-4964] | UnexpectedArchiveContents [Path Abs Dir] [Path Abs File] + [S-2040] | UnableToExtractArchive Text (Path Abs File) + [S-1641] | BadStackVersionException VersionRange + [S-8773] | NoSuchDirectory FilePath + [S-4335] | NoSuchFile FilePath + [S-3938] | ParseGHCVariantException String + [S-8530] | BadStackRoot (Path Abs Dir) + [S-7613] | Won'tCreateStackRootInDirectoryOwnedByDifferentUser (Path Abs Dir) (Path Abs Dir) + [S-8707] | UserDoesn'tOwnDirectory (Path Abs Dir) + [S-3605] | ManualGHCVariantSettingsAreIncompatibleWithSystemGHC + [S-6816] | NixRequiresSystemGhc + [S-5027] | NoSnapshotWhenUsingNoProject + [S-3803] | NoLTSWithMajorVersion Int + [S-5472] | NoLTSFound + ~~~ + + - `Stack.Types.Config.Exception.ConfigPrettyException` + + ~~~haskell + [S-6602] = ParseConfigFileException (Path Abs File) ParseException + [S-7462] | StackWorkEnvNotRelativeDir String + [S-5470] | DuplicateLocalPackageNames [(PackageName, [PackageLocation])] + [S-6854] | BadMsysEnvironment MsysEnvironment Arch + [S-5006] | NoDefaultMsysEnvironmentBug + [S-8398] | ConfigFileNotProjectLevelBug + ~~~ + + - `Stack.Types.Config.ParseAbsolutePathException` + + ~~~haskell + [S-9437] = ParseAbsolutePathException String String + ~~~ + + - `Stack.Types.Docker.DockerException` + + ~~~haskell + [S-3223] = DockerMustBeEnabledException + [S-9779] | OnlyOnHostException + [S-9105] | InspectFailedException String + [S-6626] | NotPulledException String + [S-5841] | InvalidImagesOutputException String + [S-9608] | InvalidPSOutputException String + [S-2240] | InvalidInspectOutputException String + [S-6092] | PullFailedException String + [S-6218] | DockerTooOldException Version Version + [S-8252] | DockerVersionProhibitedException [Version] Version + [S-6170] | BadDockerVersionException VersionRange Version + [S-5827] | InvalidVersionOutputException + [S-7112] | HostStackTooOldException Version (Maybe Version) + [S-5832] | ContainerStackTooOldException Version Version + [S-4078] | CannotDetermineProjectRootException + [S-7058] | DockerNotInstalledException + [S-6894] | UnsupportedStackExeHostPlatformException + [S-1512] | DockerStackExeParseException String + ~~~ + + - `Stack.Types.GhcPkgId.GhcPkgIdParseFail` + + ~~~haskell + [S-5359] = GhcPkgIdParseFail Text + ~~~ + + - `Stack.Types.Package.PackageException` + + ~~~haskell + [S-8072] = PackageInvalidCabalFile (Either PackageIdentifierRevision (Path Abs File)) (Maybe Version) [PError] [PWarning] + [S-5394] | MismatchedCabalIdentifier PackageIdentifierRevision PackageIdentifier + [S-2203] | CabalFileNameParseFail FilePath + [S-8854] | CabalFileNameInvalidPackageName FilePath + [S-4623] | ComponentNotParsedBug + ~~~ + + - `Stack.Types.Snapshot.TypesSnapshotException` + + ~~~haskell + [S-8787] = ParseSnapshotException Text + [S-4865] | FilepathInDownloadedSnapshot Text + ~~~ + + - `Stack.Types.Storage.StoragePrettyException` + + ~~~haskell + [S-8835] = StorageMigrationFailure Text (Path Abs File) SomeException + ~~~ + + - `Stack.Types.TemplateName.TypesTemplateNameException` + + ~~~haskell + [S-7410] = DefaultTemplateNameNotParsedBug String + ~~~ + + - `Stack.Unpack.UnpackPrettyException` + + ~~~haskell + [S-3515] = UnpackDirectoryAlreadyExists (Set (Path Abs Dir)) + [S-2628] | CouldNotParsePackageSelectors [String] + ~~~ + + - `Stack.Upgrade.UpgradePrettyException` + + ~~~haskell + [S-8761] = SnapshotOptionInvalid + [S-3642] | NeitherBinaryOrSourceSpecified + [S-8716] | ExecutableFailure + [S-7114] | CommitsNotFound String String + [S-9668] | StackInPackageIndexNotFound + [S-6648] | VersionWithNoRevision + ~~~ + + - `Stack.Upload.UploadPrettyException` + + ~~~haskell + [S-2256] = AuthenticationFailure + [S-6108] | ArchiveUploadFailure Int [String] String + [S-2837] | DocsTarballInvalid [(String, Path Abs File)] + [S-3179] | ItemsInvalid [FilePath] + [S-3030] | NoItemSpecified String + [S-5908] | PackageDirectoryInvalid [FilePath] + [S-7274] | PackageIdNotSpecifiedForDocsUploadBug + [S-5860] | PackageIdSpecifiedForPackageUploadBug + [S-5955] | TarGzFileNameInvalidBug String + ~~~ + + - `System.Process.Pager.PagerException` + + ~~~haskell + [S-9392] = PagerExitFailure CmdSpec Int + ~~~ + + \* The instance of `Show` is derived. + +* `Stack.Build.Execute.singleBuild`: catches exceptions in `cabal ...` + + `throwM` + +* `Stack.Build.Source.getFileDigestMaybe`: catches exceptions in + `liftM Just . withSourceFile fp $ getDigest` + + `throwM` + +* `Stack.Config.configFromConfigMonoid`: + + ~~~text + [S-8432] Stack's 'programs' path contains a space character and has no alternative + short ('8 dot 3') name. This will cause problems with packages that use the + GNU project's 'configure' shell script. Use the 'local-programs-path' + configuration option to specify an alternative path. The current path is: + <path> + ~~~ + +* `Stack.Coverage.generateHpcReport`: catches exceptions from + `findPackageFieldForBuiltPackage` + + ~~~text + <exception> + ~~~ + +* `Stack.Coverage.generateHpcReportInternal`: + + ~~~text + [S-4634] Didn't find .tix for <report> - expected to find it at <path>. + ~~~ + +* `Stack.Coverage.generateHpcReportInternal`: + + ~~~text + [S-8215] <exception> + Error occurred while producing <report>" + ~~~ + +* `Stack.Coverage.generateHpcReportInternal`: + + ~~~text + [S-6829] Error: The <report> did not consider any code. One possible cause of this is + if your test-suite builds the library code (see Stack issue #1008). It may + also indicate a bug in Stack or the hpc program. Please report this issue if + you think your coverage report should have meaningful results. + ~~~ + +* `Stack.Coverage.readTixOrlog`: + + ~~~text + [S-3521] Error while reading tix: <exeception> + ~~~ + +* `Stack.Coverage.readTixOrlog`: + + ~~~text + [S-7786] Failed to read tix file <path> + ~~~ + +* `Stack.Coverage.updateTixFile`: + + ~~~text + [S-2887] Failed to read <file> + ~~~ + +* `Stack.Ghci.buildDepsAndInitialSteps`: catches exeception from + `buildLocalTargets` + + ~~~text + <exception> + ~~~ + +* `Stack.GhcPkg.createDatabase`: + + ~~~text + [S-9735] Unable to create package database at <path> + ~~~ + +* `Stack.Lock.loadYamlThrow`: + + `Data.Yaml.AesonException` + + `throwIO` + +* `Stack.Package.resolveGlobFiles`: + + `Control.Exception.Base.IOException` + + `throwIO` + +* `Stack.Runners.withConfig`: + + ~~~text + [S-7353] Error when running shouldUpgradeCheck: <exception> + ~~~ + +* `Stack.Script.scriptCmd`: + + Error used because warnings are surpressed. + + ~~~text + Ignoring override stack.yaml file for script command: <path> + ~~~ + +* `Stack.Script.scriptCmd`: + + Error used because warnings are surpressed. + + ~~~text + Ignoring SYLGlobalProject for script command + ~~~ + +* `Stack.SDist.getSDistTarball`: + + ~~~text + [S-8399] Error building custom-setup dependencies: <exception> + ~~~ + +* `Stack.Setup.downloadStackExe`: catches exceptions from `performPathChecking` + + ~~~text + <exception> + ~~~ + +* `Stack.Upload.uploadBytes`: + + ~~~text + [S-2804] forbidden upload + Usually means: you've already uploaded this package/version combination + Ignoring error and continuing, full message from Hackage below: + <Hackage_message> + ~~~ + +* `Stack.Upload.uploadBytes`: + + ~~~text + [S-4444] service unavailable + This error some times gets sent even though the upload succeeded + Check on Hackage to see if your package is present + <Hackage_message> + ~~~
+ doc/maintainers/team_process.md view
@@ -0,0 +1,262 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Stack Maintainer Team Process + +## Purpose of this document + +This guide is intended to formalize the process by which the `Stack` maintainer +team operates. We expect it'll evolve over time as experience makes clearer +what works best in practice. + +Having a well-documented set of processes and responsibilities has been +instrumental in effectively maintaining the `Stackage` project across a +distributed team +([see the `Stackage` curators' guide +](https://github.com/commercialhaskell/stackage/blob/master/CURATORS.md)) +and we hope to replicate that success here. + +## Goals + +The goals of the `Stack` maintainer team are to: + +- Ensure that incoming bug reports and feature requests are properly triaged, + answered, and/or escalated. + +- Provide timely review of, and feedback on, incoming pull requests. + +- Set up clear channels of communication for users to make support requests. + +- Keep Stack up-to-date with its upstream dependencies, including new GHC and + Cabal releases, and libraries Stack depends on. + +- Increase the [bus factor](https://en.wikipedia.org/wiki/Bus_factor) of the + project, encouraging more people to contribute heavily to the codebase and + take ownership of it. + +- Make it easy to improve the documentation and test coverage of the project. + +The sections below detail various activities by the `Stack` team to realize +these goals. + +## Issue triage + +The maintainer team provides ongoing review and responses to newly-filed GitHub +issues and pull requests. From experience, we find it's easiest to have a +single person "on call" at any given time. Therefore, the team rotates shifts +on a weekly basis. The "on call" triager is responsible for: + +- Reviewing incoming issues and pull requests on GitHub. + +- Answering questions he/she is able to. + +- Merging PRs he/she feels comfortable reviewing. + +- Closing out irrelevant/misplaced issues. + +- Pulling in another maintainer to assist if necessary. + +The goal of the triager role is to facilitate continual, smooth progress of +`Stack`'s development and to provide triagers an opportunity to become more +familiar with how the project runs. + +This is one path to getting a lot of experience with the codebase, plus great +interaction with the rest of the maintainer team, without necessarily taking on +major coding tasks. + +## Time commitment + +Someone considering joining the issue triager team may be wondering: + +> "How large of a time investment is necessary?" + +That’s a great question for anyone considering taking on this role. It’s +frankly somewhat uncertain right now since we’re only getting started, but we +can venture a reasonable guess: + +We currently average about one new issue per day. Assuming that each issue +entails roughly ten-to-fifteen minutes of total interaction on the part of the +triager (before passing it off to someone else, answering a support question, +etc) that amounts to about one or two hours spent per week being on-call. + +Again, these estimates will evolve over time as we settle into an optimal +process, but for now we anticipate growing the team to about eight members +(which is the size of the `Stackage` team as well), each of whom is likely to +spend about two hours in total on upkeep work every eight weeks. + +## Issue and pull request interaction guidelines + +These guidelines apply to all members of the maintainer team. + +- Be courteous. + +- Avoid leaving issues and PRs in an ambiguous state. By default, when you + respond to an issue/PR, you’re taking responsibility for shepherding it to + completion. Be explicit if you’re passing it to someone else, or asking the + submitter for more info/updates/etc. + +- Use labels, assignees, and milestones wherever possible. + +- If you know you’ll be unable to answer for a significant period of time, say + so. Even better: ask someone else to take over from you. + +## Assessing feature requests and enhancement PRs + +**NB: this section is very likely to evolve over time as well.** + +A frequent source of new GitHub issues is users who would like to propose some +enhancement and/or change to how `Stack` currently operates. + +Some of these are both small and obviously beneficial, in which case the +triager should feel empowered to "green light" the idea if it makes sense to do +so. + +If the proposal is already in the form of an actionable PR the triager may +review and merge at their discretion. + +Oftentimes though, the request is larger and more far-reaching in nature. + +Perhaps the requester is unaware of the extent to which his or her change would +impact other people's workflows or related components in the code. Conversely, +they may have a deep understanding of its implications and feel strongly that +it would be a valuable improvement, whereas it's not so clear to the triager. + +Discerning which requests should be considered "small" and which warrant +broader collaboration is admittedly an inexact science. Use your best judgment +and don't sweat the occasional mistake if you approve something you thought was +small but ultimately wasn't. + +In the case of medium-to-large sized feature requests, it's best to solicit +feedback from at least one or two of the core `Stack` developers. You may use +GitHub @mentions to draw the relevant contributors' attention to the issue in +question. If you're not sure who's best to consult you should ask on +`#stack-collaborators`. + +Try to be clear to the requester that you're opening the discussion up to more +participants and that the proposal will require thoughtful consideration +(probably a majority vote) before any decision is made. + +Also remember that busy schedules, lack of complete familiarity with a given +subject, strong-yet-opposing opinions held by equally rational people, and many +other factors often collude to halt forward progress in arriving at firm +conclusions in such situations... If at all possible, try to keep things +on-track and concrete. + +*Regardless of feature size, bear in mind that sometimes the best answer is a +respectful "no".* + +*If feasible, propose alternative solutions or educate the user in preference to +complicating `Stack` or accepting scope-creep.* + +With respect to assessing a PR's code, @snoyberg has outlined some +[tips for successfully getting one's work merged +](https://www.snoyman.com/blog/2017/06/how-to-send-me-a-pull-request) +into his projects which may be helpful to `Stack` triagers when performing +reviews, as well. + +## Real-time communications + +At present, the maintainer team mostly communicates via a rather quiet channel +called [`#stack-collaborators`](../CONTRIBUTING/#slack-channel) in the +Haskell Foundation's Slack workspace, although we may migrate to some other +platform in the future. + +## Dealing with support issues + +We encourage users to submit support requests via GitHub issues and try to +consolidate our efforts in addressing questions there. Other platforms, such as +Reddit, StackOverflow, et al, may be helpful as well but the `Stack` +maintainers team makes no guarantees about regularly checking them. + +*We may decide to offload support questions elsewhere in the future, but for +now the most important thing is to direct users to a single destination.* + +## Issue vs pull request + +Sometimes it is ambiguous whether something should be opened as an issue to +discuss a change, versus a pull request including the change. A guiding +principle here is: if it will take longer to open an issue than a PR, open the +PR. As an extreme example: if you have a small documentation typo correction, +open a PR, it will _definitely_ take less time than opening an issue and +describing the change you'd like to make. This logic can sometimes apply to +minor code changes. Use your best judgement. + +## Issue closing policy + +We need to strike a balance in issue handling between keeping a maintainable +set of issues—thereby making the lives of maintainers, contributors, and +users easier—and allowing legitimate issues to remain open. The end goal +of this is: any open issue indicates "this deserves attention in the near +future." Before this policy existed, issues actually meant "maybe someone will +deal with this someday." + +The policy for closing an issue depends entirely on the type of issue we're +looking at. + +When closing an issue, please provide a brief explanation for why the issue was +closed, such as a reference to a PR, a comment about lack of clarification, +etc. + +!!! note + + The following sections establish rules under which a bug report will be + closed by the maintainer team. The goal is to avoid a situation where issues + linger in an indeterminate state. The maintainer team is allowed to + disregard these "rules" at any point. In other words: the goal isn't to + allow people to "lawyer" issues. + +### Discussion + +Some issues are for discussing the project. These issues should start with a +clear question, have an owner, and be closed when either: + +* The original question has been answered +* There is no clear question or owner +* No progress has been made in 30 days + +Discussions are typically opened by maintainers and contributors. + +### Support + +Support questions are requests for assistance in using Stack. They must have a +clear set of steps followed by the user and a desired outcome. Support requests +sometimes overlap with bug reports, handled next. Support requests are closed +when: + +* The user decides their question is answered +* No clarification to questions from the Stack team is given for 30 days +* The question is determined out of scope by the Stack team + +### Bug report + +A bug report describes a misbehavior in Stack itself. There are some cases +where an issue may appear somewhere between a support request and a bug report. +The Stack team will determine which category an issue falls into. Bug reports +must include clear reproduction steps, an expected outcome, and an actual +outcome. Bug reports are closed when: + +* The bug is fixed on the `master` or `stable` branch (NOTE: we do not wait for + fixes to be released before closing issues) +* The Stack team is unable to reproduce the issue +* No clarification to questions from the Stack team is given for 30 days +* The bug is determined to be out of scope by the Stack team, such as being an + upstream issue + +### Feature request + +Feature requests are usually clear, but sometimes have overlap with one of the +above topics. Determination of an issue being a feature request will be made by +the Stack team. Features are closed when: + +* The feature is implemented on the `master` or `stable` branch +* The Stack team decides that the feature is not desired in the project +* If no one offers to implement the feature for 30 days + +Note that, to account for the last bullet, we have a +[Wishlist](https://github.com/commercialhaskell/stack/wiki/Wishlist) wiki page. We +recommend closing issues with a message such as the following: + +> Closing due to lack of implementation progress in the past 30 days. We +> attempt to keep the Stack issue tracker focused on active work items. If you +> are still interested in this feature and would like to see it implemented in +> the future, please add it to the +> [Wishlist](https://github.com/commercialhaskell/stack/wiki/Wishlist) Wiki page.
− doc/new_command.md
@@ -1,137 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack new` command - -~~~text -stack new PACKAGE_NAME [--bare] [--[no-]init] [TEMPLATE_NAME] - [-p|--param KEY:VALUE] [DIR(S)] [--omit-packages] [--force] - [--ignore-subdirs] -~~~ - -`stack new` creates a new project using a project template. - -By default: - -* the project is created in a new directory named after the package. Pass the - `--bare` flag to create the project in the current directory; - -* the project is initialised for use with Stack. Pass the `--no-init` flag to - skip such initialisation; and - -* the project template is the one specified by the -[default-template](yaml_configuration.md#default-template) option. - -A package name acceptable to Cabal comprises an alphanumeric 'word'; or two or -more such words, with the words separated by a hyphen/minus character (`-`). A -word cannot be comprised only of the characters `0` to `9`. - -An alphanumeric character is one in one of the Unicode Letter categories -(Lu (uppercase), Ll (lowercase), Lt (titlecase), Lm (modifier), or Lo (other)) -or Number categories (Nd (decimal), Nl (letter), or No (other)). - -!!! note - - In the case of Hackage and acceptable package names, an alphanumeric - character is limited to one of `A` to `Z`, `a` to `z`, and `0` to `9`. - -!!! note - - The name of a project is not constrained to be an acceptable package name. A - single-package project can be renamed to differ from the name of its - package. - -The `--param <key>:<value>` option specifies a key-value pair to populate a key -in a template. The option can be specified multiple times. - -The arguments specifying directories and the `--ignore-subdirs`, `--force` and -`--omit-packages` flags are as for the [`stack init` command](init_command.md). -These arguments are ignored if the `--no-init` flag is passed. - -If a snapshot is specified at the command line and the project is initialised -for use with Stack, `stack new` will try to use it. For further information, see -the documentation for the [`--snapshot`](global_flags.md#-snapshot-option) and -[`--resolver`](global_flags.md#-resolver-option) options. - -## Project templates - -A project template file can be located in a repository named `stack-templates` -on GitHub, GitLab or Bitbucket; at a URL; or on the local file system. - -Project template file names have the extension `.hsfiles`. The extension does -not need to be specified with `stack new`. - -A project template file `my-template.hsfiles` in a repository -`username/stack-templates` on GitHub, GitLab or Bitbucket can be specified -with `stack new` as: - -~~~test -<service>:username/my-template -~~~ - -where `<service>` is one of `github` for [GitHub](https://github.com/), -`gitlab` for [GitLab](https://gitlab.com), or `bitbucket` for -[Bitbucket](https://bitbucket.com). - -The default service is GitHub, the default username is `commercialhaskell` and -the default project template name is `new-template`. - -## Examples - -Create a project for package `my-project` in new directory `my-project` with the -default project template file and initialise it for use with Stack: - -~~~text -stack new my-project -~~~ - -Create a project for package `my-package` in the current directory with the -default project template file and initialise it for use with Stack: - -~~~text -stack new my-package --bare -~~~ - -Create a project with the `rio` project template at the default repository and -initialise it for use with Stack: - -~~~text -stack new my-project rio -~~~ - -Create a project with the `mysql` project template provided by the -`yesodweb/stack-templates` repository on GitHub and initialise it for use with -Stack: - -~~~text -stack new my-project yesodweb/mysql -~~~ - -Create a project with the `my-template` project template provided by the -`username/stack-templates` repository on Bitbucket and initialise it for use -with Stack: - -~~~text -stack new my-project bitbucket:username/my-template -~~~ - -Create a project with the `my-template.hsfiles` project template file at -`https://example.com` and initialise it for use with Stack: - -~~~text -stack new my-project https://example.com/my-template -~~~ - -Create a project with the local project template file -`<path_to_template>/my-template.hsfiles` and initialise it for use with Stack: - -~~~text -stack new my-project <path_to_template_file>/my-template -~~~ - -Create a project with the `simple` project template file at the default -repository (which does not use Hpack and a `package.yaml` file) and do not -initialise it for use with Stack (`stack init` could be used subsequently): - -~~~text -stack new my-project --no-init simple -~~~
− doc/nix_integration.md
@@ -1,439 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Nix integration - -[:octicons-tag-24: 0.1.10.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.10.0) - -[Nix](https://nixos.org/) is a purely functional package manager. Stack can be -configured to integrate with Nix. Integration provides these benefits: - -* more reproducible builds. This is because fixed versions of any system - libraries and commands required to build the project are automatically built - using Nix and managed locally for each project. These system packages never - conflict with any existing versions of these libraries on your system. That - they are managed locally to the project means that you don't need to alter - your system in any way to build any odd project pulled from the Internet; and -* implicit sharing of system packages between projects. This means you don't - have more copies on-disk than you need. - -The Nix package manager is a pre-requisite for integration. On Linux (including -Windows Subsystem for Linux) and macOS, it can be downloaded and installed from -the [Nix download page](https://nixos.org/download.html). - -When integrated with Nix, Stack handles Haskell dependencies as it usually does -and the Nix package manager handles the _non-Haskell_ dependencies needed by the -Haskell packages. - -Stack downloads Haskell packages from [Stackage](https://www.stackage.org/lts) -and builds them locally. Stack uses Nix to download -[Nix packages][nix-search-packages]. These provide the GHC compiler and external -C libraries that you would normally install manually. - -Nix's `nix-shell` starts an interactive shell based on a Nix expression. Stack -can automatically create a Nix build environment in the background using -`nix-shell`. There are two alternative options to create such a build -environment: - -1. provide a list of [Nix packages][nix-search-packages] -2. provide a `shell.nix` file that gives you more control over the libraries and - tools available inside the shell. - -A `shell.nix` file requires writing code in Nix's -[custom language][nix-language]. Use this option only if you know Nix and have -special requirements, such as using custom Nix packages that override the -standard ones or using system libraries with special requirements. - -### Checking the Nix installation - -Once Nix is installed, the Nix commands (`nix-shell` etc) should be available. -If they are not, it could be because the file -`$HOME/.nix-profile/etc/profile.d/nix.sh` is not sourced by your shell. - -You should either: - -1. run `source ~/.nix-profile/etc/profile.d/nix.sh` each time you open a - terminal and need Nix; or -2. add the command `source ~/.nix-profile/etc/profile.d/nix.sh` to your - `~/.bashrc` or `~/.bash_profile` file. - -A Nix path can be specified between angle brackets, e.g. `<nixpkgs>`, and the -directories listed in the `NIX_PATH` environment variable will be searched for -the given file or directory name. Stack makes use of path `<nixpkgs>`. From -Nix 2.4, `NIX_PATH` is not set by `nix.sh`. If `NIX_PATH` is not set, Nix will -fall back to (first) `$HOME/.nix-defexpr/channels` in impure and unrestricted -evaluation mode. However, Stack may use a pure Nix mode (see further -[below](#pure-and-impure-nix-shells)). That directory can be appended to -`NIX_PATH` with -`export NIX_PATH=${NIX_PATH:+$NIX_PATH:}$HOME/.nix-defexpr/channels`. For -information about how Stack itself can configure `NIX_PATH`, see further -[below](#nix-package-sources). - -### Enable Nix integration - -On NixOS, Nix integration is enabled by default; on other operating systems it -is disabled. To enable Nix integration, add the following section to your Stack -YAML configuration file (`stack.yaml` or `config.yaml`): - -~~~yaml -nix: - enable: true # false by default, except on NixOS -~~~ - -The equivalent command line flag (which will prevail) is `--[no-]nix`. Passing -any `--nix-*` option on the command line will imply the `--nix` option. - -If Nix integration is not enabled, Stack will notify the user if a `nix` -executable is on the PATH. If that notification is unwanted, it can be muted by -setting Stack's configuration option -[`notify-if-nix-on-path`](yaml_configuration.md#notify-if-nix-on-path) to -`false`. - -With Nix integration enabled, `stack build` and `stack exec` will automatically -launch themselves in a local build environment (using `nix-shell` behind the -scenes). It is not necessary to run `stack setup`, unless you want to cache a -GHC installation before running a build. - -**Known limitation on macOS:** currently, `stack --nix ghci` fails on macOS, due -to a bug in GHCi when working with external shared libraries. - -### Supporting both Nix and non-Nix developers - -With Nix integration enabled in Stack's YAML configuration file, every developer -of your project needs to have Nix installed, but the developer also gets all -external libraries automatically. - -Julien Debon of Tweag has published a [blog post][tweag-blog-post] on -*Smooth, non-invasive Haskell Stack and Nix shell integration* (2 June 2022). -The post explains how to set things up so that both Nix and non-Nix developers -can work together on the same project. The `tweag/haskell-stack-nix-example` -[GitHub repository][tweag-example] provides an example of working Stack and Nix -shell integration to accompany the post. - -Nix 2.4 (released 1 November 2021) introduced a new and experimental format to -package Nix-based projects, known as 'flakes'. - -The example below adapts and extends the example accompanying the blog post -above to use Nix flakes. The `flake.nix` file is: - -~~~nix -{ - description = "my project description"; - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - inputs.flake-utils.url = "github:numtide/flake-utils"; - - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - - hPkgs = - pkgs.haskell.packages."ghc8107"; # need to match Stackage LTS version - # from stack.yaml snapshot - - myDevTools = [ - hPkgs.ghc # GHC compiler in the desired version (will be available on PATH) - hPkgs.ghcid # Continuous terminal Haskell compile checker - hPkgs.ormolu # Haskell formatter - hPkgs.hlint # Haskell codestyle checker - hPkgs.hoogle # Lookup Haskell documentation - hPkgs.haskell-language-server # LSP server for editor - hPkgs.implicit-hie # auto generate LSP hie.yaml file from cabal - hPkgs.retrie # Haskell refactoring tool - # hPkgs.cabal-install - stack-wrapped - pkgs.zlib # External C library needed by some Haskell packages - ]; - - # Wrap Stack to work with our Nix integration. We don't want to modify - # stack.yaml so non-Nix users don't notice anything. - # - no-nix: We don't want Stack's way of integrating Nix. - # --system-ghc # Use the existing GHC on PATH (will come from this Nix file) - # --no-install-ghc # Don't try to install GHC if no matching GHC found on PATH - stack-wrapped = pkgs.symlinkJoin { - name = "stack"; # will be available as the usual `stack` in terminal - paths = [ pkgs.stack ]; - buildInputs = [ pkgs.makeWrapper ]; - postBuild = '' - wrapProgram $out/bin/stack \ - --add-flags "\ - --no-nix \ - --system-ghc \ - --no-install-ghc \ - " - ''; - }; - in { - devShells.default = pkgs.mkShell { - buildInputs = myDevTools; - - # Make external Nix c libraries like zlib known to GHC, like - # pkgs.haskell.lib.buildStackProject does - # https://github.com/NixOS/nixpkgs/blob/d64780ea0e22b5f61cd6012a456869c702a72f20/pkgs/development/haskell-modules/generic-stack-builder.nix#L38 - LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath myDevTools; - }; - }); -} -~~~ - -Check-in this `flake.nix` to your project's repository. Run the `nix develop` -command (it searches for `flake.nix` by default) and you'll find a new -`flake.lock` file. That file that pins the precise nixpkgs package set. Check-in -that `flake.lock` file as well, and every Nix developer of your project will use -precisely the same package set. - -### GHC through Nix packages - -Nix integration will instruct Stack to build inside a local build environment. -That environment will also download and use a -[GHC Nix package](https://search.nixos.org/packages?query=haskell.compiler.ghc) -matching the required version of the configured Stack -[snapshot](yaml_configuration.md#snapshot). - -Enabling Nix integration means that packages will always be built using the -local GHC from Nix inside your shell, rather than your globally installed system -GHC (if any). - -Stack can use only GHC versions that are in the Nix package repository. The -[Nixpkgs master branch](https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/haskell-modules) -usually picks up new versions quickly, but it takes two or three days before -those updates arrive in the `unstable` channel. Release channels, like -`nixos-22.05`, receive those updates only occasionally -- say, every two or -three months --, so you should not expect them to have the latest compiler -available. Fresh NixOS installs use a release version by default. - -To identify whether a given compiler is available, you can use the following Nix -command: - -~~~sh -nix-env -f "<nixpkgs>" -qaP -A haskell.compiler.ghc924 -haskell.compiler.ghc924 ghc-9.2.4 -~~~ - -If Nix doesn't know that version of GHC, you'll see the following error message: - -~~~sh -nix-env -f "<nixpkgs>" -qaP -A haskell.compiler.ghc999 -error: attribute ‘ghc999’ in selection path ‘haskell.compiler.ghc999’ not found -~~~ - -You can list all known Haskell compilers in Nix with the following: - -~~~sh -nix-instantiate --eval -E "with import <nixpkgs> {}; lib.attrNames haskell.compiler" -~~~ - -Alternatively, use `nix repl`, a convenient tool to explore nixpkgs: - -~~~sh -nix repl -~~~ - -In the REPL, load nixpkgs and get the same information through autocomplete: - -~~~sh -nix-repl> :l <nixpkgs> -nix-repl> haskell.compiler.ghc<Tab> -~~~ - -You can type and evaluate any Nix expression in the Nix REPL, such as the one we -gave to `nix-instantiate` earlier. - -### External C libraries through Nix packages - -To let Nix manage external C libraries, add (for example) the following section -to your Stack YAML configuration file: - -~~~yaml -nix: - enable: true - packages: [zlib, glpk, pcre] -~~~ - -The equivalent command line option is `--nix-packages "zlib glpk pcre"`. - -The `packages` key and the `shell-file` key (see further below) are -alternatives. Specifying both results in an error. - -The example above will instruct Stack to build inside a local build environment -that will have the Nix packages -[zlib](https://search.nixos.org/packages?query=zlib), -[glpk](https://search.nixos.org/packages?query=glpk) and -[pcre](https://search.nixos.org/packages?query=pcre) -installed, which provide the C libraries of the same names. - -**Note:** currently, Stack only discovers dynamic and static libraries in the -`lib/` folder of any Nix package, and likewise header files in the `include/` -folder. If you're dealing with a package that doesn't follow this standard -layout, you'll have to deal with that using a custom `shell.nix` file (see further below). - -### External C libraries through a `shell.nix` file - -In Nix, a 'derivation' is a description of a build action and its result is a -Nix store object. Nix's [custom language][nix-language] can provide a fully -customized derivation as an environment to use. To specify such a `shell.nix` -file, add the following section to your Stack YAML configuration file: - -~~~yaml -nix: - enable: true - shell-file: shell.nix -~~~ - -The equivalent command line option (which will prevail) is -`--nix-shell-file shell.nix`. - -The `packages` and `shell-file` keys are alternatives. Specifying both results -in an error. - -Defining a `shell.nix` file allow you to override some Nix derivations, for -instance to change some build options of the libraries you use, or to set -additional environment variables. For further information, see the -[Nix manual][nix-manual-exprs]. - -The `shell.nix` file that is the equivalent of the -`packages: [zlib, glpk, pcre]` example above is: - -~~~nix -{ghc}: -with (import <nixpkgs> {}); - -haskell.lib.buildStackProject { - inherit ghc; - name = "myEnv"; - buildInputs = [ zlib glpk pcre ]; -} -~~~ - -The `buildStackProject` utility function is documented in the -[Nixpkgs manual][nixpkgs-manual-haskell]. - -Stack expects the `shell.nix` file to define a function of with one argument -called `ghc` (arguments are not positional), which you should give to -function `buildStackProject`. This argument is a GHC Nix package in the -version as defined in the snapshot you set in Stack's project-level -configuration file (`stack.yaml`, by default). - -### Pure and impure Nix shells - -By default, Stack will run the build in a *pure* Nix build environment (or -*shell*), which means two important things: - -1. basically **no environment variable will be forwarded** from your user - session to the nix-shell (variables like `HTTP_PROXY` or `PATH` notably will - not be available); and -2. the build should fail if you haven't specified all the dependencies in the - `packages:` section of the Stack YAML configuration file, even if these - dependencies are installed elsewhere on your system. This behaviour enforces - a complete description of the build environment to facilitate - reproducibility. - -To override this behaviour, add the following section to your Stack YAML -configuration file: - -~~~yaml -nix: - enable: true - pure: false -~~~ - -The equivalent command line flag (which will prevail) is `--[no-]-nix-pure`. - -**Note:** On macOS, shells are non-pure by default currently. This is due soon -to be resolved locale issues. So on macOS you'll need to be a bit more careful -to check that you really have listed all dependencies. - -### Nix package sources - -Nix organizes its packages in snapshots of packages (each snapshot being a -"package set") similar to how Stackage organizes Haskell packages. By default, -`nix-shell` will look for the "nixpkgs" package set located by your `NIX_PATH` -environment variable. This package set can be different depending on when you -installed Nix and which nixpkgs channel you're using (similar to the LTS channel -for stable packages and the nightly channel for bleeding edge packages in -[Stackage](https://www.stackage.org/)). This is bad for reproducibility so that -nixpkgs should be pinned, i.e., set to the same package set for every developer -of your project. - -To set or override the Nix package set, add the following section to your Stack -YAML configuration file: - -~~~yaml -nix: - path: [nixpkgs=<path_to_my_own_nixpkgs_clone>] -~~~ - -The equivalent command line option is -`--nix-path <path_to_my_own_nixpkgs_clone>`. - -By this means, you can ask Nix to use your own local checkout of the nixpkgs -repository. You could in this way use a bleeding edge nixpkgs, cloned from the -`NixOS/nixpkgs` [repository](http://www.github.com/NixOS/nixpkgs) `master` -branch, or edit the Nix descriptions of some packages. - -The Tweag example [repository][tweag-example] shows how you can pin a package -set. - -## Non-project specific configuration - -Below is a summary of the non-project specific configuration options and their -default values. The options can be set in Stack's project-level configuration -file (`stack.yaml`, by default) or its global configuration file -(`config.yaml`). - -~~~yaml -nix: - - # false by default, except on NixOS. Is Nix integration enabled? - enable: true - - # true by default. Should Nix run in a pure shell? - pure: true - - # Empty by default. The list of packages you want to be available in the - # nix-shell at build time (with `stack build`) and run time (with - # `stack exec`). - packages: [] - - # Unset by default. You cannot set this option if `packages:` - # is already present and not empty. - shell-file: shell.nix - - # A list of strings, empty by default. Additional options that will be passed - # verbatim to the `nix-shell` command. - nix-shell-options: [] - - # A list of strings, empty by default, such as - # `[nixpkgs=/my/local/nixpkgs/clone]` that will be used to override - # NIX_PATH. - path: [] - - # false by default. Whether to add your Nix dependencies as Nix garbage - # collection roots. This way, calling nix-collect-garbage will not remove - # those packages from the Nix store, saving you some time when running - # stack build again with Nix support activated. - # - # This creates a `nix-gc-symlinks` directory in the project `.stack-work`. - # To revert that, just delete this `nix-gc-symlinks` directory. - add-gc-roots: false -~~~ - -`stack --nix-help` will list the equivalent command line flags and options. - -## Stack and developer tools on NixOS - -NixOS is a Linux distribution based on Nix, that is composed using modules and -packages defined in the Nixpkgs project. - -When using Stack on NixOS, you must use Stack's Nix integration to install GHC. -That is because external C libraries in NixOS are not installed in the usual -distribution directories. GHC installed through Stack (without Nix) can't find -those libraries and, therefore, can't build most projects. However, GHC provided -through Nix can be modified to find the external C libraries provided through -Nix. - -[nix-language]: https://wiki.nixos.org/wiki/Overview_of_the_Nix_Language -[nix-manual-exprs]: http://nixos.org/manual/nix/stable/expressions/writing-nix-expressions.html -[nix-search-packages]: https://search.nixos.org/packages -[nixpkgs-manual-haskell]: https://haskell4nix.readthedocs.io/nixpkgs-users-guide.html?highlight=buildStackProject#how-to-build-a-haskell-project-using-stack -[tweag-blog-post]: https://www.tweag.io/blog/2022-06-02-haskell-stack-nix-shell/ -[tweag-example]: https://github.com/tweag/haskell-stack-nix-example/
− doc/nonstandard_project_init.md
@@ -1,36 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Non-standard project initialization - -You may need to configure Stack to work with an existing project that has one or -more Cabal files but no Stack project-level configuration file (`stack.yaml`, by -default). - -## The `stack init` command - -The `stack init` command: - -* finds all of the Cabal files in your current directory and subdirectories - (unless you use `--ignore-subdirs`) and determines the packages and versions - they require -* Finds the best combination of snapshot and package flags that allows - everything to compile with minimum external dependencies -* Tries to look for the best matching snapshot from latest Haskell LTS, latest - Stackage Nightly, and other Haskell LTS, in that order - -If `stack init` finds a match, it will generate a `stack.yaml` file. - -You can specify the directory, or directories to include in the search for -Cabal files. - -### The `stack init --force` flag - -Set the flag to force the over-writing of any existing `stack.yaml` file. - -### The `stack init --ignore-subdirs` flag - -Set the flag to not search for Cabal files in subdirectories. - -### The `stack init --omit-packages` flag - -Set the flag to exclude any conflicting or incompatible user packages.
doc/other_resources.md view
@@ -4,10 +4,10 @@ There are lots of resources available for learning more about Stack: -* `stack` or `stack --help` — lists Stack's commands, and flags and options - common to those commands -* `stack <command> --help` — provides help on the particular Stack command, - including flags and options specific to the command +* `stack`, `stack --help` (or `-h`) — lists Stack's commands, and flags and + options common to those commands +* `stack <command> --help` (or `-h`) — provides help on the particular Stack + command, including flags and options specific to the command * `stack --version` — identify the version and Git hash of the Stack executable * `--verbose` (or `-v`) — much more info about internal operations (useful for bug reports)
− doc/pantry.md
@@ -1,300 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://rawgit.com/commercialhaskell/stack/master/doc/img/hidden-warning.svg"></a></div> - -# Snapshot and package location - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -This document describes: - -* the specification of a snapshot location (in the - [`snapshot`](yaml_configuration.md#snapshot) or - [`resolver`](yaml_configuration.md#resolver) key) -* the specification of a package location (in the `extra-deps` key and in a - snapshot) - -!!! info - - Stack uses the [Pantry](https://hackage.haskell.org/package/pantry) to - specify the location of snapshots and packages. Pantry is geared towards - reproducible build plans with cryptographically secure specification of - snapshots and packages. - -## Snapshot location - -There are essentially four different ways of specifying a snapshot location: - -1. Via a compiler version, which is a "compiler only" snapshot. This could be, - for example: - - ~~~yaml - snapshot: ghc-8.6.5 - ~~~ - -2. Via a URL pointing to a snapshot configuration file, for example: - - ~~~yaml - snapshot: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2018/8/21.yaml` - ~~~ - -3. Via a local file path pointing to a snapshot configuration file, for - example: - - ~~~yaml - snapshot: my-local-snapshot.yaml - ~~~ - -4. Via a _convenience synonym_, which provides a short form for some common - URLs. These are: - - * GitHub: `github:user/repo:path` is treated as: - - ~~~text - https://raw.githubusercontent.com/user/repo/master/path - ~~~ - - * LTS Haskell: `lts-X.Y` is treated (by default) as: - - ~~~text - github:commercialhaskell/stackage-snapshots:lts/X/Y.yaml - ~~~ - - * Stackage Nightly: `nightly-YYYY-MM-DD` is treated (by default) as: - - ~~~text - github:commercialhaskell/stackage-snapshots:nightly/YYYY/M/D.yaml - ~~~ - -!!! info - - By default, LTS Haskell and Stackage Nightly snapshot configurations are - retrieved from the `stackage-snapshots` GitHub repository of user - `commercialhaskell`. The - [snapshot-location-base](yaml_configuration.md#snapshot-location-base) - option allows a custom location to be set. - -For safer, more reproducible builds, you can optionally specify a URL -together with a cryptographic hash of its content. For example: - -~~~yaml -snapshot: - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/12/0.yaml - size: 499143 - sha256: 781ea577595dff08b9c8794761ba1321020e3e1ec3297fb833fe951cce1bee11 -~~~ - -`size` is the number of bytes in the file and `sha256` is the file's SHA256 -hash. If not provided, the information will automatically be generated and -stored in a [lock file](lock_files.md). - -## Package location - -There are three types of package locations: - -1. Hackage packages -2. Git and Mecurial repositories -3. Local or remote archives (such as GitHub archives) - -All three types support optional tree metadata to be added, which can be used -for reproducibility and faster downloads. This information can automatically be -generated in a [lock file](lock_files.md). - -### Hackage packages - -A package can be identified by its name, version and Cabal file revision -number, with revision `0` being the original Cabal file. For example: - -~~~yaml -extra-deps: -- acme-missiles-0.3@rev:0 -~~~ - -A package name and version only can be stated. Using this syntax, the most -recent Cabal file revision available in the package index will be used. For -example: - -~~~yaml -extra-deps: -- acme-missiles-0.3 -~~~ - -This syntax is often used in practice, but may result in one build differing -from another, if a new or further Cabal file revision is added to the package -index between the builds. - -As an alternative to specifying the Cabal file revision number, you can specify -the package name and version with the SHA256 hash of the contents of its Cabal -file. Doing so is slightly more resilient than using the Cabal file revision -number, as it does not rely on the correct ordering in the package index. -For example: - -~~~yaml -extra-deps: -- acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1 -~~~ - -Optionally, you can specify also the size of the Cabal file in bytes. For -example (where the file size is `631` bytes): - -~~~yaml -extra-deps: -- acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1,631 -~~~ - -Optionally, you can specify also the Pantry tree information. For example: - -~~~yaml -- hackage: acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1,613 - pantry-tree: - size: 226 - sha256: 614bc0cca76937507ea0a5ccc17a504c997ce458d7f2f9e43b15a10c8eaeb033 -~~~ - -A Pantry tree is a list of CAS (content-addressable storage) -'SHA256 hash'-'size in bytes' keys for each of the files in a package. - -The SHA256 hash of the contents of the Cabal file and its size in bytes is -provided in Stack's lock file. For further information, see the -[lock files](lock_files.md) documentation. The SHA256 hash and file size -alternative is also what Stack uses when it makes suggestions about missing -packages. - -### Git and Mercurial repositories - -You can specify a Git or Mercurial repository at a specific commit, and Stack -will clone that repository and, if it has submodules (Git), update the -repository's submodules. For example: - -~~~yaml -extra-deps: -- git: git@github.com:commercialhaskell/stack.git - commit: '6a86ee32e5b869a877151f74064572225e1a0398' -- git: git@github.com:snoyberg/http-client.git - commit: 'a5f4f3' -- hg: https://example.com/hg/repo - commit: 'da39a3ee5e6b4b0d3255bfef95601890afd80709' -~~~ - -!!! note - - It is highly recommended that you only use SHA1 values for a Git or - Mercurial commit. Other values may work, but they are not officially - supported, and may result in unexpected behavior (namely, Stack will not - automatically pull to update to new versions). Another problem with this is - that your build will not be deterministic, because when someone else tries - to build the project they can get a different checkout of the package. - -!!! note - - The `commit:` key expects a YAML string. A commit hash, or partial hash, - comprised only of digits represents a YAML number, unless it is enclosed in - quotation marks. - -!!! warning - - For the contents of a Git repository, Stack cannot handle filepaths or - symbolic link names that are longer than those supported by the `ustar` - (Unix Standard TAR) archive format defined by - [POSIX.1-1988](https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub151-1.pdf). - - Stack uses `git archive` to convert the content of a Git repository to a - TAR archive, which it then seeks to consume. Git produces `pax` format - archives which use 'extended' headers for matters that the `ustar` format - cannot handle. Unfortunately, Stack cannot consume an extended header and - will silently discard the item. - -A common practice in the Haskell world is to use "megarepos", or repositories -with multiple packages in various subdirectories. Some common examples include -[wai](https://github.com/yesodweb/wai/) and -[digestive-functors](https://github.com/jaspervdj/digestive-functors). To -support this, you may also specify `subdirs` for repositories. For example: - -~~~yaml -extra-deps: -- git: git@github.com:yesodweb/wai - commit: '2f8a8e1b771829f4a8a77c0111352ce45a14c30f' - subdirs: - - auto-update - - wai -~~~ - -If unspecified, `subdirs` defaults to `['.']` meaning looking for a package in -the root of the repository. If you specify a value of `subdirs`, then `'.'` is -_not_ included by default and needs to be explicitly specified if a required -package is found in the top-level directory of the repository. - -#### git-annex - -[git-annex](https://git-annex.branchable.com) is not supported. This is because -`git archive` does not handle symbolic links outside the work tree. It is still -possible to use repositories which use git-annex but do not require the annex -files for the package to be built. - -To do so, ensure that any files or directories stored by git-annex are marked -[export-ignore](https://git-scm.com/docs/git-archive#Documentation/git-archive.txt-export-ignore) -in the `.gitattributes` file in the repository. For further information, see -issue [#4579](https://github.com/commercialhaskell/stack/issues/4579). - -For example, if the directory `fonts/` is controlled by git-annex, use the -following line: - -~~~gitattributes -fonts export-ignore -~~~ - -### Local or remote archives (such as GitHub archives) - -#### Filepaths or URLs to archive files - -You can use filepaths referring to local archive files or HTTP or HTTPS URLs -referring to remote archive files, either tarballs or ZIP files. - -!!! note - - An example of a remote archive file is a Hackage package candidate, usually - located at (for example) - https://hackage.haskell.org/package/my-package-1.0.0/candidate/my-package-1.0.0.tar.gz. - -!!! warning - - Stack assumes that these archive files never change after downloading to - avoid needing to make an HTTP request on each build. - -For safer, more reproducible builds, you can optionally specify a cryptographic -hash of the archive file. - -For example: - -~~~yaml -extra-deps: -- https://example.com/foo/bar/baz-0.0.2.tar.gz -- archive: http://github.com/yesodweb/wai/archive/2f8a8e1b771829f4a8a77c0111352ce45a14c30f.zip - subdirs: - - wai - - warp -- archive: ../acme-missiles-0.3.tar.gz - sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b -~~~ - -#### GitHub archive files - -[:octicons-tag-24: 1.7.1](https://github.com/commercialhaskell/stack/releases/tag/v1.7.1) - -You can specify a GitHub respository at a specific commit and Stack will obtain -from GitHub an archive file of the files in the repository at that point in its -history. For example: - -~~~yaml -extra-deps: -- github: snoyberg/http-client - commit: 'a5f4f30f01366738f913968163d856366d7e0342' -~~~ - -!!! note - - An archive file of the files in a GitHub repository at a point in its - history is not the same as a clone of the repository (including its history) - and the updating of any submodules. If you need the latter, use the syntax - for a [Git repository](pantry.md#git-and-mercurial-repositories). - - If the package fails to build due to missing files, it may be that updated - submodules are required.
− doc/path_command.md
@@ -1,49 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack path` command - -~~~text -stack path [--stack-root] [--global-config] [--programs] [--local-bin] - [--project-root] [--config-location] [--bin-path] [--compiler-exe] - [--compiler-bin] [--compiler-tools-bin] [--extra-include-dirs] - [--extra-library-dirs] [--snapshot-pkg-db] [--local-pkg-db] - [--global-pkg-db] [--ghc-package-path] [--snapshot-install-root] - [--local-install-root] [--snapshot-doc-root] [--local-doc-root] - [--local-hoogle-root] [--dist-dir] [--local-hpc-root] -~~~ - -`stack path` provides information about files and locations used by Stack. - -Pass the following flags for information about specific files or locations: - -|Flag |File or location | -|-----------------------|------------------------------------------------------| -|--bin-path |The PATH in the Stack environment. | -|--compiler-bin |The directory containing the GHC executable. | -|--compiler-exe |The GHC executable. | -|--compiler-tools-bin |The directory containing binaries specific to a particular compiler.| -|--config-location |Stack's project-level YAML configuration file (`stack.yaml`, by default).| -|--dist-dir |The dist work directory, relative to the package directory.| -|--extra-include-dirs |Extra include directories. | -|--extra-library-dirs |Extra library directories. | -|--ghc-package-path |The `GHC_PACKAGE_PATH` environment variable. | -|--global-config |Stack's user-specific global YAML configuration file (`config.yaml`).| -|--global-pkg-db |The global package database. | -|--local-bin |The directory in which Stack installs executables. | -|--local-doc-root |The root directory for local project documentation. | -|--local-hoogle-root |The root directory for local project documentation. | -|--local-hpc-root |The root directory for .tix files and HPC reports. | -|--local-install-root |The root directory for local project installation. | -|--local-pkg-db |The local package database. | -|--programs |The root directory for GHC and other Stack-supplied tools.| -|--project-root |The project root directory.| -|--snapshot-doc-root |The root directory for snapshot documentation. | -|--snapshot-install-root|The root directory for snapshot installation. | -|--snapshot-pkg-db |The snapshot package database. | -|--stack-root |The Stack root. | - -The command also accepts flags and options of the -[`stack build`](build_command.md#flags-affecting-ghcs-behaviour) command that -affect the location of the local project installation directory, such as -`--profile` and `--no-strip`. For further information, see the documentation of -the [project Stack work directory](stack_work.md#project-stack-work-directory).
− doc/purge_command.md
@@ -1,10 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack purge` command - -~~~text -stack purge -~~~ - -`stack purge` has the same effect as, and is provided as a shorthand for, -[`stack clean --full`](clean_command.md).
− doc/query_command.md
@@ -1,44 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack query` command - -:octicons-beaker-24: Experimental - -[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) - -~~~text -stack query [SELECTOR...] -~~~ - -`stack query` outputs certain build information. For example, for a -multi-package project `multi` specifying snapshot `lts-19.25` (GHC 9.0.2) and -with two project packages, `my-package-A` (version 0.1.0.0) and `my-package-B` -(version 0.2.0.0), command `stack query` outputs: - -~~~text -compiler: - actual: ghc-9.0.2 - wanted: ghc-9.0.2 -locals: - my-package-A: - path: <absolute_path_to>\multi\my-package-A\ - version: 0.1.0.0 - my-package-B: - path: <absolute_path_to>\multi\my-package-B\ - version: 0.2.0.0 -~~~ - -The component parts of the information can be specified using 'selectors' with -the command. In the example above the selectors include `compiler`, -`compiler actual`, `locals`, `locals my-package-A`, and -`locals my-package-A version`. For example, commanding: - -~~~text -stack query locals my-package-B path -~~~ - -results in output: - -~~~text -<absolute_path_to>\multi\my-package-B\ -~~~
− doc/run_command.md
@@ -1,46 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack run` command - -~~~text -stack run [-- ARGUMENT(S) (e.g. stack run -- file.txt)] - [--[no-]ghc-package-path] [--[no-]stack-exe] - [--package PACKAGE] [--rts-options RTSFLAG] [--cwd DIR] -~~~ - -`stack run` builds a project executable and runs it. If the command has a first -argument and it is recognised as the name of an executable component of a -project package then that is built. Otherwise, the project's first executable is -built. If the project has no executables Stack reports no executables found as -an error. - -!!! note - - To identify a project's first executable, and search for the name of an - executable component, Stack lists the executable components, in order, for - each package, listed in order. For example: - - `packageA:a-exe` < `packageA:b-exe` < `packageB:a-exe` < `packageB:b-exe` - -Everything after `--` on the command line is interpreted as a command line -argument to be passed to what is run, other than a first argument recognised as -the name of an executable component of a project package. - -By default: - -* the `GHC_PACKAGE_PATH` environment variable is set for the subprocess. Pass - the `--no-ghc-package-path` flag to not set the variable; and - -* the `STACK_EXE` environment variable is set with the path to Stack. Pass the - `--no-stack-exe` flag to not set the variable. - -The `--cwd` option can be used to set the working directory before the -executable is run. - -The `--package` option (which can be specified multiple times) can be used to -add a package name to build targets. - -The `--rts-options` option (which can be specified multiple times) can be used -to pass a list of GHC's -[runtime system (RTS) options](https://downloads.haskell.org/~ghc/latest/docs/users_guide/runtime_control.html#) -to the executable when it is run. (The `+RTS` and `-RTS` must not be included.)
− doc/runghc_command.md
@@ -1,22 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack runghc` and `stack runhaskell` commands - -~~~text -stack runghc [-- ARGUMENT(S) (e.g. stack runghc -- X.hs)] - [--[no-]ghc-package-path] [--[no-]stack-exe] [--package PACKAGE] - [--rts-options RTSFLAG] [--cwd DIR] -~~~ - -`stack runhaskell` has the same effect as `stack runghc`. `stack runghc` has the -same effect as, and is provided as a shorthand for, -[`stack exec runghc`](exec_command.md), with the exception of the `--package` -option. - -Pass the option `--package <package(s)>` to add the initial GHC argument -`-package-id=<unit_id>`, where `<unit_id>` is the unit ID of the specified -package in the installed package database. The option can be a list of package -names or package identifiers separated by spaces. The option can also be -specified multiple times. The approach taken to these packages is the same as if -they were specified as targets to -[`stack build`](build_command.md#target-syntax).
− doc/script_command.md
@@ -1,177 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack script` command - -~~~text -stack script [--package PACKAGE] FILE - [-- ARGUMENT(S) (e.g. stack script X.hs -- argument(s) to program)] - [--compile | --optimize] [--[no-]use-root] [--ghc-options OPTIONS] - [--extra-dep PACKAGE-VERSION] [--no-run] -~~~ - -The `stack script` command either runs a specified Haskell source file (using -GHC's `runghc`) or, optionally, compiles such a file (using GHC) and, by -default, runs it. - -Unlike `stack ghc` and `stack runghc`, the command ignores all Stack YAML -configuration files (global and project-level). A snapshot must be specified on -the command line (with the `--snapshot` option). For example: - -~~~text -stack script --snapshot lts-22.21 MyScript.hs -~~~ - -The `stack script` command behaves as if the `--install-ghc` flag had been -passed at the command line. - -Everything after `--` on the command line is interpreted as a command line -argument to be passed to what is run. - -A package can be added to the snapshot on the command line with the -`--extra-dep` option (which can be specified multiple times). - -Each required package can be specified by name on the command line with the -`--package` option (which can be specified multiple times). A single `--package` -option can also refer to a list of package names, separated by a space or comma -character. If the package is not in the snapshot, the most recent version in the -package index (e.g. Hackage) will be obtained. - -If no packages are specified in that way, all the required packages that are in -the snapshot or are a GHC boot package (packages that come with GHC and are -included in GHC's global package database) will be deduced by reference to the -`import` statements in the source file. The `base` package associated with the -version of GHC specified by the snapshot is always available. - -If a required package is a GHC boot package, the behaviour can be complex. If -the boot package has not been 'replaced', then it will be used in Stack's build -plan. However, if the boot package has been 'replaced', the latest version of -that package in the package index will be used in Stack's build plan, which may -differ from the version provided by the version of GHC specified by the -snapshot. A boot package will be treated as 'replaced' if the package i -included directly in the Stackage snapshot or it depends on a package included -directly in the snapshot. Stackage snapshots do not include directly most boot -packages but some snapshots may include directly some boot packages. In -particular, some snapshots include directly `Win32` (which is a boot package on -Windows) while others do not. For example, if `Cabal` (a boot package) is a -required package then, with Stackage snapshot LTS Haskell 20.25, Stack will: - -* on Windows, try to construct a build plan based on the latest version of - `Cabal` in the package index (because that snapshot includes `Win32` directly, - and `Cabal` depends on `Win32` and so is treated as 'replaced'); and -* on non-Windows, use the boot package in the build plan (because `Cabal` is not - 'replaced'). - -Boot packages that have been 'replaced' can be specified as an `--extra-dep`. - -The source file can be compiled by passing either the `--compile` flag (no -optimization) or the `--optimize` flag (compilation with optimization). If the -file is compiled, passing the `--no-run` flag will mean the compiled code is not -run. - -By default, all the compilation outputs (including the executable) are written -to the directory of the source file. Pass the `--use-root` flag to write such -outputs to a script-specific location in the `scripts` directory of the Stack -root. The location reflects the absolute path to the source file, but ignoring -the drive. This can avoid clutter in the source file directory. - -Additional options can be passed to GHC using the `--ghc-options` option. - -## Examples - -For example, Haskell source file `MyScript.hs` at location -`<drive>Users/jane/my-project` (where `<drive>` could be `/` on Unix-like -operating systems or `C:/` or similar on Windows): - -~~~haskell -module Main (main) where - -import Data.List (intercalate) -import System.Environment (getArgs) - -import Acme.Missiles (launchMissiles) - -main :: IO () -main = do - advices <- getArgs - launchMissiles - putStrLn $ intercalate "\n" advices -~~~ - -can be compiled and run, with arguments, with: - -~~~text -stack --snapshot lts-22.21 script --package acme-missiles --compile MyScript.hs -- "Don't panic!" "Duck and cover!" -~~~ - -All the compilation outputs (like `Main.hi`, `Main.o`, and the executable -`MyScript`) will be written to the `my-project` directory. - -If compiled and run with the additional flag `--use-root`, all the compilation -outputs will be written to a directory named `MyScript.hs` at -`Users/jane/my-project/` in the `scripts` directory of the Stack root. - -For example, consider the following script extract, based on snapshot Stackage -LTS Haskell 20.25, where considerations on Windows differ from non-Windows. The -`stack script` command is specified using Stack's -[script interpreter](scripts.md). - -=== "Windows" - - The snapshot includes `Win32` directly. As a consequence, GHC boot packages - `directory`, `process` and `time` (which depend on `Win32`) are all treated - as 'replaced'. - - ~~~haskell - {- stack script - --snapshot lts-20.25 - --extra-dep acme-missiles-0.3 - --extra-dep directory-1.3.6.2 - --extra-dep process-1.6.16.0 - --extra-dep time-1.11.1.1 - -} - - import Acme.Missiles -- from acme-missiles - import Data.Time.Clock.System -- from time - import System.Time.Extra -- from extra - - ... - ~~~ - - `acme-missiles` is not in the snapshot and so needs to be specified as an - extra-dep. - - Stack can deduce that the module imports imply that the required packages - are `acme-missiles`, `time` and `extra` (which is in the snapshot). - - `extra` depends on `directory` and `process`. If `directory` and `process` - are not specified as extra-deps, Stack will complain that they have been - 'pruned'. - - `directory-1.3.6.2` depends on `time < 1.12`. If `time` is not specified as - an extra-dep, Stack will try to construct a build plan based on the latest - version in the package index (which will fail, as the latest version is - `>= 1.12`) - -=== "Unix-like" - - ~~~haskell - {- stack script - --snapshot lts-20.25 - --extra-dep acme-missiles-0.3 - -} - - import Acme.Missiles -- from acme-missiles - import Data.Time.Clock.System -- from time - import System.Time.Extra -- from extra - - ... - ~~~ - - `acme-missiles` is not in the snapshot and so needs to be specified as an - extra-dep. - - Stack can deduce that the module imports imply that the required packages - are `acme-missiles`, `time` and `extra` (which is in the snapshot). - - All the other dependencies required are either GHC boot packages (which have - not been 'replaced') or in the snapshot.
− doc/scripts.md
@@ -1,268 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Stack's script interpreter - -Stack offers a very useful feature for running files: a script interpreter. For -too long have Haskellers felt shackled to bash or Python because it's just too -hard to create reusable source-only Haskell scripts. Stack attempts to solve -that. - -You can use `stack <file_name>` to execute a Haskell source file. Usually, the -Stack command to be applied is specified using a special Haskell comment (the -Stack interpreter options comment) at the start of the source file. That command -is most often `stack script` but it can be, for example, `stack runghc`. If -there is no Stack interpreter options comment, Stack will warn that one was -expected. - -An example will be easiest to understand. Consider the Haskell source file -`turtle-example.hs` with contents: - -~~~haskell -#!/usr/bin/env stack --- stack script --snapshot lts-22.21 --package turtle -{-# LANGUAGE OverloadedStrings #-} -import Turtle (echo) -main = echo "Hello World!" -~~~ - -=== "Unix-like" - - The first line beginning with the 'shebang' (`#!`) tells Unix to use Stack - as a script interpreter, if the file's permissions mark it as executable. A - shebang line is limited to a single argument, here `stack`. - - The file's permissions can be set with command `chmod` and then it can be - run: - - ~~~text - chmod +x turtle-example.hs - ./turtle-example.hs - ~~~ - - !!! note - - On macOS: - - - Avoid `{-# LANGUAGE CPP #-}` in Stack scripts; it breaks the shebang - line ([GHC #6132](https://gitlab.haskell.org/ghc/ghc/issues/6132)) - - - Use a compiled executable, not another script, in the shebang line. - Eg `#!/usr/bin/env runhaskell` will work but - `#!/usr/local/bin/runhaskell` would not. - - Alternatively, the script can be run with command: - - ~~~text - stack turtle-example.hs - ~~~ - -=== "Windows (with PowerShell)" - - The first line beginning with the 'shebang' (`#!`) has a meaning on - Unix-like operating systems but will be ignored by PowerShell. It can be - omitted on Windows. The script can be run with command: - - ~~~text - stack turtle-example.hs - ~~~ - -In both cases, the command yields: - -~~~text -Hello World! -~~~ - -the first time after a little delay (as GHC is downloaded, if necessary, and -dependencies are built) and subsequent times more promptly (as the runs are -able to reuse everything already built). - -The second line of the source code is the Stack interpreter options comment. In -this example, it specifies the `stack script` command with the options of a -LTS Haskell 22.21 snapshot (`--snapshot lts-22.21`) and ensuring the -[`turtle` package](https://hackage.haskell.org/package/turtle) is available -(`--package turtle`). The version of the package will be that in the specified -snapshot (`lts-22.21` provides `turtle-1.6.2`). - -## Arguments and interpreter options and arguments - -Arguments for the script can be specified on the command line after the file -name: `stack <file_name> <arg1> <arg2> ...`. - -The Stack interpreter options comment must specify what would be a single valid -Stack command at the command line if the file name were included as an argument, -starting with `stack`. It can include `--` followed by arguments. In particular, -the Stack command `stack <arg1> MyScript.hs <arg4>` with -Stack interpreter options comment: - -~~~haskell --- stack <arg2> <command> <arg3> -- <arg5> -~~~ - -is equivalent to the following command at the command line: - -~~~text -stack <arg1> <arg2> <command> <arg3> -- MyScript.hs <arg4> <arg5> -~~~ - -The Stack interpreter options comment must be the first line of the file, unless -a shebang line is the first line, when the comment must be the second line. The -comment must start in the first column of the line. - -When many options are needed, a block style comment that splits the command over -more than one line may be more convenient and easier to read. - -For example, the command `stack MyScript.hs arg1 arg2` with `MyScript.hs`: - -~~~haskell -#!/usr/bin/env stack -{- stack script - --snapshot lts-22.21 - -- - +RTS -s -RTS --} -import Data.List (intercalate) -import System.Environment (getArgs) -import Turtle (echo, fromString) - -main = do - args <- getArgs - echo $ fromString $ intercalate ", " args -~~~ - -is equivalent to the following command at the command line: - -~~~text -stack script --snapshot lts-22.21 -- MyScript.hs arg1 arg2 +RTS -s -RTS -~~~ - -where `+RTS -s -RTS` are some of GHC's -[runtime system (RTS) options](https://downloads.haskell.org/~ghc/latest/docs/users_guide/runtime_control.html). - -## Just-in-time compilation - -As with using `stack script` at the command line, you can pass the `--compile` -flag to make Stack compile the script, and then run the compiled executable. -Compilation is done quickly, without optimization. To compile with optimization, -pass the `--optimize` flag instead. Compilation is done only if needed; if the -executable already exists, and is newer than the script, Stack just runs the -executable directly. - -This feature can be good for speed (your script runs faster) and also for -durability (the executable remains runnable even if the script is disturbed, eg -due to changes in your installed GHC/snapshots, changes to source files during -git bisect, etc.) - -## Using multiple packages - -As with using `stack script` at the command line, you can also specify multiple -packages, either with multiple `--package` options, or by providing a comma or -space separated list. For example: - -~~~haskell -#!/usr/bin/env stack -{- stack script - --snapshot lts-22.21 - --package turtle - --package "stm async" - --package http-client,http-conduit --} -~~~ - -## Stack configuration for scripts - -With the `stack script` command, all Stack YAML configuration files (global and -project-level) are ignored. - -With the `stack runghc` command, if the current working directory is inside a -project then that project's Stack project-level YAML configuration is effective -when running the script. Otherwise the script uses the global project -configuration specified in `<Stack root>/global-project/stack.yaml`. - -## Testing scripts - -You can use the flag `--script-no-run-compile` on the command line to enable (it -is disabled by default) the use of the `--no-run` option with `stack script` -(and forcing the `--compile` option). The flag may help test that scripts -compile in CI (continuous integration). - -For example, consider the following simple script, in a file named `Script.hs`, -which makes use of the joke package -[`acme-missiles`](https://hackage.haskell.org/package/acme-missiles): - -~~~haskell -{- stack script - --snapshot lts-22.21 - --package acme-missiles --} -import Acme.Missiles (launchMissiles) - -main :: IO () -main = launchMissiles -~~~ - -The command `stack --script-no-run-compile Script.hs` then behaves as if the -command -`stack script --snapshot lts-22.21 --package acme-missiles --no-run --compile -- Script.hs` -had been given. `Script.hs` is compiled (without optimisation) and the resulting -executable is not run: no missiles are launched in the process! - -## Writing independent and reliable scripts - -The `stack script` command will automatically: - -* Install GHC and libraries, if missing. `stack script` behaves as if the - `--install-ghc` flag had been passed at the command line. -* Require that all packages used be explicitly stated on the command line. - -This ensures that your scripts are _independent_ of any prior deployment -specific configuration, and are _reliable_ by using exactly the same version of -all packages every time it runs so that the script does not break by -accidentally using incompatible package versions. - -In earlier versions of Stack, the `runghc` command was used for scripts and can -still be used in that way. In order to achieve the same effect with the `runghc` -command, you can do the following: - -1. Use the `--install-ghc` option to install the compiler automatically -2. Explicitly specify all packages required by the script using the `--package` - option. Use `-hide-all-packages` GHC option to force explicit specification - of all packages. -3. Use the `--snapshot` Stack option to ensure a specific GHC version and - package set is used. - -It is possible for configuration files to affect `stack runghc`. For that -reason, `stack script` is strongly recommended. For those curious, here is an -example with `runghc`: - -~~~haskell -#!/usr/bin/env stack -{- stack - runghc - --install-ghc - --snapshot lts-22.21 - --package base - --package turtle - -- - -hide-all-packages - -} -~~~ - -The `runghc` command is still very useful, especially when you're working on a -project and want to access the package databases and configurations used by that -project. See the next section for more information on configuration files. - -## Loading scripts in GHCi - -Sometimes you want to load your script in GHCi to play around with your program. -In those cases, you can use `exec ghci` option in the script to achieve -it. Here is an example: - -~~~haskell -#!/usr/bin/env stack -{- stack - exec ghci - --install-ghc - --snapshot lts-22.21 - --package turtle --} -~~~
− doc/sdist_command.md
@@ -1,42 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack sdist` command - -~~~text -stack sdist [DIR] [--pvp-bounds PVP-BOUNDS] [--ignore-check] - [--[no-]test-tarball] [--tar-dir ARG] -~~~ - -Hackage only accepts packages for uploading in a standard form, a compressed -archive ('tarball') in the format produced by Cabal's `sdist` action. - -`stack sdist` generates a file for your package, in the format accepted by -Hackage for uploads. The command will report the location of the generated file. - -## `--ignore-check` flag - -Pass the flag to disable checks of the package for common mistakes. By default, -the command will check the package for common mistakes. - -## `--pvp-bounds` option - -The `--pvp-bounds <pvp_bounds_mode>` option determines whether and, if so, how -PVP version bounds should be added to the Cabal file of the package. The -available modes for basic use are: `none`, `lower`, `upper`, and `both`. The -available modes for use with Cabal file revisions are `lower-revision`, -`upper-revision` and `both-revision`. - -For futher information, see the -[YAML configuration](yaml_configuration.md#pvp-bounds) documentation. - -## `--tar-dir` option - -The `--tar-dir <path_to_directory>` option determines whether the package -archive should be copied to the specified directory. - -## `--[no-]test-tarball` flag - -Default: Disabled - -Set the flag to cause Stack to test the resulting package archive, by attempting -to build it.
− doc/setup_command.md
@@ -1,85 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack setup` command - -~~~text -stack setup [GHC_VERSION] [--[no-]reinstall] [--ghc-bindist URL] - [--ghcjs-boot-options GHCJS_BOOT] [--[no-]ghcjs-boot-clean] -~~~ - -`stack setup` attempts to install a version of GHC. - -By default: - -* the version of GHC is the one required by the project. Specify the version of - GHC as an argument to attempt to install a different version of GHC. For - example `stack setup 9.4.4` will attempt to install GHC 9.4.4; and - -* an attempt to install is made only if the version of GHC is not already - available to Stack. Pass the flag `--reinstall` (disabled by default) to - attempt to install the version of GHC regardless of whether it is already - available to Stack. - -Pass the option `--ghc-bindist <url>` to specify the URL of the GHC to be -downloaded and installed. This option requires the use of the `--ghc-variant` -option specifying a custom GHC variant. For further information about the -`--ghc-variant` option, see the see the -[YAML configuration](yaml_configuration.md#ghc-variant) documentation. - -If Stack is configured not to install GHC (`install-ghc: false` or passing the -`--no-install-ghc` flag) then `stack setup` will warn that the flag and the -command are inconsistent and take no action. - -=== "Linux" - - A particular binary distribution of GHC will depend on certain libraries, - which need to be available. - - There are many different Linux distributions and different versions of a - particular Linux distribution. One Linux distribution/version may make - available different libraries to another Linux distribution/version. - - In attempting to identify the particular binary distribution of GHC that is - required on Linux, Stack will refer to the presence or absence of certain - libraries or the versions of those libraries. - - For example, Stack 2.15.1 considers: - - * If `libc.musl-x86_64.so.1` is present. This file is provided by the - [musl libc](https://musl.libc.org/). - - * The version of `libc6` (if musl libc is not applicable), the - [GNU C Library](https://www.gnu.org/software/libc/) (glibc), that is - present. The GNU C Library is designed to be backwards compatible. - - * If `libgmp.so.3` or `libgmp.so.10` is present. These files are provided - by different versions of the - [GNU Multiple Precision Arithmetic Library](https://gmplib.org/). - - * If `libncursesw.so.6` is present. This file is provided by a shared - library for terminal handling with wide character support. - - * If `libtinfo.so.5` or `libtinfo.so.6` is present. These files are - provided by different versions of a shared low-level terminfo library - for terminal handling. - - Stack 2.15.1 uses `ghc-build`: - - * `musl` to indicate `libc.musl-x86_64.so.1` is present and Stack should use - the GHC binary distribution for Alpine Linux. - * `tinfo6` to indicate `libgmp.so.10` and `libtinfo.so.6` are present and - `libc6` is compatible with `libc6` 2.32. - * `tinfo6-libc6-pre232` to indicate `libgmp.so.10` and `libtinfo.so.6` are - present and `libc6` is not compatible with `libc6` 2.32. - * `ncurses6` to indicate `libgmp.so.10` and `libncursesw.so.6` are present - * `gmp4` to indicate `libgmp.so.3` is present - - By default, Stack associates: - - * the `tinfo6` build with the 'Fedora 33' binary distribution of GHC 9.4.1 - to 9.4.4. Those binary distributions require versions of `libc6` that are - compatible with `libc6` 2.32; and - - * the `tinfo6-libc6-pre232` build with the 'Debian 10' binary distribution - of GHC 9.4.1 to 9.4.4. Those binary distributions require versions of - `libc6` that are compatible with `libc6` 2.28.
− doc/shell_autocompletion.md
@@ -1,70 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Shell auto-completion - -The following adds support for the tab completion of standard Stack arguments to -the following shell programs: Bash, Zsh (the Z shell) and fish. Completion of -file names and executables within Stack is still lacking. For further -information, see issue -[#823](https://github.com/commercialhaskell/stack/issues/832). - -!!! info - - Stack's completion library provides - [hidden options](https://github.com/pcapriotti/optparse-applicative#bash-zsh-and-fish-completions) - for Bash, Zsh, and fish which output commands used for shell - auto-completion. For example: - - ~~~bash - $ stack --bash-completion-script stack - _stack() - { - local CMDLINE - local IFS=$'\n' - CMDLINE=(--bash-completion-index $COMP_CWORD) - - for arg in ${COMP_WORDS[@]}; do - CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg) - done - - COMPREPLY=( $(stack "${CMDLINE[@]}") ) - } - - complete -o filenames -F _stack stack - ~~~ - -=== "Bash" - - Add the output of the following command to your preferred completions file - (e.g. `~/.config/bash_completions.d/stack`). - - ~~~bash - stack --bash-completion-script $(which stack) - ~~~ - - You may need to `source` this. - -=== "Zsh" - - Add the output of the following command to your preferred completions file - (e.g. `~/.config/zsh/completions/_stack`). - - ~~~zsh - stack --zsh-completion-script $(which stack) - ~~~ - - You won't need to `source` this, but do update your `fpath`: - - ~~~zsh - fpath=($HOME/.config/zsh/completions $fpath) - autoload -U compinit && compinit - ~~~ - -=== "fish" - - Add the output of the following command to your preferred completions file - (e.g. `~/.config/fish/completions/stack.fish`). - - ~~~fish - stack --fish-completion-script $(which stack) - ~~~
− doc/stack_root.md
@@ -1,260 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Stack root - -The Stack root is a directory where Stack stores important files. - -On Unix-like operating systems and Windows, Stack can be configured to follow -the XDG Base Directory Specification if the environment variable `STACK_XDG` is -set to any non-empty value. However, Stack will ignore that configuration if the -Stack root location has been set on the command line or the `STACK_ROOT` -environment variable exists. - -## Location - -The location of the Stack root depends on the operating system, whether Stack is -configured to use the XDG Base Directory Specification, and/or whether an -alternative location to Stack's default 'programs' directory has been specified. - -The location of the Stack root can be configured by setting the -[`STACK_ROOT`](environment_variables.md#stack_root) environment variable or -using Stack's [`--stack-root`](global_flags.md#stack-root-option) option on the -command line. - -=== "Unix-like" - - The Stack root contains snapshot packages; (by default) tools such as GHC, - in a `programs` directory; Stack's global - [YAML configuration](yaml_configuration.md#yaml-configuration) file - (`config.yaml`); and Stack's - [`global-projects`](yaml_configuration.md#yaml-configuration) directory. - - The default Stack root is `~/.stack`. - -=== "Windows" - - The default Stack root is `%APPDIR%\stack`. - - If the `LOCALAPPDATA` environment variable exists, the default location of - tools is `%LOCALAPPDATA%\Programs\stack`. Otherwise, it is the `programs` - directory in the Stack root. - - !!! warning - - If there is a space character in the `%LOCALAPPDATA%` path (which may be - the case if the relevant user account name and its corresponding user - profile path have a space) this may cause problems with building - packages that make use of the GNU project's `autoconf` package and - `configure` shell script files. That may be the case particularly if - there is no corresponding short name ('8 dot 3' name) for the directory - in the path with the space (which may be the case if '8 dot 3' names - have been stripped or their creation not enabled by default). If there - are problems building, it will be necessary to override the default - location of Stack's 'programs' directory to specify an alternative path - that does not contain space characters. Examples of packages on - Hackage that make use of `configure` are `network` and `process`. - - On Windows, the length of filepaths may be limited (to - [MAX_PATH](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd)), - and things can break when this limit is exceeded. Setting a Stack root with - a short path to its location (for example, `C:\sr`) can help. - -=== "XDG Base Directory Specification" - - The Stack root is `<XDG_DATA_HOME>/stack`. If the `XDG_DATA_HOME` - environment variable does not exist, the default is `~/.local/share/stack` - on Unix-like operating systems and `%APPDIR%\stack` on Windows. - - The location of `config.yaml` is `<XDG_CONFIG_HOME>/stack`. If the - `XDG_CONFIG_HOME` environment variable does not exist, the default is - `~/.config/stack` on Unix-like operating systems and `%APPDIR%\stack` on - Windows. - - This approach treats: - - * the project-level YAML configuration file that is common to all projects - without another such file in their project directory or its ancestor - directories as _data_ rather than as part of Stack's own - _configuration_; - - * the snapshots database as essential data rather than as non-essential - data that would be part of a _cache_, notwithstanding that Stack will - rebuild that database as its contents are needed; and - - * the Pantry store as essential data rather than as non-essential data - that would be part of a _cache_, notwithstanding that Stack will - download the package index and rebuild the store if it is absent. - -An alternative to the default location of tools such as GHC can be specified -with the [`local-programs-path`](yaml_configuration.md#local-programs-path) -configuration option. - -The location of the Stack root is reported by command: - -~~~text -stack path --stack-root -~~~ - -The full path of Stack's global YAML configuration file is reported by command: - -~~~text -stack path --global-config -~~~ - -The location of tools such as GHC for the current platform is reported by -command: - -~~~text -stack path --programs -~~~ - -## Contents - -The contents of the Stack root depend on the operating system, whether Stack is -configured to use the XDG Base Directory Specification, and/or whether an -alternative location to Stack's default 'programs' directory has been specified. - -=== "Unix-like" - - The Stack root contains snapshot packages; (by default) tools such as GHC, - in a `programs` directory; Stack's global - [YAML configuration](yaml_configuration.md#yaml-configuration) file - (`config.yaml`); and Stack's - [`global-projects`](yaml_configuration.md#yaml-configuration) directory. - -=== "Windows" - - The Stack root contains snapshot packages; Stack's global - [YAML configuration](yaml_configuration.md#yaml-configuration) file - (`config.yaml`); and Stack's - [`global-projects`](yaml_configuration.md#yaml-configuration) directory. The - default location of tools such as GHC and MSYS2 is outside of the Stack - root. - -=== "XDG Base Directory Specification" - - If Stack is following the XDG Base Directory Specification, the Stack root - contains what it would otherwise contain for the operating system, but - Stack's global YAML configuration file (`config.yaml`) may be located - elsewhere. - -### `config.yaml` - -This is Stack's global configuration file. For further information, see the -documentation for non-project specific -[configuration](yaml_configuration.md#non-project-specific-configuration). - -If the file is deleted, and Stack needs to consult it, Stack will create a file -with default contents. - -### `stack.sqlite3` - -This is a 'user' database that Stack uses to cache certain information. The -associated lock file is `stack.sqlite3.pantry-write-lock`. - -### `global-project` directory - -This contains: - -* an explanation of the directory (`README.txt`); -* the project-level configuration file (`stack.yaml`) for the global project - and its associated lock file (`stack.yaml.lock`); and -* if created, Stack's working directory (`.stack-work`) for the global project. - -If the project-level configuration file is deleted, and Stack needs to consult -it, Stack will recreate the contents of the directory. - -### `pantry\hackage` directory - -This contains a local cache of the package index. If the contents of the -directory are deleted, and Stack needs to consult the package index, Stack will -seek to download the latest package index. - -!!! info - - Stack depends on package `pantry` which, in turn, depends on package - `hackage-security`. The latter handles the local cache of the package index. - The type `CacheLayout` represents the location of the files that are cached. - `pantry` uses `cabalCacheLayout :: CacheLayout`, the layout that Cabal (the - tool) uses. That is what specifies the names of the files used to cache the - package index, including `00-index.tar` and `00-index.tar.gz`. - -### `pantry` directory - -This contains: - -* the Pantry database used by Stack (`pantry.sqlite3`) and its associated lock - file (`pantry.sqlite2.pantry-write-lock`). If the database is deleted, and - Stack needs to consult it, Stack will seek to create and initialise it. The - database is initialised with information from the package index; and -* a database of package versions that come with each version of GHC - (`global-hints-cache.yaml`). - -### `programs` directory - -This contains a directory for the platform. That directory contains for each -installed Stack-supplied tool: - -* the archive file for the tool. This can be deleted; -* a file indicating the tool is installed (`<tool_name>.installed`); and -* a directory for the tool. - -To remove a Stack-supplied tool, delete all of the above. If Stack needs a -Stack-supplied tool and it is unavailable, Stack will seek to obtain it. - -### `setup-exe-cache` directory - -This contains a directory for the platform. That directory contains, for each -version of GHC (an associated version of Cabal (the library)) that Stack has -used, an executable that Stack uses to access Cabal (the library). - -If the contents of the directory are deleted, and Stack needs the executable, -Stack will seek to rebuild it. - -### `setup-exe-src` directory - -See the documentation for the -[`setup-exe-cache` directory](#setup-exe-cache-directorysetup-exe-cache). This -contains the two source files (`setup-<hash>.hs` and `setup-shim-<hash>.hs`) -that Stack uses to build the executable. - -If the contents of the directory are deleted, and Stack needs the executable, -Stack will recreate them. - -The hash in the names of the source files is a hash of arguments passed to GHC -when building the executable and the contents of the two source files. - -The content of the `setup-<hash>.hs` file is the familiar: - -~~~haskell -import Distribution.Simple -main = defaultMain -~~~ - -The content of the `setup-shim-<hash>.hs` file uses `main` except when the -executable is called with arguments `repl` and `stack-initial-build-steps`. Then -Stack uses Cabal (the library) to create the autogenerated files for every -configured component. Stack's `stack ghci` or `stack repl` commands call the -executable with those arguments. - -### `snapshots` directory - -This contains a directory for each snapshot that Stack creates when building -immutable dependencies of projects. - -If the contents of the directory are deleted, and the snapshot is not available -to Stack when it builds, Stack will recreate the snapshot. - -### `templates` directory - -This contains a `.hsfile` for each project template that Stack has used. For -further information, see the [`stack templates`](templates_command.md) command -documentation. - -If the contents of the directory are deleted, an Stack needs a project template, -Stack will seek to download the template. - -### `upload` directory - -This may contain saved credentials for uploading packages to Hackage -(`credentials.json`).
− doc/stack_work.md
@@ -1,144 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Stack work directories - -Stack work directories are directories within a local project or package -directory in which Stack stores files created during the build process. Stack -can be used without an understanding of the content of those directories. In -particular, the [`stack exec`](exec_command.md) command sets up an environment -where relevant subdirectories of the project Stack work directory are on the -PATH. - -## Naming - -By default, Stack work directories are named `.stack-work`. The name can be -overidden by: - -* the use of the - [`STACK_WORK` environment variable](environment_variables.md#stack_work); -* the [`work-dir`](yaml_configuration.md#work-dir) non-project specific - configuration option; or -* the [`--work-dir`](global_flags.md#-work-dir-option) command line option. - -Given the location of Stack work directories, the name of the work directories -must be a relative path to a directory. - -## Location - -If the work directory does not already exist, it will be created by the -[`stack build`](build_command.md) command as a subdirectory of each project -package directory and, if different, the project directory. - -## Project package Stack work directory - -The Stack work directory for a project package will contain a `dist` directory. -This directory will contain a path to a directory containing: - -* a `build` directory; -* a `package.conf.inplace` directory; -* a `stack-build-caches` directory; -* a `build-lock` file; -* a `setup-config` file; -* a `stack-cabal-mod` file. This file is used by Stack only for its modification - time; -* a `stack-project-root` file. This file contains an absolute path to the - project root directory; and -* a `stack-setup-config-mod` file. This file is used by Stack only for its - modification time. - -The directory, relative to the project package directory or the project -directory, is the one reported by [`stack path --dist-dir`](path_command.md). - -=== "Unix-like" - - On Unix-like operating systems, the path to the directory is a directory - named after the platform (including Stack's classification of variants of - Linux distributions) followed by a directory named after the GHC version. - -=== "Windows" - - On Windows, the path to the directory is an eight-character hash of the - path that applies on Unix-like operating systems. - -## Project Stack work directory - -The Stack work directory for a project will contain a `install` directory. -This directory will contain a path to a directory containing: - -* a `bin` directory, containing built executable files; -* a `doc` directory, containing a directory for each project package. This is - the directory reported by [`stack path --local-doc-root`](path_command.md); -* if the [`stack hpc`](hpc_command.md) command is used, a `hpc` directory. This - is the directory reported by [`stack path --local-hpc-root`](path_command.md); -* a `lib` directory, containing a directory named after the platform and the - GHC version and, within that, a directory for each project package; -* a `pkgdb` directory. This is the directory reported by - [`stack path --local-pkg-db`](path_command.md); -* a `stack.sqlite3` file; and -* a `stack.sqlite3.pantry-write-lock` file. - -The directory is the one reported by -[`stack path --local-install-root`](path_command.md). - -=== "Unix-like" - - On Unix-like operating systems, the path to the directory is a directory - named after the platform (including Stack's classification of variants of - Linux distributions) followed by a directory named after a SHA 256 hash - (see further below) followed by a directory named after the version number - of GHC. - - The SHA 256 hash is a hash of the following information: - - * the path to the specified compiler; - * the information about the compiler provided by `ghc --info`; - * the options that Stack passes to GHC for package that is not a project - package; and - * information about the immutable dependencies: their location, whether or - not Haddock documentation is to be built, their flags, their GHC options, - and their Cabal configuration options. - - The options that Stack passes to GHC for a package that is not a project - package depend on: - - * the specification of - [profiling](https://docs.haskellstack.org/en/stable/build_command/#flags-affecting-ghcs-behaviour); - * the specification of - [stripping](https://docs.haskellstack.org/en/stable/build_command/#flags-affecting-ghcs-behaviour); and - * if - [`apply-ghc-options: everything`](yaml_configuration.md#apply-ghc-options) - is specified, any GHC command line options specified on the command line. - - !!! note - - As a consequence, the path reported by the following commands will - differ (and similarly for the paths established by the - [`stack exec`](exec_command.md) command): - - ~~~text - stack path --local-install-root - stack --profile path --local-install-root - stack --no-strip path --local-install-root - stack --profile --no-strip path --local-install-root - ~~~ - -=== "Windows" - - On Windows, the path to the directory is an eight-character hash of the - path that applies on Unix-like operating systems. - -Following a `stack ghci` or `stack repl` command, the Stack work directory for -a project will contain a `ghci` directory. This directory will contain paths to -`cabal_macos.h` files that are generated automatically by Cabal. - -!!! note - - Haskell Language Server makes use of the `stack ghci` command to obtain - information. - -If the [`stack hoogle`](hoogle_command.md) command is used, the Stack work -directory for a project will contain a `hoogle` directory. This directory will -contain a directory being the one reported by -[`stack path --local-hoogle-root`](path_command.md). The naming of the path to -the directory is same as for the path to the directory in the `install` -directory.
− doc/stack_yaml_vs_cabal_package_file.md
@@ -1,162 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# stack.yaml versus package.yaml versus a Cabal file - -What is the difference between a `stack.yaml` file, a `package.yaml` file and a -Cabal file (named `<package_name>.cabal`)? This page aims to make that clear. - -In short: - -* `stack.yaml` contains project-level configuration for Stack, and may contain - project-specific options and non-project-specific options. - -* `package.yaml` contains a description of a package in the - [Hpack](https://github.com/sol/hpack) format. Hpack, including Stack's - built-in version, uses the file to create a Cabal file. - -* a Cabal file also contains a description of a package, but in the format used - by Cabal. - -## package.yaml versus a Cabal file - -Why two different formats to describe packages? Hpack is considered to have some -advantages over the underlying Cabal format, which are explained its project -repository. They include that the Hpack format supports YAML syntax and the -automatic generation of the lists of `exposed-modules` used in the Cabal format. - -The remainder of this page will focus on the difference between a `stack.yaml` -file and a package description file. - -## Package versus project - -Stack is a build tool and it uses Cabal, a build system. Cabal defines the -concept of a _package_. A package has: - -* A name and version -* optionally, one library -* optionally, one or more executables -* A Cabal file (or, as mentioned above, an [Hpack](https://github.com/sol/hpack) - `package.yaml` file that generates a Cabal file) -* And a bunch more - -There is a one-to-one correspondence between a package and a Cabal file. - -Stack defines a new concept called a _project_. A project has: - -* A snapshot _resolver_ (more on this later) -* Extra dependencies on top of the snapshot -* Optionally, one or more local Cabal packages -* Flag and GHC options configurations -* And a bunch more Stack configuration - -Often you will have a project that defines only one local Cabal package that you -are working on. If you need to specify a dependency, a source of confusion can -be why you need to specify it both in the `stack.yaml` file _and_ -in the Cabal file. To explain, let's take a quick detour to talk about snapshots -and how Stack resolves dependencies. - -## Snapshots and resolvers - -Stack follows a rule that says, for any project, there is precisely one version -of each package available. Obviously, for many packages there are _many_ -versions available in the world. But when resolving a `stack.yaml` file, Stack -requires that you have chosen a specific version for each package available. - -The most common means by which this set of packages is defined is via a -snapshot provided by Stackage. For example, if you go to the page -<https://www.stackage.org/lts-22.21>, you will see a list of 3,342 packages at -specific version numbers. When you then specify `snapshot: lts-22.21` or, -alternatively, `resolver: lts-22.21`, you're telling Stack to use those package -versions in resolving dependencies down to specific versions of packages. - -Sometimes a snapshot doesn't have all of the packages that you want. Or you want -a different version of a package. Or you want to work on a local modification of -a package. In all of those cases, you can add more configuration data to your -`stack.yaml` file to override the values it received from your -[`snapshot`](yaml_configuration.md#snapshot) or -[`resolver`](yaml_configuration.md#resolver) setting. At the end of the day, -each of your projects will end up with some way of resolving a package name into -a specific version of that package. - -## Why specify dependencies twice? - -The package `acme-missiles` is not included in any Stackage snapshots. When you -add something like this to your `stack.yaml` file: - -~~~yaml -extra-deps: -- acme-missiles-0.3 -~~~ - -what you're saying to Stack is: "if at any point you find that you need to build -the `acme-missiles` package, please use version `0.3`". You are _not_ saying -"please build `acme-missiles` now." You are also not saying "my package depends -on `acme-missiles`." You are simply making it available should the need arise. - -When you add to your `package.yaml` file: - -~~~yaml -dependencies: -- acme-missiles -~~~ - -or, alternatively, you add directly to your Cabal file: - -~~~yaml -build-depends: acme-missiles -~~~ - -you're saying "this package requires that `acme-missiles` be available." Since -`acme-missiles` doesn't appear in your snapshot, without also modifying your -`stack.yaml` to mention it via `extra-deps`, Stack will complain about the -dependency being unavailable. - -You may challenge: but why go through all of that annoyance? Stack knows what -package I want, why not just go grab it? The answer is that, if Stack just -grabbed `acme-missiles` for you without it being specified in the `stack.yaml` -somehow, you'd lose reproducibility. How would Stack know which version to use? -It may elect to use the newest version, but if a new version is available in -the future, will it automatically switch to that? - -Stack's core philosophy is that build plans are always reproducible. The -purpose of the `stack.yaml` file is to define an immutable set of packages. No -matter when in time you use it, and no matter how many new release happen in -the interim, the build plan generated should be the same. - -(There is, however, at least one hole in this theory today, which is Hackage -revisions. When you specify `extra-deps: [acme-missiles-0.3]`, it doesn't -specify which revision of the Cabal file to use, and Stack will just choose the -latest. Stack has the ability to specify exact revisions of Cabal files, but -this isn't enforced as a requirement, because it is so different from the way -most people work with packages.) - -And now, how about the other side: why doesn't Stack automatically add -`acme-missiles` to `build-depends` in your Cabal file if you add it as an -extra-dep? There are a surprising number reasons for this: - -* The Cabal specification doesn't support anything like that -* There can be multiple packages in a project, and how do we know which package - actually needs the dependency? -* There can be multiple components (libraries, executable, etc) in a package, - and how do we know which of those actually needs the dependency? -* The dependency may only be conditionally needed, based on flags, operating - system, or architecture. As an extreme example, we wouldn't want a Linux-only - package to be built by force on Windows. - -While for simple use cases it seems like automatically adding dependencies from -the Cabal file to the `stack.yaml` file or vice-versa would be a good thing, it -breaks down immediately for any semi-difficult case. Therefore, Stack requires -you to add it to both places. - -And a final note, in case it wasn't clear. The example above used -`acme-missiles`, which is not in Stackage snapshots. If, however, you want to -depend on a package already present in the snapshot you've selected, there's no -need to add it explicitly to your `stack.yaml` file: it's already there -implicitly via the `snapshot` setting. This is what you do the majority of the -time, such as when you add `vector` or `mtl` as a `build-depends` value. - -## Should I check-in automatically generated Cabal files? - -Yes, you should. This recommendation was changed in -[issue #5210](https://github.com/commercialhaskell/stack/issues/5210). Please -see the discussion there.
− doc/templates_command.md
@@ -1,34 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack templates` command - -~~~text -stack templates -~~~ - -`stack templates` provides information to the standard output stream about -project templates used with the [`stack new` command](new_command.md). - -Project templates are specified in `.hsfiles` files. The format of those files -is documented at the -[`commercialhaskell/stack-templates`](https://github.com/commercialhaskell/stack-templates#project-template-format) -repository on GitHub. - -Any GitHub, GitLab or Bitbucket repository named `stack-templates` can provide -project template files. For example, a template file -`username/stack-templates/my-template.hsfiles` on GitHub can be identified as -`username/my-template` when using `stack new`. The relevant service can be -specified by a prefix: `github:` for [GitHub](https://github.com/) (the default -service), `gitlab:` for [GitLab](https://gitlab.com), or `bitbucket:` for -[Bitbucket](https://bitbucket.com). - -[`commercialhaskell/stack-templates`](https://github.com/commercialhaskell/stack-templates#project-template-format) -on GitHub is the default repository for project templates. Its username -(`commercialhaskell`) does not need to be specified when using `stack new`. - -The project template that `stack new` uses by default is named `new-template` -and provided at the default repository. - -The default repository provides 24 other project templates. Its Wiki provides -a description of some of those templates and information about the location of -other templates.
+ doc/topics/CI.md view
@@ -0,0 +1,17 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Continuous integration (CI) + +## GitHub Actions + +The Stack repository uses GitHub Actions for its own CI. For further +information, see the guide to +[contributing](../CONTRIBUTING.md#continuous-integration-ci). + +## Azure + +For further information, see the [Azure CI](azure_ci.md) documentation. + +## Travis + +For further information, see the [Travis CI](travis_ci.md) documentation.
+ doc/topics/Stack_and_VS_Code.md view
@@ -0,0 +1,133 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Stack and Visual Studio Code + +[Visual Studio Code](https://code.visualstudio.com/) (VS Code) is a popular +source code editor, and +['Haskell'](https://marketplace.visualstudio.com/items?itemName=haskell.haskell) +is an extension for VS Code that is popular with Haskell coders. + +The 'Haskell' extension can be used with Stack but there are some things to be +aware of, set out below. + +## Haskell Language Server + +The VS Code extension makes use of the Haskell Language Server (HLS). To work, +HLS has to be built with the same version of GHC that it will support. That is, +a version of HLS is required for each version of GHC in use. It is possible that +the most recent versions of GHC are not supported by HLS. + +By default, the VS Code extension uses tools that are in the PATH. However, the +extension's settings (under 'Haskell: Manage HLS') allow a user to specify +that the extension should use a separate application, +[GHCup](https://www.haskell.org/ghcup/), to download and install the versions of +HLS that it needs. GHCup can download and install things other than HLS, +including GHC, MSYS2 (on Windows), Cabal (a tool for building Haskell code), and +Stack itself. GHCup can also update itself. On Windows, GHCup has the capability +of using the Stack-supplied MSYS2 rather than installing a duplicate copy. Cabal +(the tool), like Stack, depends on the Cabal (the library). Cabal (the tool), +unlike Stack, does not have the capability to automatically install necessary +versions of GHC, and (as well as supporting the extension) GHCup fills a +important gap for users of the Cabal tool. + +If the VS Code extension is set not to use GHCup, its user needs to ensure that +each version of HLS that the extension needs is on the PATH. + +For the most part, the versions of HLS provided by GHCup are built with the same +versions of GHC that Stack downloads from its default `setup-info` dictionary +(see the [`setup-info`](../configure/yaml/non-project.md#setup-info) non-project +specific configuration option documentation). Stack's default is to mirror the +'official' binary distributions published by GHC. However, in some cases, it is +possible that a GHCup-supplied and GHCup-selected HLS has been built with a +different binary distribution of GHC than the one which Stack has installed. + +One example of that occurred with the release of GHC 9.0.2. For some Linux users +(Debian 9 and Fedora 27), the version of GHC 9.0.2 linked on GHC’s download +[web page](https://www.haskell.org/ghc/download_ghc_9_0_2.html) was broken. The +GHC developers made alternative ‘9.0.2a’ versions available. For a while, Stack +referred to the versions published by GHC on its download web page while the +GHCup-supplied versions of HLS were built using alternative versions. This +incompatibility led to problems. It was resolved by Stack's default also being +changed to refer to the '9.0.2a' versions. (Where Stack has already installed +GHC 9.0.2, it is necessary to delete GHC 9.0.2 from the `stack path --programs` +directory. This will cause Stack to reinstall the alternative version, when it +first needs GHC 9.0.2. Stack should distinguish what it builds with the +alternative from what it has built, and cached, with the original GHC 9.0.2.) + +### GHCup and Stack >= 2.9.1 + +From Stack 2.9.1, GHCup can configure Stack so that if Stack needs a version of +GHC, GHCup takes over obtaining and installing that version. By default, the +script to install GHCup (which can be run more than once) configures Stack in +that way. For further information about how GHCup configures Stack, see the GHC +installation customisation +[documentation](../configure/customisation_scripts.md#ghc-installation-customisation). + +### Workaround #1 + +If GHCup does not configure Stack in the way described above, one workaround is +to allow GHCup to install versions of GHC on the PATH and to cause Stack to use +those versions of GHC, by making use of Stack's `install-ghc` option (which +needs to be disabled) and Stack's `system-ghc` option (which needs to be +enabled). For further information about these options, see the +[`install-ghc`](../configure/yaml/non-project.md#install-ghc) documentation and +the [`system-ghc`](../configure/yaml/non-project.md#system-ghc) documentation. + +For this workaround to work, each time that a snapshot is used that references a +different version of GHC, then GHCup must be used to install it (if GHCup has +not already installed that version). For example, to use `snapshot: lts-22.28` +(GHC 9.6.6), the command `ghcup install ghc 9.6.6` must have been used to +install GHC 9.6.6. That may be a minor inconvenience for some people, as one the +primary benefits of Stack over other tools for building Haskell code has been +that Stack automatically ensures that the necessary version of GHC is available. + +### Workaround #2 + +If GHCup does not configure Stack, another partial workaround is to install +GHCup so that it is 'empty' except for the current version of HLS, allow the +VS Code extension to use GHCup to manage HLS requirements only, and to ignore +any messages (if any) from the extension on start-up that installation of GHC, +Cabal (the tool) and/or Stack are also necessary (they are not, if only Stack is +being used). + +For this workaround to work, however, there can be no differences between the +version of GHC that the GHCup-supplied HLS was built with and the version that +Stack has installed. A slight inconvenience here is also the possibility of +false messages from the start-up that need to be ignored. In principle, those +messages can be disabled by +[setting the following](https://github.com/haskell/vscode-haskell#setting-a-specific-toolchain) +for the VS Code extension: + +~~~yaml +"haskell.toolchain": { + "ghc": null, + "cabal": null, + "stack": null +} +~~~ + +To install a version of GHCup that is 'empty' is a little more complicated than +a default installation of GHCup. + +On Unix-like operating systems, the following environment variable must be set +before GHCup's installation `sh` script is run: `BOOTSTRAP_HASKELL_MINIMAL`. + +On Windows, the second argument to the PowerShell script must be set to +`$false`, namely: + + Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true,$false + +### Cradle + +HLS may need a 'cradle' - an +[`hie.yaml` file](https://hackage.haskell.org/package/hie-bios#stack) - in the +project's root directory in order to work well. + +The [`gen-hie` tool](https://hackage.haskell.org/package/implicit-hie) can help +generate such a cradle. + +### Tips + +It has been suggested that a project must have been successfully built before +the VS code extension (and HLS) is first activated on the project, for HLS to +work reliably.
+ doc/topics/azure_ci.md view
@@ -0,0 +1,174 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Azure CI + +This page documents how to use Stack on [Azure CI](http://dev.azure.com/). + +## Quick Start + +Note that you have to create [azure pipelines](#creating-azure-pipelines) for +your project and then you need to put the relevant configuration files: + +* For simple Azure configuration, copy-paste the + [azure-simple](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-simple.yml) + file into `azure-pipelines.yml`. +* For complex Azure configuration, you need to take the below linked four files + and put all of them into the `.azure` directory. + +For a more detailed explanation, you can read further. + +## Simple and Complex configuration + +We provide two fully baked configuration ready to be used on your projects: + +* [The simple Azure configuration](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-simple.yml) + is intended for applications that do not require multiple GHC support or + cross-platform support. It builds and tests your project with just the + settings present in your `stack.yaml` file. +* The complex Azure configuration is intended for projects that need to support + multiple GHC versions and multiple operating systems, such as open source + libraries to be released to Hackage. It tests against Stack for different + snapshots on Linux, macOS and Windows. These are the files for the complex + configuration: + - [azure-pipelines.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-pipelines.yml) + : This is the starter file used by the Azure CI. + - [azure-linux-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-linux-template.yml) + : Template for Azure Linux build + - [azure-osx-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-osx-template.yml) + : Template for Azure macOS build + - [azure-windows-template.yml](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/azure/azure-windows-template.yml) + : Template for Azure Windows build + + !!! note + + It is likely going to be necessary to modify this configuration to match + the needs of your project, such as tweaking the build matrix to alter + which GHC versions you test against, or to specify GHC-version-specific + `stack.yaml` files if necessary. Don't be surprised if it doesn't work the + first time around. See the multiple GHC section below for more + information. + +## Creating Azure Pipelines + +Each of these configurations is ready to be used immediately. But before we go +into where to put them, we have to create pipeline for your project in Azure +CI platform: + +* Go to [dev.azure.com](https://dev.azure.com). You have to initially sign-in to + your microsoft account there. +* Once you have logged in to your Microsoft account, you have to sign in to + [Azure devops](https://user-images.githubusercontent.com/737477/52465678-70963080-2ba5-11e9-83d8-84112b140236.png) + from there. +* You will be greeted with a + [dashboard](https://user-images.githubusercontent.com/737477/52465677-70963080-2ba5-11e9-904a-c15c7c0524ef.png) + where you can create your projects. +* Click the "Create Project" button and fill the relevant information in the + [dialog](https://user-images.githubusercontent.com/737477/52465676-70963080-2ba5-11e9-82a4-093ee58f11c9.png) and then click the "Create" button. +* This will lead you to the project + [dashboard](https://user-images.githubusercontent.com/737477/52465675-6ffd9a00-2ba5-11e9-917e-3dec251fcc87.png) + page where you can create pipelines. +* Click on "Pipelines" in the left menu. This will load the + [pipelines page](https://user-images.githubusercontent.com/737477/52465673-6ffd9a00-2ba5-11e9-97a4-04e703ae1fbc.png) + on the right. +* Click on the button "New Pipeline" and you have to follow through the wizard + there. You need to choose your github repository (or Azure repos) and follow + the wizard. Note that in the + [Configure step](https://user-images.githubusercontent.com/737477/52465670-6ffd9a00-2ba5-11e9-83a3-9fffdacbf249.png) + you have to select the "Starter Pipeline". This will open up an + [editor window](https://user-images.githubusercontent.com/737477/52465669-6f650380-2ba5-11e9-9662-e9c6fc2682b5.png). + You can leave the existing YAML configuration there as it is and click the + "Save and run" button. That will popup a + [dialog](https://user-images.githubusercontent.com/737477/52465668-6f650380-2ba5-11e9-9203-6347a609e3c4.png). + Select the relevant option and click "Save and run" button. (Note that this + step would have created `azure-pipelines.yml` in your repository. You have to + replace that with the appropriate configuration file.) + +The rest of this document explains the details of common Azure configurations +for those of you who want to tweak the above configuration files or write your +own. + +*Note:* both Azure and Stack infrastructures are actively developed. We try to +document best practices at the moment. + +## Infrastructure + +Note that you need at least one agent to build your code. You can specify which +virtual image you want to choose using this configuration: + +~~~yaml +pool: + vmImage: ubuntu-latest +~~~ + +The other popular options are `macOS-latest`, `windows-latest` for macOS and +Windows respectively. You can find the +[complete list](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=vsts&tabs=yaml) +here. You also have the option to select a specific supported ubuntu version +like `ubuntu-18.08`. + +## Installing Stack + +Currently there is only one reasonable way to install Stack: fetch a precompiled +binary from GitHub. + +~~~yaml +- script: | + mkdir -p ~/.local/bin + curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' + displayName: Install Stack +~~~ + +## Installing GHC + +There are two ways to install GHC: + +- Let Stack download GHC +- Install GHC using apt package manger. This method is only applicable for + Debian based images. + +But we only use the first method of using Stack to download GHC. + +### Multiple GHC - parametrised builds + +For different GHC versions, you probably want to use different project-level +configuration files (`stack.yaml`, by default). If you don't want to put a +specific `stack.yaml` for a particular snapshot and still want to test it, you +have specify your snapshot argument in `ARGS` environment variable (you will see +an example below). + +~~~yaml +strategy: + matrix: + GHC 8.0: + ARGS: "--snapshot lts-9" + GHC 8.2: + ARGS: "--snapshot lts-11" + GHC 8.4: + ARGS: "--snapshot lts-12" + GHC 8.6: + ARGS: "--snapshot lts-14" + GHC 8.8: + ARGS: "--snapsht lts-15" + nightly: + ARGS: "--snapshot nightly" +~~~ + +## Running tests + +After the environment setup, actual test running is simple. Command: + +~~~text +stack $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps +~~~ + +## Other details + +Some Stack commands will run for long time. To avoid timeouts, use the +[timeoutInMinutes](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?tabs=yaml&view=azdevops#timeouts) +for jobs. + +## Examples + +- [commercialhaskell/stack](https://github.com/commercialhaskell/stack/blob/master/azure-pipelines.yml) +- [psibi/tldr-hs](http://github.com/psibi/tldr-hs) +- [psibi/wai-slack-middleware](https://github.com/psibi/wai-slack-middleware)
+ doc/topics/custom_snapshot.md view
@@ -0,0 +1,137 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +## Snapshot specification + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +Snapshots provide a list of packages to use, along with flags, GHC options, and +a few other settings. Snapshots may extend any other snapshot that can be +specified in a [`snapshot`](../configure/yaml/project.md#snapshot) or +[`resolver`](../configure/yaml/project.md#resolver) key. The packages specified +follow the same syntax for dependencies in Stack's project-level configuration +files. Unlike the `extra-deps` key, however, no support for local directories is +available in snapshots to ensure reproducibility. + +!!! info + + Stack uses the [Pantry](https://hackage.haskell.org/package/pantry) library + for snapshot specification. + +~~~yaml +snapshot: lts-22.28 # Inherits GHC version and package set +compiler: ghc-9.6.5 # Overwrites GHC version in the snapshot, optional + +# Additional packages, follows extra-deps syntax +packages: +- unordered-containers-0.2.7.1 +- hashable-1.2.4.0 +- text-1.2.2.1 + +# Packages from the parent snapshot to ignore +drop-packages: +- wai-extra + +# Packages which should be hidden +hidden: + wai: true + warp: false + +# Set GHC options for specific packages +ghc-options: + warp: + - -O2 + +# Override flags, can also override flags in the parent snapshot +flags: + unordered-containers: + debug: true +~~~ + +If you put this in a `snapshot.yaml` file in the same directory as your project, +you can now use the snapshot like this: + +~~~yaml +snapshot: snapshot.yaml +~~~ + +This is an example of a custom snapshot stored in the filesystem. They are +assumed to be mutable, so you are free to modify it. We detect that the snapshot +has changed by hashing the contents of the involved files, and using it to +identify the snapshot internally. It is often reasonably efficient to modify a +custom snapshot, due to Stack sharing snapshot packages whenever possible. + +### Overriding the compiler + +The following snapshot specification will be identical to `lts-22.28`, but +instead use `ghc-9.6.5` instead of `ghc-9.6.6`: + +~~~yaml +snapshot: lts-22.28 +compiler: ghc-9.6.5 +~~~ + +### Dropping packages + +The following snapshot specification will be identical to `lts-22.28`, but +without the `text` package in our snapshot. Removing this package will cause all +the packages that depend on `text` to be unbuildable, but they will still be +present in the snapshot. + +~~~yaml +snapshot: lts-22.28 +drop-packages: +- text +~~~ + +### Hiding packages + +The following snapshot specification will be identical to `lts-22.28`, but the +`text` package will be hidden when registering. This will affect, for example, +the import parser in the script command. + +~~~yaml +snapshot: lts-22.28 +hidden: +- text +~~~ + +### Specifying GHC options + +In order to specify GHC options for a package, you use the same syntax as the +[ghc-options](../configure/yaml/non-project.md#ghc-options) key for build +configuration. + +The following snapshot specification will be identical to `lts-22.28`, but +provides `-O1` as a ghc-option for `text`: + +~~~yaml +snapshot: lts-22.28 +packages: +- text-2.0.2 +ghc-options: + text: -O1 +~~~ + +This works somewhat differently than the stack.yaml `ghc-options` field, in that +options can only be specified for packages that are mentioned in the custom +snapshot's `packages` list. It sets the ghc-options, rather than extending those +specified in the snapshot being extended. + +Another difference is that the `*` entry for `ghc-options` applies to all +packages in the `packages` list, rather than all packages in the snapshot. + +### Specifying Cabal flags + +In order to specify Cabal flags for a package, you use the same syntax as the +[flags](../configure/yaml/project.md#flags) key for build configuration. The +following snapshot specification will be identical to `lts-22.28`, but +it enables the `developer` Cabal flag: + +~~~yaml +snapshot: lts-22.28 +packages: +- text-2.0.2 +flags: + text: + developer: true +~~~
+ doc/topics/debugging.md view
@@ -0,0 +1,96 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Debugging + +To profile a component of the current project, pass the +[`--profile` flag](../commands/build_command.md#-profile-flag) to `stack build`. + +The flag: + +* for project packages, turns on the Cabal flag + [`--enable-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-profiling); +* turns on the Cabal flag + [`--enable-library-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-library-profiling); and +* passes GHC's + [`+RTS -p` runtime options](https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#rts-flag--p) + to any test suites and benchmarks. + +For example the following command will build the `my-tests` testsuite with +profiling options and create a `my-tests.prof` file in the current directory +as a result of the test run. + +~~~text +stack test --profile my-tests +~~~ + +The `my-tests.prof` file now contains time and allocation info for the test run. + +To create a profiling report for an executable, e.g. `my-exe`, you can command: + +~~~text +stack exec --profile -- my-exe +RTS -p +~~~ + +For more fine-grained control of compilation options there are the +[`--library-profiling` flag](../commands/build_command.md#-no-library-profiling-flag) +and +[`--executable-profiling` flag](../commands/build_command.md#-no-executable-profiling-flag). + +The `--library-profiling` flag: + +* turns on the Cabal flag + [`--enable-library-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-library-profiling); and +* passes GHC's + [`+RTS -p` runtime options](https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#rts-flag--p) + to any test suites and benchmarks. + +The `--executable-profiling` flag: + +* for project packages, turns on the Cabal flag + [`--enable-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-profiling); +* turns on the Cabal flag + [`--enable-library-profiling`](https://cabal.readthedocs.io/en/stable/setup-commands.html#cmdoption-runhaskell-Setup.hs-configure-enable-library-profiling); and +* passes GHC's + [`+RTS -p` runtime options](https://downloads.haskell.org/ghc/latest/docs/users_guide/profiling.html#rts-flag--p) + to any test suites and benchmarks. + +To enable compilation with profiling options by default you can add the +following to a project-level or global configuration file: + +~~~yaml +build: + library-profiling: true + executable-profiling: true +~~~ + +## Further reading + +For more commands and uses, see the +[official GHC chapter on profiling](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html), +the [Haskell wiki](https://wiki.haskell.org/How_to_profile_a_Haskell_program), +and the +[chapter on profiling in Real World Haskell](http://book.realworldhaskell.org/read/profiling-and-optimization.html). + +## Tracing + +To generate a backtrace in case of exceptions during a test or benchmarks run, +use the `--trace` flag. Like `--profile` this compiles with profiling options, +but adds the `+RTS -xc` runtime option. + +## Debugging symbols + +Building with debugging symbols in the +[DWARF information](https://ghc.haskell.org/trac/ghc/wiki/DWARF) is supported by +Stack. This can be done by passing the flag `--ghc-options="-g"` and also to +override the default behaviour of stripping executables of debugging symbols by +passing either one of the following flags: `--no-strip`, +`--no-library-stripping` or `--no-executable-stripping`. + +In Windows, GDB can be installed to debug an executable with +`stack exec -- pacman -S gdb`. Windows' Visual Studio compiler's debugging +format PDB is not supported at the moment. This might be possible by +[separating](https://stackoverflow.com/questions/866721/how-to-generate-gcc-debug-symbol-outside-the-build-target) +debugging symbols and +[converting](https://github.com/rainers/cv2pdb) their format. Or as an option +when +[using the LLVM backend](http://blog.llvm.org/2017/08/llvm-on-windows-now-supports-pdb-debug.html).
+ doc/topics/developing_on_windows.md view
@@ -0,0 +1,109 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Developing on Windows # + +On Windows, Stack comes with an installation of [MSYS2](https://www.msys2.org/). +An environment of MSYS2 (by default, `MINGW64` on 64-bit Windows or `MINGW32` on +32-bit Windows) will be used by Stack to provide a Unix-like shell and +environment for Stack. This may be necessary for installing some Haskell +packages, such as those which use `configure` scripts, or if your project needs +some additional tools during the build phase. + +No matter which terminal software you choose (Windows Terminal, Console Windows +Host, Command Prompt, PowerShell, Git bash or any other) you can use this +environment too by executing all programs through +`stack exec -- <program_name>`. + +Executables and libraries can be installed with the MSYS2 package manager +`pacman`. All tools can be found in the [index](https://packages.msys2.org) to +MSYS2 packages. A [guide](https://www.msys2.org/docs/package-management/) to +package management with `pacman` is also available. `pacman` — like all +other tools in the Stack environment — should be started with +`stack exec -- pacman`. Help about `pacman` commands (operations) can be +obtained by `stack exec -- pacman --help`. Help about a specific `pacman` +operation can be obtained by using `--help` (or `-h`) with an operation. For +example, help about the operation `--sync` (or `-S`) can be obtained with +`stack exec -- pacman --sync --help` or, equivalently, +`stack exec -- pacman -Sh`. + +Command `stack path --bin-path` to see the PATH in the Stack environment. If the +relevant MSYS2 environment is `MINGW64`, on Windows, it includes the +`\mingw64\bin`, `\usr\bin` and `\usr\local\bin` directories of the +Stack-supplied MSYS2. (It includes the corresponding directory if the relevant +MSYS2 environment is other than `MINGW64`.) If your executable depends on files +(for example, dynamic-link libraries) in those directories and you want to run +it outside of the Stack environment, you will need to ensure copies of those +files are on the PATH. + +Command `stack path --extra-include-dirs` and `stack path --extra-library-dirs` +to see the extra directories searched for C header files or system libraries +files in the Stack environment. If the relevant MSYS2 environment is `MINGW64`, +on Windows, it includes the `\mingw64\include` (include) and the `\mingw64\lib` +and `\mingw64\bin` directories (library) of the Stack-supplied MSYS2. (It +includes the corresponding directories if the relevant MSYS2 environment is +other than `MINGW64`.) + +For further information about configuring the relevant MSYS2 environment, see +Stack's [`msys-environment`](../configure/yaml/non-project.md#msys-environment) +non-project specific configuration option documentation. + +## Updating the Stack-supplied MSYS2 ## + +The Stack-supplied MSYS2 can itself be updated with the Stack-supplied `pacman`. +See the MSYS2 guide [Updating MSYS2](https://www.msys2.org/docs/updating/). If +the Stack-supplied `pacman` has a version that is 5.0.1.6403 or greater (see +`stack exec -- pacman --version`) then the command to update is simply: + + stack exec -- pacman -Suy + +This command may need to be run more than once, until everything is reported by +`pacman` as 'up to date' and 'nothing to do'. + +## Setup.hs ## + +`Setup.hs` is automatically run inside the Stack environment. So when you need +to launch another tool you don't need to prefix the command with `stack exec --` +within the custom `Setup.hs` file. + +## Pacman packages to install for common Haskell packages ## + +The following lists MSYS2 packages known to allow the installation of some +common Haskell packages on Windows. Feel free to submit additional entries via a +pull request. + +* For [text-icu](https://hackage.haskell.org/package/text-icu) install + `mingw64/mingw-w64-x86_64-icu`. + +* For [zlib >= 0.7](https://hackage.haskell.org/package/zlib) the default + Cabal flag `pkg-config` is `true` and requires executable `pkg-config` on + the PATH. MSYS2 [defaults](https://www.msys2.org/docs/pkgconfig/) to + [`pkgconf`](https://packages.msys2.org/package/pkgconf?repo=msys&variant=x86_64) + as its `pkg-config` implementation. Installation: + + stack exec -- pacman -S pkgconf + + Alternatively, build with `--flag zlib:-pkg-config`. + +## CMake ## + +CMake has trouble finding other tools even if they are available on the PATH. +Likely this is not a CMake problem but one of the environment not fully +integrating. For example GHC comes with a copy of GCC which is not installed by +MSYS2 itself. If you want to use this GCC you can provide a full path to it, or +find it first with `System.Directory.findExecutable` if you want to launch GCC +from a Haskell file such as `Setup.hs`. + +Experience tells that the `mingw-w64` versions of Make and CMake are most +likely to work. Though there are other versions available through `pacman`, so +have a look to see what works for you. Both tools can be installed with the +commands: + + stack exec -- pacman -S mingw-w64-x86_64-make + stack exec -- pacman -S mingw-w64-x86_64-cmake + +Even though Make and CMake are then both installed into the same environment, +CMake still seems to have trouble to find Make. To help CMake find GCC and Make +supply the following flags: + + -DCMAKE_C_COMPILER=path + -DCMAKE_MAKE_PROGRAM=path
+ doc/topics/docker_integration.md view
@@ -0,0 +1,473 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +Docker integration +=============================================================================== + +Stack has support for automatically performing builds inside a Docker +container, using volume mounts and user ID switching to make it mostly seamless. +FP Complete provides images for use with stack that include GHC, tools, and +optionally have all of the Stackage LTS packages pre-installed in the global +package database. + +The primary purpose for using stack/docker this way is for teams to ensure all +developers are building in an exactly consistent environment without team +members needing to deal with Docker themselves. + +See the +[how stack can use Docker under the hood](https://www.fpcomplete.com/blog/2015/08/stack-docker) +blog post for more information about the motivation and implementation of stack's +Docker support. + +If you'd like to build Docker images that contain your Haskell +executables, see [Building Haskell Apps with +Docker](https://www.fpcomplete.com/blog/2017/12/building-haskell-apps-with-docker). + +Prerequisites +------------------------------------------------------------------------------- + +### Supported operating systems + +**Linux 64-bit**: Docker use requires machine (virtual or metal) running a Linux +distribution +[that Docker supports](https://docs.docker.com/installation/#installation), with +a 64-bit kernel. If you do not already have one, we suggest Ubuntu 14.04 +("trusty") since this is what we test with. + +**macOS**: [Docker for Mac](https://docs.docker.com/docker-for-mac/) is the +supported way to use Docker integration on macOS (the older Docker Machine +(boot2docker) approach to using Docker on macOS is not supported due to issues +with host volume mounting that make Stack nearly unusable for anything but the +most trivial projects). + +Other Un*xen are not officially supported but there are ways to get them +working. See [#194](https://github.com/commercialhaskell/stack/issues/194) for +details and workarounds. + +Note: you may want to use set the `mount-mode` option to `delegated`, since +this can dramatically improve performance on macOS (see +[configuration](#configuration) for more information). + +**Windows does not work at all** (see +[#2421](https://github.com/commercialhaskell/stack/issues/2421)). + +### Docker + +Install the latest version of Docker by following the +[instructions for your operating system](http://docs.docker.com/installation/). + +The Docker client should be able to connect to the Docker daemon as a non-root +user. For example (from +[here](http://docs.docker.com/installation/ubuntulinux/#ubuntu-raring-1304-and-saucy-1310-64-bit)): + + # Add the connected user "${USER}" to the docker group. + # Change the user name to match your preferred user. + sudo gpasswd -a ${USER} docker + + # Restart the Docker daemon. + sudo service docker restart + +You will now need to log out and log in again for the group addition +to take effect. + +Note the above has security implications. See [security](#security) for more. + +Usage +------------------------------------------------------------------------------- + +This section assumes that you already have Docker installed and working. If +not, see the [prerequisites](#prerequisites) section. If you run into any +trouble, see the [troubleshooting](#troubleshooting) section. + +### Enable in stack.yaml + +The most basic configuration is to add this to your project's `stack.yaml`: + + docker: + enable: true + +See [configuration](#configuration) for additional options. You can enable it on +the command-line using `stack --docker`. + +Please note that in a docker-enabled configuration, stack uses the GHC installed +in the Docker container by default. To use a compiler installed by stack, add + + system-ghc: false + +(see [`system-ghc`](../configure/yaml/non-project.md#system-ghc)). + +### Use stack as normal + +With Docker enabled, most stack sub-commands will automatically launch +themselves in an ephemeral Docker container (the container is deleted as soon as +the command completes). The project directory and `~/.stack` are volume-mounted +into the container, so any build artifacts are "permanent" (not deleted with the +container). + +The first time you run a command with a new image, you will be prompted to run +`stack docker pull` to pull the image first. This will pull a Docker +image with a tag that matches your snapshot. Only LTS snapshots are supported +(we do not generate images for nightly snapshots). Not every LTS version is +guaranteed to have an image existing, and new LTS images tend to lag behind +the LTS snapshot being published on stackage.org. Be warned: these images are +rather large! + +Docker sub-commands +------------------------------------------------------------------------------- + +These `stack docker` sub-commands have Docker-specific functionality. Most other +`stack` commands will also use a Docker container under the surface if Docker is +enabled. + +### pull - Pull latest version of image + +`stack docker pull` pulls an image from the Docker registry for the first time, +or updates the image by pulling the latest version. + +### reset - Reset the Docker "sandbox" + +In order to preserve the contents of the in-container home directory between +runs, a special "sandbox" directory is volume-mounted into the container. +`stack docker reset` will reset that sandbox to its defaults. + +Note: `~/.stack` is separately volume-mounted, and is left alone during reset. + +Command-line options +------------------------------------------------------------------------------- + +The default Docker configuration can be overridden on the command-line. See +`stack --docker-help` for a list of all Docker options, and consult +[configuration](#configuration) section below for more information about +their meanings. These are global options, and apply to all commands (not just +`stack docker` sub-commands). + +Configuration +------------------------------------------------------------------------------- + +`stack.yaml` contains a `docker:` section with Docker settings. If this +section is omitted, Docker containers will not be used. These settings can +be included in project, user, or global configuration. + +Here is an annotated configuration file. The default values are shown unless +otherwise noted. + + docker: + + # Set to false to disable using Docker. In the project configuration, + # the presence of a `docker:` section implies docker is enabled unless + # `enable: false` is set. In user and global configuration, this is not + # the case. + enable: true + + # The name of the repository to pull the image from. See the "repositories" + # section of this document for more information about available repositories. + # If this includes a tag (e.g. "my/image:tag"), that tagged image will be + # used. Without a tag specified, the LTS version slug is added automatically. + # Either `repo` or `image` may be specified, but not both. + repo: "fpco/stack-build" + + # Exact Docker image name or ID. Overrides `repo`. Either `repo` or `image` + # may be specified, but not both. (default none) + image: "5c624ec1d63f" + + # Registry requires login. A login will be requested before attempting to + # pull. + registry-login: false + + # Username to log into the registry. (default none) + registry-username: "myuser" + + # Password to log into the registry. (default none) + registry-password: "SETME" + + # If true, the image will be pulled from the registry automatically, without + # needing to run `stack docker pull`. See the "security" section of this + # document for implications of enabling this. + auto-pull: true + + # If true, the container will be run "detached" (in the background). Refer + # to the Docker users guide for information about how to manage containers. + # This option would rarely make sense in the configuration file, but can be + # useful on the command-line. When true, implies `persist`. + detach: false + + # If true, the container will not be deleted after it terminates. Refer to + # the Docker users guide for information about how to manage containers. This + # option would rarely make sense in the configuration file, but can be + # useful on the command-line. `detach` implies `persist`. + persist: false + + # What to name the Docker container. Only useful with `detach` or + # `persist` true. (default none) + container-name: "example-name" + + # Sets the network used by docker. Gets directly passed to dockers `net` + # argument (default: host) + network: host + + # Additional arguments to pass to `docker run`. (default none) + run-args: ["--net=bridge"] + + # Directories from the host to volume-mount into the container. If it + # contains a `:`, the part before the `:` is the directory on the host and + # the part after the `:` is where it should be mounted in the container. + # (default none, aside from the project and stack root directories which are + # always mounted) + mount: + - "/foo/bar" + - "/baz:/tmp/quux" + + # Sets the volume mount mode, passed directly to `docker`. + # The default mode (consistent) is safest, but may suffer poor performance + # on non-Linux platforms such as macOS, where the `delegated` mode will + # be significantly faster. + # See https://docs.docker.com/docker-for-mac/osxfs-caching/ + # for valid values and the implications of changing the default. + mount-mode: delegated + + # Environment variables to set in the container. Environment variables + # are not automatically inherited from the host, so if you need any specific + # variables, use the `--docker-env` command-line argument version of this to + # pass them in. (default none) + env: + - "FOO=BAR" + - "BAR=BAZ QUUX" + + # Location of a Docker container-compatible 'stack' executable with the + # matching version. This executable must be compatible with the Docker + # image in terms of platform (linux-x86_64) and shared libraries + # (statically linked is best, otherwise the image needs to have the + # same shared libraries installed). + # Valid values are: + # host: use the host's executable. This is the default when the host's + # executable is known to work (e.g., from official linux-x86_64 bindist) + # download: download a compatible executable matching the host's version. + # This is the default when the host's executable is not known to work + # image: use the 'stack' executable baked into the image. The version + # must match the host's version + # /path/to/stack: path on the host's local filesystem + stack-exe: host + + # If true (the default when using the local Docker Engine), run processes + # in the Docker container as the same UID/GID as the host. The ensures + # that files written by the container are owned by you on the host. + # When the Docker Engine is remote (accessed by tcp), defaults to false. + set-user: true + + # Require the version of the Docker client to be within the specified + # Cabal-style version range (e.g., ">= 1.6.0 && < 1.9.0") + require-docker-version: "any" + +Image Repositories +------------------------------------------------------------------------------- + +FP Complete provides the following public image repositories on Docker Hub: + +- [fpco/stack-build](https://registry.hub.docker.com/r/fpco/stack-build/) (the + default) - GHC (patched), tools (Stack, Cabal (the tool), happy, alex, etc.), + and system developer libraries required to build all Stackage packages. + +FP Complete also builds custom variants of these images for their clients. + +These images can also be used directly with `docker run` and provide a complete +Haskell build environment. + +In addition, most Docker images that contain the basics for running GHC can be +used with Stack's Docker integration. For example, the +[official Haskell image repository](https://hub.docker.com/_/haskell/) works. +See [Custom images](#custom-images) for more details. + +Security +------------------------------------------------------------------------------- + +Having `docker` usable as a non-root user is always a security risk, and will +allow root access to your system. It is also possible to craft a `stack.yaml` +that will run arbitrary commands in an arbitrary docker container through that +vector, thus a `stack.yaml` could cause stack to run arbitrary commands as root. +While this is a risk, it is not really a greater risk than is posed by the +docker permissions in the first place (for example, if you ever run an unknown +shell script or executable, or ever compile an unknown Haskell package that uses +Template Haskell, you are at equal risk). Nevertheless, there are +[plans to close the stack.yaml loophole](https://github.com/commercialhaskell/stack/issues/260). + +One way to mitigate this risk is, instead of allowing `docker` to run as +non-root, replace `docker` with a wrapper script that uses `sudo` to run the +real Docker client as root. This way you will at least be prompted for your root +password. As [@gregwebs](https://github.com/gregwebs) pointed out, put this +script named `docker` in your PATH (and make sure you remove your user from the +`docker` group as well, if you added it earlier): + + #!/bin/bash -e + # The goal of this script is to maintain the security privileges of sudo + # Without having to constantly type "sudo" + exec sudo /usr/bin/docker "$@" + +Additional notes +------------------------------------------------------------------------------- + +### Volume-mounts and ephemeral containers + +Since filesystem changes outside of the volume-mounted project directory are not +persisted across runs, this means that if you `stack exec sudo apt-get install some-ubuntu-package`, +that package will be installed but then the container it's +installed in will disappear, thus causing it to have no effect. If you wish to +make this kind of change permanent, see later instructions for how to create a +[derivative Docker image](#derivative-image). + +Inside the container, your home directory is a special location that volume- +mounted from within your project directory's `.stack-work` in such a +way as that installed GHC/cabal packages are not shared between different +Stackage snapshots. In addition, `~/.stack` is volume-mounted from the host. + +### Network + +stack containers use the host's network stack within the container +by default, meaning a process running in the container can connect to +services running on the host, and a server process run within the container +can be accessed from the host without needing to explicitly publish its port. +To run the container with an isolated network, use `--docker-run-args` to pass +the `--net` argument to `docker-run`. For example: + + stack --docker-run-args='--net=bridge --publish=3000:3000' \ + exec some-server + +will run the container's network in "bridge" mode (which is Docker's default) +and publish port 3000. + +### Persistent container + +If you do want to do all your work, including editing, in the container, it +might be better to use a persistent container in which you can install Ubuntu +packages. You could get that by running something like +`stack --docker-container-name=NAME --docker-persist exec bash`. This +means when the container exits, it won't be deleted. You can then restart it +using `docker start -a -i NAME`. It's also possible to detach from a container +while it continues running in the background using by pressing Ctrl-P Ctrl-Q, +and then reattach to it using `docker attach NAME`. + +Note that each time you run `stack --docker-persist`, a _new_ persistent +container is created (it will not automatically reuse the previous one). +See the [Docker user guide](https://docs.docker.com/userguide/) for more +information about managing Docker containers. + +### Derivative image + +Creating your own custom derivative image can be useful if you need to install +additional Ubuntu packages or make other changes to the operating system. Here +is an example (replace `stack-build:custom` if you prefer a different name for +your derived container, but it's best if the repo name matches what you're +deriving from, only with a different tag, to avoid recompilation): + + ;;; On host + $ sudo stack --docker-persist --docker-container-name=temp exec bash + + ;;; In container, make changes to OS + # apt-get install r-cran-numderiv + [...] + # exit + + ;;; On host again + $ docker commit temp stack-build:custom + $ docker rm temp + +Now you have a new Docker image named `stack-build:custom`. To use the new +image, run a command such as the following or update the corresponding values in +your `stack.yaml`: + + stack --docker-image=stack-build:custom <COMMAND> + +Note, however, that any time a new image is used, you will have to re-do this +process. You could also use a Dockerfile to make this reusable. Consult the +[Docker user guide](https://docs.docker.com/userguide/) for more +on creating Docker images. + +### Custom images + +The easiest way to create your own custom image us by extending FP Complete's +images, but if you prefer to start from scratch, most images that include the +basics for building code with GHC will work. The image doesn't even, strictly +speaking, need to include GHC, but it does need to have libraries and tools that +GHC requires (e.g., libgmp, gcc, etc.). + +There are also a few ways to set up images that tightens the integration: + +* Create a user and group named `stack`, and create a `~/.stack` directory for + it. Any build plans and caches from it will be copied from the image by Stack, + meaning they don't need to be downloaded separately. +* Any packages in GHC's global package database will be available. This can be + used to add private libraries to the image, or the make available a set of + packages from an LTS release. + +Troubleshooting +------------------------------------------------------------------------------- + +### "No Space Left on Device", but 'df' shows plenty of disk space + +This is likely due to the storage driver Docker is using, in combination with +the large size and number of files in these images. Use +`docker info|grep 'Storage Driver'` to determine the current storage driver. + +We recommend using either the `overlay` or `aufs` storage driver for stack, as +they are least likely to give you trouble. On Ubuntu, `aufs` is the default for +new installations, but older installations sometimes used `devicemapper`. + +The `devicemapper` storage driver's doesn't work well with large filesystems, +and we have experienced other instabilities with it as well. We recommend +against its use. + +The `btrfs` storage driver has problems running out of metadata space long +before running out of actual disk space, which requires rebalancing or adding +more metadata space. See +[CoreOS's btrfs troubleshooting page](https://coreos.com/docs/cluster-management/debugging/btrfs-troubleshooting/) +for details about how to do this. + +Pass the `-s <driver>` argument to the Docker daemon to set the storage driver +(in `/etc/default/docker` on Ubuntu). See +[Docker daemon storage-driver option](https://docs.docker.com/reference/commandline/cli/#daemon-storage-driver-option) +for more details. + +You may also be running out of inodes on your filesystem. Use `df -i` to check +for this condition. Unfortunately, the number of inodes is set when creating +the filesystem, so fixing this requires reformatting and passing the `-N` +argument to mkfs.ext4. + +### Name resolution doesn't work from within container + +On Ubuntu 12.04, by default `NetworkManager` runs `dnsmasq` service, which sets +`127.0.0.1` as your DNS server. Since Docker containers cannot access this +dnsmasq, Docker falls back to using Google DNS (8.8.8.8/8.8.4.4). This causes +problems if you are forced to use internal DNS server. This can be fixed by +executing: + + sudo sed 's@dns=dnsmasq@#dns=dnsmasq@' -i \ + /etc/NetworkManager/NetworkManager.conf && \ + sudo service network-manager restart + +If you have already installed Docker, you must restart the daemon for this +change to take effect: + + sudo service docker restart + +<small> +The above commands turn off `dnsmasq` usage in NetworkManager +configuration and restart network manager. They can be reversed by executing +`sudo sed 's@#dns=dnsmasq@dns=dnsmasq@' -i /etc/NetworkManager/NetworkManager.conf && sudo service network-manager restart`. +These instructions are adapted from +[the Shipyard Project's QuickStart guide](https://github.com/shipyard/shipyard/wiki/QuickStart#127011-dns-server-problem-on-ubuntu). +</small> + +### Cannot pull images from behind firewall that blocks TLS/SSL + +If you are behind a firewall that blocks TLS/SSL and pulling images from a +private Docker registry, you must edit the system configuration so that the +`--insecure-registry <registry-hostname>` option is passed to the Docker daemon. +For example, on Ubuntu: + + echo 'DOCKER_OPTS="--insecure-registry registry.example.com"' \ + |sudo tee -a /etc/default/docker + sudo service docker restart + +This does require the private registry to be available over plaintext HTTP. + +See +[Docker daemon insecure registries documentation](https://docs.docker.com/reference/commandline/cli/#insecure-registries) +for details.
+ doc/topics/editor_integration.md view
@@ -0,0 +1,20 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Editor integration + +## Visual Studio Code + +For further information, see the [Stack and Visual Code](Stack_and_VS_Code.md) +documentation. + +## Shell auto-completion + +Love tab-completion of commands? You're not alone. If you're on bash, just run +the following command (or add it to `.bashrc`): + +~~~text +eval "$(stack --bash-completion-script stack)" +~~~ + +For more information and other shells, see the +[shell auto-completion](shell_autocompletion.md) documentation.
+ doc/topics/haskell_and_c_code.md view
@@ -0,0 +1,229 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Haskell and C code + +## Haskell packages with C code + +A Haskell package can include C source code. For example, consider a simple +one-package Stack project named `c-example`, created by `stack new c-example` +but with these changes: + +A C header file `my-library.h` added in new directory `include`: +~~~c +#ifndef MY_LIBRARY_HEADER +#define MY_LIBRARY_HEADER +int max(int, int); +#endif +~~~ + +A C source code file `my-library.c` added in new directory `c-source`: +~~~c +#include "my-library.h" + +/* Function returning the larger of two integers */ +int max(int x1, int x2) { + if (x1 > x2) + return x1; + else + return x2; +} +~~~ + +A different Haskell module in source file `src/Lib.hs`, including a Haskell +foreign import declaration making use of the C `max` function: +~~~haskell +module Lib ( c_max ) where + +foreign import ccall "max" c_max :: Int -> Int -> Int +~~~ + +A different Haskell module in source file `app/Main.hs`, making use of the +Haskell function `c_max` exported from module `Lib`: +~~~haskell +module Main ( main ) where + +import Lib ( c_max ) + +main :: IO () +main = print $ c_max 10 100 +~~~ + +The package's `package.yaml` file (simplied), used to create the package's +Cabal file, might look like this: +~~~yaml +spec-version: 0.36.0 + +name: c-example +version: 0.1.0.0 + +extra-source-files: +- include/my-library.h + +dependencies: +- base >= 4.7 && < 5 + +library: + source-dirs: src + include-dirs: # Where to look for C header files? + - include + c-sources: # What C source code files to be compiled and linked? + - c-source/my-library.c + +executables: + c-example-exe: + main: Main.hs + source-dirs: app + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: + - c-example +~~~ + +The project's `stack.yaml` file only needs to identify a snapshot: +~~~yaml +snapshot: lts-22.28 # GHC 9.6.6 +~~~ + +This example project can be built with Stack in the normal way (`stack build`), +and the built executable can then be executed in the Stack environment in the +normal way (`stack exec c-example-exe`). + +## Haskell packages with C `main` function + +A Haskell package can include an executable which has a `main` function written +in C. For example, consider a simple one-package Stack project named +`c-example`, with: + +A `package.yaml` describing a library and two executables, named `haskell-exe` +and `c-exe`: + +~~~yaml +spec-version: 0.36.0 + +name: c-example +version: 0.1.0.0 + +dependencies: base + +library: + source-dirs: src + # The Lib_stub.h header must be put by GHC somewhere where Cabal can find it. + # This tells GHC to put it in the autogen-stubs directory of the project + # directory. + ghc-options: + - -stubdir autogen-stubs + +executables: + haskell-exe: + main: Main.hs + source-dirs: app + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: c-example + c-exe: + main: main.c + source-dirs: c-app + ghc-options: -no-hs-main + # This specifies that directory autogen-stubs should be searched for header + # files. + include-dirs: autogen-stubs + dependencies: c-example +~~~ + +!!! warning + + `Cabal-3.12.0.0`, a boot package of GHC 9.10.1, ignores `source-dirs` when + the `main` file is not a Haskell source code file. This was a regression and + fixed in subsequent versions of Cabal (the library). + +A Haskell module souce file named `Lib.hs` in directory `src`: +~~~haskell +module Lib + ( myMax -- Exported only for the use of the 'Haskell' executable + ) where + +myMax :: Int -> Int -> Int +myMax x1 x2 = if x1 > x2 then x1 else x2 + +foreign export ccall myMax :: Int -> Int -> Int +~~~ + +A Haskell module source file named `Main.hs` in directory `app`: +~~~haskell +module Main ( main ) where + +import Lib ( myMax ) + +main :: IO () +main = print $ myMax 10 100 +~~~ + +A C source file named `main.c` in directory `c-app`: +~~~c +// Based in part on +// https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/ffi.html#using-your-own-main + +#include <stdio.h> // Provides printf() + +#include <HsFFI.h> // Provides hs_init() and hs_exit(). See the Haskell 2010 + // Report, 8.7. + +// Parts specific to GHC +#ifdef __GLASGOW_HASKELL__ +#include "Lib_stub.h" // Automatically generated by GHC, given use of + // foreign export ... in module Lib.hs ... +#endif + +int main(int argc, char *argv[]) { + // Initialises the Haskell system and provides it with the available command + // line arguments + hs_init(&argc, &argv); + + // Use our foreign export from module Lib.hs ... + printf("%lld\n", myMax(10,100)); + + // De-initialise the Haskell system + hs_exit(); + return 0; +} +~~~ + +The `foreign export` declaration in Haskell module `Lib` will cause GHC to +generate a 'stub' C header file named `Lib_stub.h`. The GHC option `-stubdir` +will cause GHC to put that file in the specified directory (`autogen-stubs`, in +this example). + +!!! info + + If GHC's `-stubdir` option is omitted, GHC will put the generated C header + file together with the other build artefacts for the module. However, that + location cannot be specified reliably using the `include-dirs` key. + +That generated C header file will have content like: +~~~c +#include <HsFFI.h> +#if defined(__cplusplus) +extern "C" { +#endif +extern HsInt myMax(HsInt a1, HsInt a2); +#if defined(__cplusplus) +} +#endif +~~~ + +The `include-dirs` key will cause the specified directory (again, +`autogen-stubs` in this example) to be searched for C header files. + +The project's `stack.yaml` file only needs to identify a snapshot: +~~~yaml +snapshot: lts-22.28 # GHC 9.6.6 +~~~ + +This example project can be built with Stack in the normal way (`stack build`), +and the built executables can then be executed in the Stack environment in the +normal way (`stack exec haskell-exe` for the 'Haskell' executable and +`stack exec c-exe` for the 'C' executable).
+ doc/topics/index.md view
@@ -0,0 +1,96 @@+--- +title: Topics +--- +<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Topics (advanced) + +This part of the guide provides pages dedicated to specific topics. + +[Stack root](stack_root.md) + +: The Stack root is a directory where Stack stores important information + +[Stack work directories](stack_work.md) + +: Stack work directories are directories within a local project or package + directory in which Stack stores files created during the build process. + +[Snapshot location](snapshot_location.md) + +: How to specify the location of snapshots. + +[Package location](package_location.md) + +: How to specify the location of packages. + +[Snapshot specification](custom_snapshot.md) + +: How to specify the contents of a snapshot. + +[`stack.yaml` vs a Cabal file](stack_yaml_vs_cabal_package_file.md) + +: The difference between Stack's project-level configuration file and a + Cabal file describing a Haskell package. + +[Script interpreter](scripts.md) + +: How to use Stack's script interpreter. + +[Docker integration](docker_integration.md) + +: Stack has support for automatically performing builds inside a Docker + container. + +[Nix integration](nix_integration.md) + +: Stack can be configured to integrate with Nix, a purely functional package + manager. + +[Non-standard project initialization](nonstandard_project_init.md) + +: You may need to configure Stack to work with an existing project that has + one or more Cabal files but no Stack project-level configuration file. + +[Debugging](debugging.md) + +: Advice on debugging using Stack. + +[Editor integration](editor_integration.md) + +: Advice on intergrating Stack with code editors. + +[Stack and Visual Studio Code](Stack_and_VS_Code.md) + +: Advice on using Stack with Visual Studio Code and its Haskell extension. + +[Developing on Windows](developing_on_windows.md) + +: Advice on using Stack on Windows. + +[Shell auto-completion](shell_autocompletion.md) + +: Adding support for the tab completion of standard Stack arguments to the + shell programs Bash, Zsh (the Z shell) and fish. + +[CI](CI.md) + +: Advice on using Stack with CI. + +[Travis CI](travis_ci.md) + +: Advice on using Stack on Travis CI. + +[Azure CI](azure_ci.md) + +: Advice on using Stack on Azure CI. + +[Lock files](lock_files.md) + +: The contents of Stack's lock files, how they are used, and how they are + created and updated. + +[Haskell and C code](haskell_and_c_code.md) + +: Advice on using Stack with Haskell packages that include C source code, + including those with a C `main` function.
+ doc/topics/lock_files.md view
@@ -0,0 +1,186 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Lock Files + +Stack attempts to provide reproducible build plans. This involves reproducibly +getting the exact same contents of source packages and configuration options +(like Cabal flags and GHC options) for a given set of input files. There are a +few problems with making this work: + +* Entering all of the information to fully provide reproducibility is tedious. + This would include things like Hackage revisions, hashes of remote tarballs, + etc. Users don't want to enter this information. +* Many operations in Stack rely upon a "snapshot hash," which transitively + includes the completed information for all of these dependencies. If any of + that information is missing when parsing the `stack.yaml` file or snapshot + files, it could be expensive for Stack to calculate it. + +To address this, we follow the (fairly standard) approach of having a +_lock file_. The goal of the lock file is to cache completed locations of +project, snapshot packages and snapshots themselves so that: + +* These files can be stored in source control +* Users on other machines can reuse these lock files and get identical build + plans given that the used project packages and local snapshots are the same on + those machines +* Rerunning `stack build` in the future is deterministic in the build plan, not + depending on mutable state in the world like Hackage revisions + + !!! note + + If, for example, a tarball available remotely is deleted or the hash + changes, it will not be possible for Stack to perform the build. + However, by deterministic, we mean it either performs the same build or + fails, never accidentally doing something different. + +This document explains the contents of a lock file, how they are used, and how +they are created and updated. + +## stack.yaml and snapshot files + +Relevant to this discussion, Stack's project-level configuration file +(`stack.yaml`, by default) specifies: + +* the parent snapshot (the [`snapshot`](../configure/yaml/project.md#snapshot) + or [`resolver`](../configure/yaml/project.md#resolver) key) +* extra-deps + +Some of this information can be incomplete. Consider this `stack.yaml` file: + +~~~yaml +snapshot: lts-19.22 +packages: +- . +extra-deps: +- acme-missiles-0.3 +~~~ + +This information is _incomplete_. For example, the extra-deps may change in the +future. Instead, you could specify enough information in the `stack.yaml` file +to fully resolve that package. That looks like: + +~~~yaml +extra-deps: +- hackage: acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1,613 + pantry-tree: + size: 226 + sha256: 614bc0cca76937507ea0a5ccc17a504c997ce458d7f2f9e43b15a10c8eaeb033 +~~~ + +The `lts-19.22` information is also incomplete. While we assume in general that +Haskell LTS snapshots never change, there's nothing that prohibits that from +happening. Instead, the complete version of that key is: + +~~~yaml +snapshot: +- url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/22.yaml + size: 619399 + sha256: 5098594e71bdefe0c13e9e6236f12e3414ef91a2b89b029fd30e8fc8087f3a07 +~~~ + +Users don't particularly feel like writing all of that. Therefore, it's common +to see _incomplete_ information in a `stack.yaml` file. + +## Recursive snapshot layers + +Snapshot files can be _recursive_, where `stack.yaml` refers to `foo.yaml`, +which refers to `bar.yaml`, which refers to `baz.yaml`. A local snapshot file +can refer to a remote snapshot file (available via an HTTP(S) URL). + +We need to encode information from _all_ of these snapshot layers and the +`stack.yaml` file in the lock file, to ensure that we can detect if anything +changes. + +## Performance + +In addition to acting as a pure correctness mechanism, the design of a lock file +given here also works as a performance improvement. Instead of requiring that +all snapshot files be fully parsed on each Stack invocation, we can store +information in the lock file and bypass parsing of the additional files in the +common case of no changes. + +## Lock file contents + +The lock file contains the following information: + +* Completed package locations for extra-deps and packages in snapshot files + + !!! note + + This only applies to _immutable_ packages. Mutable packages are not + included in the lock file. + +* Completed information for the snapshot locations + +It looks like the following: + +~~~yaml +# Lock file, some message about the file being auto-generated +snapshots: + # Starts with the snapshot specified in stack.yaml, + # then continues with the snapshot specified in each + # subsequent snapshot file + - original: + foo.yaml # raw content specified in a snapshot file + completed: + file: foo.yaml + sha256: XXXX + size: XXXX + - original: + lts-13.9 + completed: + size: 496662 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/13/9.yaml + sha256: 83de9017d911cf7795f19353dba4d04bd24cd40622b7567ff61fc3f7223aa3ea + +packages: +- original: https://hackage.haskell.org/package/acme-missiles-0.3.tar.gz + completed: + size: 1442 + url: https://hackage.haskell.org/package/acme-missiles-0.3.tar.gz + name: acme-missiles + version: '0.3' + sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b + pantry-tree: + size: 226 + sha256: 614bc0cca76937507ea0a5ccc17a504c997ce458d7f2f9e43b15a10c8eaeb033 +~~~ + +## Creation procedure + +Whenever a project-level configuration file (`stack.yaml`, by default) is +loaded, Stack checks for a lock file in the same file path, with a `.lock` +extension added. For example, if you command: + +~~~text +stack --stack-yaml my-stack.yaml build +~~~ + +or + +~~~text +stack --stack-yaml my-stack.yaml build --dry-run +~~~ + +then Stack will use a lock file in the location `my-stack.yaml.lock`. For the +rest of this document, we'll assume that the files are simply `stack.yaml` and +`stack.yaml.lock`. + +If the lock file does not exist, subject to Stack's +[`--lock-file`](../configure/global_flags.md#-lock-file-option) option, it will +be created by: + +* Loading the `stack.yaml` +* Loading all snapshot files +* Completing all missing information +* Writing out the new `stack.yaml.lock` file to the disk + +## Update procedure + +Whenever a project-level configuration file (`stack.yaml`, by default) is +loaded, all completed package or snapshot locations (even those completed using +information from a lock file) get collected to form a new lock file in memory. +Subject to Stack's +[`--lock-file`](../configure/global_flags.md#-lock-file-option) option, that new +lock file is compared against the one on disk and, if there are any differences, +written out to the disk.
+ doc/topics/nix_integration.md view
@@ -0,0 +1,440 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Nix integration + +[:octicons-tag-24: 0.1.10.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.10.0) + +[Nix](https://nixos.org/) is a purely functional package manager. Stack can be +configured to integrate with Nix. Integration provides these benefits: + +* more reproducible builds. This is because fixed versions of any system + libraries and commands required to build the project are automatically built + using Nix and managed locally for each project. These system packages never + conflict with any existing versions of these libraries on your system. That + they are managed locally to the project means that you don't need to alter + your system in any way to build any odd project pulled from the Internet; and +* implicit sharing of system packages between projects. This means you don't + have more copies on-disk than you need. + +The Nix package manager is a pre-requisite for integration. On Linux (including +Windows Subsystem for Linux) and macOS, it can be downloaded and installed from +the [Nix download page](https://nixos.org/download.html). + +When integrated with Nix, Stack handles Haskell dependencies as it usually does +and the Nix package manager handles the _non-Haskell_ dependencies needed by the +Haskell packages. + +Stack downloads Haskell packages from [Stackage](https://www.stackage.org/lts) +and builds them locally. Stack uses Nix to download +[Nix packages][nix-search-packages]. These provide the GHC compiler and external +C libraries that you would normally install manually. + +Nix's `nix-shell` starts an interactive shell based on a Nix expression. Stack +can automatically create a Nix build environment in the background using +`nix-shell`. There are two alternative options to create such a build +environment: + +1. provide a list of [Nix packages][nix-search-packages] +2. provide a `shell.nix` file that gives you more control over the libraries and + tools available inside the shell. + +A `shell.nix` file requires writing code in Nix's +[custom language][nix-language]. Use this option only if you know Nix and have +special requirements, such as using custom Nix packages that override the +standard ones or using system libraries with special requirements. + +### Checking the Nix installation + +Once Nix is installed, the Nix commands (`nix-shell` etc) should be available. +If they are not, it could be because the file +`$HOME/.nix-profile/etc/profile.d/nix.sh` is not sourced by your shell. + +You should either: + +1. run `source ~/.nix-profile/etc/profile.d/nix.sh` each time you open a + terminal and need Nix; or +2. add the command `source ~/.nix-profile/etc/profile.d/nix.sh` to your + `~/.bashrc` or `~/.bash_profile` file. + +A Nix path can be specified between angle brackets, e.g. `<nixpkgs>`, and the +directories listed in the `NIX_PATH` environment variable will be searched for +the given file or directory name. Stack makes use of path `<nixpkgs>`. From +Nix 2.4, `NIX_PATH` is not set by `nix.sh`. If `NIX_PATH` is not set, Nix will +fall back to (first) `$HOME/.nix-defexpr/channels` in impure and unrestricted +evaluation mode. However, Stack may use a pure Nix mode (see further +[below](#pure-and-impure-nix-shells)). That directory can be appended to +`NIX_PATH` with +`export NIX_PATH=${NIX_PATH:+$NIX_PATH:}$HOME/.nix-defexpr/channels`. For +information about how Stack itself can configure `NIX_PATH`, see further +[below](#nix-package-sources). + +### Enable Nix integration + +On NixOS, Nix integration is enabled by default; on other operating systems it +is disabled. To enable Nix integration, add the following section to your Stack +configuration file (`stack.yaml` or `config.yaml`): + +~~~yaml +nix: + enable: true # false by default, except on NixOS +~~~ + +The equivalent command line flag (which will prevail) is `--[no-]nix`. Passing +any `--nix-*` option on the command line will imply the `--nix` option. + +If Nix integration is not enabled, Stack will notify the user if a `nix` +executable is on the PATH. If that notification is unwanted, it can be muted by +setting Stack's configuration option +[`notify-if-nix-on-path`](../configure/yaml/non-project.md#notify-if-nix-on-path) +to `false`. + +With Nix integration enabled, `stack build` and `stack exec` will automatically +launch themselves in a local build environment (using `nix-shell` behind the +scenes). It is not necessary to run `stack setup`, unless you want to cache a +GHC installation before running a build. + +**Known limitation on macOS:** currently, `stack --nix ghci` fails on macOS, due +to a bug in GHCi when working with external shared libraries. + +### Supporting both Nix and non-Nix developers + +With Nix integration enabled in Stack's configuration file, every developer of +your project needs to have Nix installed, but the developer also gets all +external libraries automatically. + +Julien Debon of Tweag has published a [blog post][tweag-blog-post] on +*Smooth, non-invasive Haskell Stack and Nix shell integration* (2 June 2022). +The post explains how to set things up so that both Nix and non-Nix developers +can work together on the same project. The `tweag/haskell-stack-nix-example` +[GitHub repository][tweag-example] provides an example of working Stack and Nix +shell integration to accompany the post. + +Nix 2.4 (released 1 November 2021) introduced a new and experimental format to +package Nix-based projects, known as 'flakes'. + +The example below adapts and extends the example accompanying the blog post +above to use Nix flakes. The `flake.nix` file is: + +~~~nix +{ + description = "my project description"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + hPkgs = + pkgs.haskell.packages."ghc8107"; # need to match Stackage LTS version + # from stack.yaml snapshot + + myDevTools = [ + hPkgs.ghc # GHC compiler in the desired version (will be available on PATH) + hPkgs.ghcid # Continuous terminal Haskell compile checker + hPkgs.ormolu # Haskell formatter + hPkgs.hlint # Haskell codestyle checker + hPkgs.hoogle # Lookup Haskell documentation + hPkgs.haskell-language-server # LSP server for editor + hPkgs.implicit-hie # auto generate LSP hie.yaml file from cabal + hPkgs.retrie # Haskell refactoring tool + # hPkgs.cabal-install + stack-wrapped + pkgs.zlib # External C library needed by some Haskell packages + ]; + + # Wrap Stack to work with our Nix integration. We don't want to modify + # stack.yaml so non-Nix users don't notice anything. + # - no-nix: We don't want Stack's way of integrating Nix. + # --system-ghc # Use the existing GHC on PATH (will come from this Nix file) + # --no-install-ghc # Don't try to install GHC if no matching GHC found on PATH + stack-wrapped = pkgs.symlinkJoin { + name = "stack"; # will be available as the usual `stack` in terminal + paths = [ pkgs.stack ]; + buildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/stack \ + --add-flags "\ + --no-nix \ + --system-ghc \ + --no-install-ghc \ + " + ''; + }; + in { + devShells.default = pkgs.mkShell { + buildInputs = myDevTools; + + # Make external Nix c libraries like zlib known to GHC, like + # pkgs.haskell.lib.buildStackProject does + # https://github.com/NixOS/nixpkgs/blob/d64780ea0e22b5f61cd6012a456869c702a72f20/pkgs/development/haskell-modules/generic-stack-builder.nix#L38 + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath myDevTools; + }; + }); +} +~~~ + +Check-in this `flake.nix` to your project's repository. Run the `nix develop` +command (it searches for `flake.nix` by default) and you'll find a new +`flake.lock` file. That file that pins the precise nixpkgs package set. Check-in +that `flake.lock` file as well, and every Nix developer of your project will use +precisely the same package set. + +### GHC through Nix packages + +Nix integration will instruct Stack to build inside a local build environment. +That environment will also download and use a +[GHC Nix package](https://search.nixos.org/packages?query=haskell.compiler.ghc) +matching the required version of the configured Stack +[snapshot](../configure/yaml/project.md#snapshot). + +Enabling Nix integration means that packages will always be built using the +local GHC from Nix inside your shell, rather than your globally installed system +GHC (if any). + +Stack can use only GHC versions that are in the Nix package repository. The +[Nixpkgs master branch](https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/haskell-modules) +usually picks up new versions quickly, but it takes two or three days before +those updates arrive in the `unstable` channel. Release channels, like +`nixos-22.05`, receive those updates only occasionally -- say, every two or +three months --, so you should not expect them to have the latest compiler +available. Fresh NixOS installs use a release version by default. + +To identify whether a given compiler is available, you can use the following Nix +command: + +~~~sh +nix-env -f "<nixpkgs>" -qaP -A haskell.compiler.ghc924 +haskell.compiler.ghc924 ghc-9.2.4 +~~~ + +If Nix doesn't know that version of GHC, you'll see the following error message: + +~~~sh +nix-env -f "<nixpkgs>" -qaP -A haskell.compiler.ghc999 +error: attribute ‘ghc999’ in selection path ‘haskell.compiler.ghc999’ not found +~~~ + +You can list all known Haskell compilers in Nix with the following: + +~~~sh +nix-instantiate --eval -E "with import <nixpkgs> {}; lib.attrNames haskell.compiler" +~~~ + +Alternatively, use `nix repl`, a convenient tool to explore nixpkgs: + +~~~sh +nix repl +~~~ + +In the REPL, load nixpkgs and get the same information through autocomplete: + +~~~sh +nix-repl> :l <nixpkgs> +nix-repl> haskell.compiler.ghc<Tab> +~~~ + +You can type and evaluate any Nix expression in the Nix REPL, such as the one we +gave to `nix-instantiate` earlier. + +### External C libraries through Nix packages + +To let Nix manage external C libraries, add (for example) the following section +to your Stack configuration file: + +~~~yaml +nix: + enable: true + packages: [zlib, glpk, pcre] +~~~ + +The equivalent command line option is `--nix-packages "zlib glpk pcre"`. + +The `packages` key and the `shell-file` key (see further below) are +alternatives. Specifying both results in an error. + +The example above will instruct Stack to build inside a local build environment +that will have the Nix packages +[zlib](https://search.nixos.org/packages?query=zlib), +[glpk](https://search.nixos.org/packages?query=glpk) and +[pcre](https://search.nixos.org/packages?query=pcre) +installed, which provide the C libraries of the same names. + +**Note:** currently, Stack only discovers dynamic and static libraries in the +`lib/` folder of any Nix package, and likewise header files in the `include/` +folder. If you're dealing with a package that doesn't follow this standard +layout, you'll have to deal with that using a custom `shell.nix` file (see +further below). + +### External C libraries through a `shell.nix` file + +In Nix, a 'derivation' is a description of a build action and its result is a +Nix store object. Nix's [custom language][nix-language] can provide a fully +customized derivation as an environment to use. To specify such a `shell.nix` +file, add the following section to your Stack configuration file: + +~~~yaml +nix: + enable: true + shell-file: shell.nix +~~~ + +The equivalent command line option (which will prevail) is +`--nix-shell-file shell.nix`. + +The `packages` and `shell-file` keys are alternatives. Specifying both results +in an error. + +Defining a `shell.nix` file allow you to override some Nix derivations, for +instance to change some build options of the libraries you use, or to set +additional environment variables. For further information, see the +[Nix manual][nix-manual-exprs]. + +The `shell.nix` file that is the equivalent of the +`packages: [zlib, glpk, pcre]` example above is: + +~~~nix +{ghc}: +with (import <nixpkgs> {}); + +haskell.lib.buildStackProject { + inherit ghc; + name = "myEnv"; + buildInputs = [ zlib glpk pcre ]; +} +~~~ + +The `buildStackProject` utility function is documented in the +[Nixpkgs manual][nixpkgs-manual-haskell]. + +Stack expects the `shell.nix` file to define a function of with one argument +called `ghc` (arguments are not positional), which you should give to +function `buildStackProject`. This argument is a GHC Nix package in the +version as defined in the snapshot you set in Stack's project-level +configuration file (`stack.yaml`, by default). + +### Pure and impure Nix shells + +By default, Stack will run the build in a *pure* Nix build environment (or +*shell*), which means two important things: + +1. basically **no environment variable will be forwarded** from your user + session to the nix-shell (variables like `HTTP_PROXY` or `PATH` notably will + not be available); and +2. the build should fail if you haven't specified all the dependencies in the + `packages:` section of the Stack configuration file, even if these + dependencies are installed elsewhere on your system. This behaviour enforces + a complete description of the build environment to facilitate + reproducibility. + +To override this behaviour, add the following section to your Stack YAML +configuration file: + +~~~yaml +nix: + enable: true + pure: false +~~~ + +The equivalent command line flag (which will prevail) is `--[no-]-nix-pure`. + +**Note:** On macOS, shells are non-pure by default currently. This is due soon +to be resolved locale issues. So on macOS you'll need to be a bit more careful +to check that you really have listed all dependencies. + +### Nix package sources + +Nix organizes its packages in snapshots of packages (each snapshot being a +"package set") similar to how Stackage organizes Haskell packages. By default, +`nix-shell` will look for the "nixpkgs" package set located by your `NIX_PATH` +environment variable. This package set can be different depending on when you +installed Nix and which nixpkgs channel you're using (similar to the LTS channel +for stable packages and the nightly channel for bleeding edge packages in +[Stackage](https://www.stackage.org/)). This is bad for reproducibility so that +nixpkgs should be pinned, i.e., set to the same package set for every developer +of your project. + +To set or override the Nix package set, add the following section to your Stack +configuration file: + +~~~yaml +nix: + path: [nixpkgs=<path_to_my_own_nixpkgs_clone>] +~~~ + +The equivalent command line option is +`--nix-path <path_to_my_own_nixpkgs_clone>`. + +By this means, you can ask Nix to use your own local checkout of the nixpkgs +repository. You could in this way use a bleeding edge nixpkgs, cloned from the +`NixOS/nixpkgs` [repository](http://www.github.com/NixOS/nixpkgs) `master` +branch, or edit the Nix descriptions of some packages. + +The Tweag example [repository][tweag-example] shows how you can pin a package +set. + +## Non-project specific configuration + +Below is a summary of the non-project specific configuration options and their +default values. The options can be set in Stack's project-level configuration +file (`stack.yaml`, by default) or its global configuration file +(`config.yaml`). + +~~~yaml +nix: + + # false by default, except on NixOS. Is Nix integration enabled? + enable: true + + # true by default. Should Nix run in a pure shell? + pure: true + + # Empty by default. The list of packages you want to be available in the + # nix-shell at build time (with `stack build`) and run time (with + # `stack exec`). + packages: [] + + # Unset by default. You cannot set this option if `packages:` + # is already present and not empty. + shell-file: shell.nix + + # A list of strings, empty by default. Additional options that will be passed + # verbatim to the `nix-shell` command. + nix-shell-options: [] + + # A list of strings, empty by default, such as + # `[nixpkgs=/my/local/nixpkgs/clone]` that will be used to override + # NIX_PATH. + path: [] + + # false by default. Whether to add your Nix dependencies as Nix garbage + # collection roots. This way, calling nix-collect-garbage will not remove + # those packages from the Nix store, saving you some time when running + # stack build again with Nix support activated. + # + # This creates a `nix-gc-symlinks` directory in the project `.stack-work`. + # To revert that, just delete this `nix-gc-symlinks` directory. + add-gc-roots: false +~~~ + +`stack --nix-help` will list the equivalent command line flags and options. + +## Stack and developer tools on NixOS + +NixOS is a Linux distribution based on Nix, that is composed using modules and +packages defined in the Nixpkgs project. + +When using Stack on NixOS, you must use Stack's Nix integration to install GHC. +That is because external C libraries in NixOS are not installed in the usual +distribution directories. GHC installed through Stack (without Nix) can't find +those libraries and, therefore, can't build most projects. However, GHC provided +through Nix can be modified to find the external C libraries provided through +Nix. + +[nix-language]: https://wiki.nixos.org/wiki/Overview_of_the_Nix_Language +[nix-manual-exprs]: http://nixos.org/manual/nix/stable/expressions/writing-nix-expressions.html +[nix-search-packages]: https://search.nixos.org/packages +[nixpkgs-manual-haskell]: https://haskell4nix.readthedocs.io/nixpkgs-users-guide.html?highlight=buildStackProject#how-to-build-a-haskell-project-using-stack +[tweag-blog-post]: https://www.tweag.io/blog/2022-06-02-haskell-stack-nix-shell/ +[tweag-example]: https://github.com/tweag/haskell-stack-nix-example/
+ doc/topics/nonstandard_project_init.md view
@@ -0,0 +1,36 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Non-standard project initialization + +You may need to configure Stack to work with an existing project that has one or +more Cabal files but no Stack project-level configuration file (`stack.yaml`, by +default). + +## The `stack init` command + +The `stack init` command: + +* finds all of the Cabal files in your current directory and subdirectories + (unless you use `--ignore-subdirs`) and determines the packages and versions + they require +* Finds the best combination of snapshot and package flags that allows + everything to compile with minimum external dependencies +* Tries to look for the best matching snapshot from latest Haskell LTS, latest + Stackage Nightly, and other Haskell LTS, in that order + +If `stack init` finds a match, it will generate a `stack.yaml` file. + +You can specify the directory, or directories to include in the search for +Cabal files. + +### The `stack init --force` flag + +Set the flag to force the over-writing of any existing `stack.yaml` file. + +### The `stack init --ignore-subdirs` flag + +Set the flag to not search for Cabal files in subdirectories. + +### The `stack init --omit-packages` flag + +Set the flag to exclude any conflicting or incompatible user packages.
+ doc/topics/package_location.md view
@@ -0,0 +1,225 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://rawgit.com/commercialhaskell/stack/master/doc/img/hidden-warning.svg"></a></div> + +# Package location + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +This document describes the specification of a package location (in the +`extra-deps` key and in a snapshot). + +!!! info + + Stack uses the [Pantry](https://hackage.haskell.org/package/pantry) to + specify the location of packages. Pantry is geared towards reproducible + build plans with cryptographically secure specification of packages. + +There are three types of package locations: + +1. Hackage packages +2. Git and Mecurial repositories +3. Local or remote archives (such as GitHub archives) + +All three types support optional tree metadata to be added, which can be used +for reproducibility and faster downloads. This information can automatically be +generated in a [lock file](lock_files.md). + +## Hackage packages + +A package can be identified by its name, version and Cabal file revision +number, with revision `0` being the original Cabal file. For example: + +~~~yaml +extra-deps: +- acme-missiles-0.3@rev:0 +~~~ + +A package name and version only can be stated. Using this syntax, the most +recent Cabal file revision available in the package index will be used. For +example: + +~~~yaml +extra-deps: +- acme-missiles-0.3 +~~~ + +This syntax is often used in practice, but may result in one build differing +from another, if a new or further Cabal file revision is added to the package +index between the builds. + +As an alternative to specifying the Cabal file revision number, you can specify +the package name and version with the SHA256 hash of the contents of its Cabal +file. Doing so is slightly more resilient than using the Cabal file revision +number, as it does not rely on the correct ordering in the package index. +For example: + +~~~yaml +extra-deps: +- acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1 +~~~ + +Optionally, you can specify also the size of the Cabal file in bytes. For +example (where the file size is `631` bytes): + +~~~yaml +extra-deps: +- acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1,631 +~~~ + +Optionally, you can specify also the Pantry tree information. For example: + +~~~yaml +- hackage: acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a687d45965778deb8694c5d1,613 + pantry-tree: + size: 226 + sha256: 614bc0cca76937507ea0a5ccc17a504c997ce458d7f2f9e43b15a10c8eaeb033 +~~~ + +A Pantry tree is a list of CAS (content-addressable storage) +'SHA256 hash'-'size in bytes' keys for each of the files in a package. + +The SHA256 hash of the contents of the Cabal file and its size in bytes is +provided in Stack's lock file. For further information, see the +[lock files](lock_files.md) documentation. The SHA256 hash and file size +alternative is also what Stack uses when it makes suggestions about missing +packages. + +## Git and Mercurial repositories + +You can specify a Git or Mercurial repository at a specific commit, and Stack +will clone that repository and, if it has submodules (Git), update the +repository's submodules. For example: + +~~~yaml +extra-deps: +- git: git@github.com:commercialhaskell/stack.git + commit: '6a86ee32e5b869a877151f74064572225e1a0398' +- git: git@github.com:snoyberg/http-client.git + commit: 'a5f4f3' +- hg: https://example.com/hg/repo + commit: 'da39a3ee5e6b4b0d3255bfef95601890afd80709' +~~~ + +!!! note + + It is highly recommended that you only use SHA1 values for a Git or + Mercurial commit. Other values may work, but they are not officially + supported, and may result in unexpected behavior (namely, Stack will not + automatically pull to update to new versions). Another problem with this is + that your build will not be deterministic, because when someone else tries + to build the project they can get a different checkout of the package. + +!!! note + + The `commit:` key expects a YAML string. A commit hash, or partial hash, + comprised only of digits represents a YAML number, unless it is enclosed in + quotation marks. + +!!! warning + + For the contents of a Git repository, Stack cannot handle filepaths or + symbolic link names that are longer than those supported by the `ustar` + (Unix Standard TAR) archive format defined by + [POSIX.1-1988](https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub151-1.pdf). + + Stack uses `git archive` to convert the content of a Git repository to a + TAR archive, which it then seeks to consume. Git produces `pax` format + archives which use 'extended' headers for matters that the `ustar` format + cannot handle. Unfortunately, Stack cannot consume an extended header and + will silently discard the item. + +A common practice in the Haskell world is to use "megarepos", or repositories +with multiple packages in various subdirectories. Some common examples include +[wai](https://github.com/yesodweb/wai/) and +[digestive-functors](https://github.com/jaspervdj/digestive-functors). To +support this, you may also specify `subdirs` for repositories. For example: + +~~~yaml +extra-deps: +- git: git@github.com:yesodweb/wai + commit: '2f8a8e1b771829f4a8a77c0111352ce45a14c30f' + subdirs: + - auto-update + - wai +~~~ + +If unspecified, `subdirs` defaults to `['.']` meaning looking for a package in +the root of the repository. If you specify a value of `subdirs`, then `'.'` is +_not_ included by default and needs to be explicitly specified if a required +package is found in the top-level directory of the repository. + +### git-annex + +[git-annex](https://git-annex.branchable.com) is not supported. This is because +`git archive` does not handle symbolic links outside the work tree. It is still +possible to use repositories which use git-annex but do not require the annex +files for the package to be built. + +To do so, ensure that any files or directories stored by git-annex are marked +[export-ignore](https://git-scm.com/docs/git-archive#Documentation/git-archive.txt-export-ignore) +in the `.gitattributes` file in the repository. For further information, see +issue [#4579](https://github.com/commercialhaskell/stack/issues/4579). + +For example, if the directory `fonts/` is controlled by git-annex, use the +following line: + +~~~gitattributes +fonts export-ignore +~~~ + +## Local or remote archives (such as GitHub archives) + +### Filepaths or URLs to archive files + +You can use filepaths referring to local archive files or HTTP or HTTPS URLs +referring to remote archive files, either tarballs or ZIP files. + +!!! note + + An example of a remote archive file is a Hackage package candidate, usually + located at (for example) + https://hackage.haskell.org/package/my-package-1.0.0/candidate/my-package-1.0.0.tar.gz. + +!!! warning + + Stack assumes that these archive files never change after downloading to + avoid needing to make an HTTP request on each build. + +For safer, more reproducible builds, you can optionally specify a cryptographic +hash of the archive file. + +For example: + +~~~yaml +extra-deps: +- https://example.com/foo/bar/baz-0.0.2.tar.gz +- archive: http://github.com/yesodweb/wai/archive/2f8a8e1b771829f4a8a77c0111352ce45a14c30f.zip + subdirs: + - wai + - warp +- archive: ../acme-missiles-0.3.tar.gz + sha256: e563d8b524017a06b32768c4db8eff1f822f3fb22a90320b7e414402647b735b +~~~ + +### GitHub archive files + +[:octicons-tag-24: 1.7.1](https://github.com/commercialhaskell/stack/releases/tag/v1.7.1) + +You can specify a GitHub respository at a specific commit and Stack will obtain +from GitHub an archive file of the files in the repository at that point in its +history. For example: + +~~~yaml +extra-deps: +- github: snoyberg/http-client + commit: 'a5f4f30f01366738f913968163d856366d7e0342' +~~~ + +!!! note + + An archive file of the files in a GitHub repository at a point in its + history is not the same as a clone of the repository (including its history) + and the updating of any submodules. If you need the latter, use the syntax + for a [Git repository](#git-and-mercurial-repositories). + + If the package fails to build due to missing files, it may be that updated + submodules are required.
+ doc/topics/scripts.md view
@@ -0,0 +1,290 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Stack's script interpreter + +Stack offers a very useful feature for running files: a script interpreter. For +too long have Haskellers felt shackled to bash or Python because it's just too +hard to create reusable source-only Haskell scripts. Stack attempts to solve +that. + +You can use `stack <file_name>` to execute a Haskell source file. Usually, the +Stack command to be applied is specified using a special Haskell comment (the +Stack interpreter options comment) at the start of the source file. That command +is most often [`stack script`](../commands/script_command.md) but it can be, for +example, [`stack runghc`](../commands/runghc_command.md). If there is no Stack +interpreter options comment, Stack will warn that one was expected. + +An example will be easiest to understand. Consider the Haskell source file +`turtle-example.hs` with contents: + +~~~haskell +#!/usr/bin/env stack +-- stack script --snapshot lts-22.28 --package turtle +{-# LANGUAGE OverloadedStrings #-} +import Turtle (echo) +main = echo "Hello World!" +~~~ + +=== "Unix-like" + + The first line beginning with the 'shebang' (`#!`) tells Unix to use Stack + as a script interpreter, if the file's permissions mark it as executable. A + shebang line is limited to a single argument, here `stack`. + + The file's permissions can be set with command `chmod` and then it can be + run: + + ~~~text + chmod +x turtle-example.hs + ./turtle-example.hs + ~~~ + + !!! note + + On macOS: + + - Avoid `{-# LANGUAGE CPP #-}` in Stack scripts; it breaks the shebang + line ([GHC #6132](https://gitlab.haskell.org/ghc/ghc/issues/6132)) + + - Use a compiled executable, not another script, in the shebang line. + Eg `#!/usr/bin/env runhaskell` will work but + `#!/usr/local/bin/runhaskell` would not. + + Alternatively, the script can be run with command: + + ~~~text + stack turtle-example.hs + ~~~ + +=== "Windows (with PowerShell)" + + The first line beginning with the 'shebang' (`#!`) has a meaning on + Unix-like operating systems but will be ignored by PowerShell. It can be + omitted on Windows. The script can be run with command: + + ~~~text + stack turtle-example.hs + ~~~ + +In both cases, the command yields: + +~~~text +Hello World! +~~~ + +the first time after a little delay (as GHC is downloaded, if necessary, and +dependencies are built) and subsequent times more promptly (as the runs are +able to reuse everything already built). + +The second line of the source code is the Stack interpreter options comment. In +this example, it specifies the [`stack script`](../commands/script_command.md) +command with the options of a LTS Haskell 22.28 snapshot +(`--snapshot lts-22.28`) and ensuring the +[`turtle`](https://hackage.haskell.org/package/turtle) package is available +(`--package turtle`). The version of the package will be that in the specified +snapshot (`lts-22.28` provides `turtle-1.6.2`). + +## Arguments and interpreter options and arguments + +Arguments for the script can be specified on the command line after the file +name: `stack <file_name> <arg1> <arg2> ...`. + +The Stack interpreter options comment must specify what would be a single valid +Stack command at the command line if the file name were included as an argument, +starting with `stack`. It can include `--` followed by arguments. In particular, +the Stack command `stack <arg1> MyScript.hs <arg4>` with +Stack interpreter options comment: + +~~~haskell +-- stack <arg2> <command> <arg3> -- <arg5> +~~~ + +is equivalent to the following command at the command line: + +~~~text +stack <arg1> <arg2> <command> <arg3> -- MyScript.hs <arg4> <arg5> +~~~ + +The Stack interpreter options comment must be the first line of the file, unless +a shebang line is the first line, when the comment must be the second line. The +comment must start in the first column of the line. + +When many options are needed, a block style comment that splits the command over +more than one line may be more convenient and easier to read. + +For example, the command `stack MyScript.hs arg1 arg2` with `MyScript.hs`: + +~~~haskell +#!/usr/bin/env stack +{- stack script + --snapshot lts-22.28 + -- + +RTS -s -RTS +-} +import Data.List (intercalate) +import System.Environment (getArgs) +import Turtle (echo, fromString) + +main = do + args <- getArgs + echo $ fromString $ intercalate ", " args +~~~ + +is equivalent to the following command at the command line: + +~~~text +stack script --snapshot lts-22.28 -- MyScript.hs arg1 arg2 +RTS -s -RTS +~~~ + +where `+RTS -s -RTS` are some of GHC's +[runtime system (RTS) options](https://downloads.haskell.org/~ghc/latest/docs/users_guide/runtime_control.html). + +## Just-in-time compilation + +As with using [`stack script`](../commands/script_command.md) at the command +line, you can pass the `--compile` flag to make Stack compile the script, and +then run the compiled executable. Compilation is done quickly, without +optimization. To compile with optimization, pass the `--optimize` flag instead. +Compilation is done only if needed; if the executable already exists, and is +newer than the script, Stack just runs the executable directly. + +This feature can be good for speed (your script runs faster) and also for +durability (the executable remains runnable even if the script is disturbed, eg +due to changes in your installed GHC/snapshots, changes to source files during +git bisect, etc.) + +## Using multiple packages + +As with using [`stack script`](../commands/script_command.md) at the command +line, you can also specify multiple packages, either with multiple `--package` +options, or by providing a comma or space separated list. For example: + +~~~haskell +#!/usr/bin/env stack +{- stack script + --snapshot lts-22.28 + --package turtle + --package "stm async" + --package http-client,http-conduit +-} +~~~ + +## Stack configuration for scripts + +When using the [`stack script`](../commands/script_command.md) command, as when +using it at the command line, any project-level configuration file +(`stack.yaml`, by default) (including in the `global-project` directory in the +Stack root), including any specified by the options to the `stack script` +command itself, is ignored. + +!!! info + + Non-project level configuration options in global configuration files + (`config.yaml`), are not ignored by the + [`stack script`](../commands/script_command.md) command. Such options may be + useful if [`allow-newer`](../configure/yaml/non-project.md#allow-newer) + and/or + [`allow-newer-deps`](../configure/yaml/non-project.md#allow-newer-deps) + are required. + +When using the [`stack runghc`](../commands/runghc_command.md) command, as when +using it at the command line, if the current working directory is inside a +project, then that project's project-level configuration file is effective when +running the script. Otherwise the script uses the project-level configuration +file in the `global-project` directory in the Stack root. + +## Testing scripts + +You can use the flag `--script-no-run-compile` on the command line to enable (it +is disabled by default) the use of the `--no-run` option with +[`stack script`](../commands/script_command.md) (and forcing the `--compile` +option). The flag may help test that scripts compile in CI (continuous +integration). + +For example, consider the following simple script, in a file named `Script.hs`, +which makes use of the joke package +[`acme-missiles`](https://hackage.haskell.org/package/acme-missiles): + +~~~haskell +{- stack script + --snapshot lts-22.28 + --package acme-missiles +-} +import Acme.Missiles (launchMissiles) + +main :: IO () +main = launchMissiles +~~~ + +The command `stack --script-no-run-compile Script.hs` then behaves as if the +command +`stack script --snapshot lts-22.28 --package acme-missiles --no-run --compile -- Script.hs` +had been given. `Script.hs` is compiled (without optimisation) and the resulting +executable is not run: no missiles are launched in the process! + +## Writing independent and reliable scripts + +The [`stack script`](../commands/script_command.md) command will automatically: + +* Install GHC and libraries, if missing. + [`stack script`](../commands/script_command.md) behaves as if the + `--install-ghc` flag had been passed at the command line. +* Require that all packages used be explicitly stated on the command line. + +This ensures that your scripts are _independent_ of any prior deployment +specific configuration, and are _reliable_ by using exactly the same version of +all packages every time it runs so that the script does not break by +accidentally using incompatible package versions. + +In earlier versions of Stack, the +[`stack runghc`](../commands/runghc_command.md) command was used for scripts and +can still be used in that way. In order to achieve the same effect with the +[`stack runghc`](../commands/runghc_command.md) command, you can do the +following: + +1. Use the `--install-ghc` option to install the compiler automatically +2. Explicitly specify all packages required by the script using the `--package` + option. Use `-hide-all-packages` GHC option to force explicit specification + of all packages. +3. Use the `--snapshot` Stack option to ensure a specific GHC version and + package set is used. + +It is possible for a project-level configuration file to affect +[`stack runghc`](../commands/runghc_command.md). For that reason, +[`stack script`](../commands/script_command.md) is strongly recommended. For +those curious, here is an example with +[`stack runghc`](../commands/runghc_command.md): + +~~~haskell +#!/usr/bin/env stack +{- stack + runghc + --install-ghc + --snapshot lts-22.28 + --package base + --package turtle + -- + -hide-all-packages + -} +~~~ + +The [`stack runghc`](../commands/runghc_command.md) command is still useful, +especially when you're working on a project and want to access the package +databases and configurations used by that project. See the next section for more +information on configuration files. + +## Loading scripts in GHCi + +Sometimes you want to load your script in GHCi to play around with your program. +In those cases, you can use `exec ghci` option in the script to achieve +it. Here is an example: + +~~~haskell +#!/usr/bin/env stack +{- stack + exec ghci + --install-ghc + --snapshot lts-22.28 + --package turtle +-} +~~~
+ doc/topics/shell_autocompletion.md view
@@ -0,0 +1,70 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Shell auto-completion + +The following adds support for the tab completion of standard Stack arguments to +the following shell programs: Bash, Zsh (the Z shell) and fish. Completion of +file names and executables within Stack is still lacking. For further +information, see issue +[#823](https://github.com/commercialhaskell/stack/issues/832). + +!!! info + + Stack's completion library provides + [hidden options](https://github.com/pcapriotti/optparse-applicative#bash-zsh-and-fish-completions) + for Bash, Zsh, and fish which output commands used for shell + auto-completion. For example: + + ~~~bash + $ stack --bash-completion-script stack + _stack() + { + local CMDLINE + local IFS=$'\n' + CMDLINE=(--bash-completion-index $COMP_CWORD) + + for arg in ${COMP_WORDS[@]}; do + CMDLINE=(${CMDLINE[@]} --bash-completion-word $arg) + done + + COMPREPLY=( $(stack "${CMDLINE[@]}") ) + } + + complete -o filenames -F _stack stack + ~~~ + +=== "Bash" + + Add the output of the following command to your preferred completions file + (e.g. `~/.config/bash_completions.d/stack`). + + ~~~bash + stack --bash-completion-script $(which stack) + ~~~ + + You may need to `source` this. + +=== "Zsh" + + Add the output of the following command to your preferred completions file + (e.g. `~/.config/zsh/completions/_stack`). + + ~~~zsh + stack --zsh-completion-script $(which stack) + ~~~ + + You won't need to `source` this, but do update your `fpath`: + + ~~~zsh + fpath=($HOME/.config/zsh/completions $fpath) + autoload -U compinit && compinit + ~~~ + +=== "fish" + + Add the output of the following command to your preferred completions file + (e.g. `~/.config/fish/completions/stack.fish`). + + ~~~fish + stack --fish-completion-script $(which stack) + ~~~
+ doc/topics/snapshot_location.md view
@@ -0,0 +1,80 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://rawgit.com/commercialhaskell/stack/master/doc/img/hidden-warning.svg"></a></div> + +# Snapshot location + +[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) + +This document describes the specification of a snapshot location (in the + [`snapshot`](../configure/yaml/project.md#snapshot) or + [`resolver`](../configure/yaml/project.md#resolver) key). + +!!! info + + Stack uses the [Pantry](https://hackage.haskell.org/package/pantry) to + specify the location of snapshots. Pantry is geared towards reproducible + build plans with cryptographically secure specification of snapshots. + +There are essentially four different ways of specifying a snapshot location: + +1. Via a compiler version, which is a "compiler only" snapshot. This could be, + for example: + + ~~~yaml + snapshot: ghc-8.6.5 + ~~~ + +2. Via a URL pointing to a snapshot configuration file, for example: + + ~~~yaml + snapshot: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2018/8/21.yaml` + ~~~ + +3. Via a local file path pointing to a snapshot configuration file, for + example: + + ~~~yaml + snapshot: my-local-snapshot.yaml + ~~~ + +4. Via a _convenience synonym_, which provides a short form for some common + URLs. These are: + + * GitHub: `github:user/repo:path` is treated as: + + ~~~text + https://raw.githubusercontent.com/user/repo/master/path + ~~~ + + * LTS Haskell: `lts-X.Y` is treated (by default) as: + + ~~~text + github:commercialhaskell/stackage-snapshots:lts/X/Y.yaml + ~~~ + + * Stackage Nightly: `nightly-YYYY-MM-DD` is treated (by default) as: + + ~~~text + github:commercialhaskell/stackage-snapshots:nightly/YYYY/M/D.yaml + ~~~ + +!!! info + + By default, LTS Haskell and Stackage Nightly snapshot configurations are + retrieved from the `stackage-snapshots` GitHub repository of user + `commercialhaskell`. The + [snapshot-location-base](../configure/yaml/non-project.md#snapshot-location-base) + option allows a custom location to be set. + +For safer, more reproducible builds, you can optionally specify a URL +together with a cryptographic hash of its content. For example: + +~~~yaml +snapshot: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/12/0.yaml + size: 499143 + sha256: 781ea577595dff08b9c8794761ba1321020e3e1ec3297fb833fe951cce1bee11 +~~~ + +`size` is the number of bytes in the file and `sha256` is the file's SHA256 +hash. If not provided, the information will automatically be generated and +stored in a [lock file](lock_files.md).
+ doc/topics/stack_root.md view
@@ -0,0 +1,284 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Stack root + +The Stack root is a directory where Stack stores important files. + +On Unix-like operating systems and Windows, Stack can be configured to follow +the XDG Base Directory Specification if the environment variable `STACK_XDG` is +set to any non-empty value. However, Stack will ignore that configuration if the +Stack root location has been set on the command line or the `STACK_ROOT` +environment variable exists. + +## Location + +The location of the Stack root depends on the operating system, whether Stack is +configured to use the XDG Base Directory Specification, and/or whether an +alternative location to Stack's default 'programs' directory has been specified. + +The location of the Stack root can be configured by setting the +[`STACK_ROOT`](../configure/environment_variables.md#stack_root) environment +variable or using Stack's +[`--stack-root`](../configure/global_flags.md#stack-root-option) option on the +command line. + +=== "Unix-like" + + The Stack root contains snapshot packages; (by default) tools such as GHC, + in a `programs` directory; Stack's global + [configuration](../configure/yaml-configuration.md) file + (`config.yaml`); and Stack's + [`global-projects`](../configure/yaml-configuration.md) directory. + + The default Stack root is `~/.stack`. + +=== "Windows" + + The default Stack root is `%APPDIR%\stack`. + + If the `LOCALAPPDATA` environment variable exists, then the default location + of tools is `%LOCALAPPDATA%\Programs\stack`. Otherwise, it is the `programs` + directory in the Stack root. + + !!! warning + + If there is a space character in the `%LOCALAPPDATA%` path (which may be + the case if the relevant user account name and its corresponding user + profile path have a space) this may cause problems with building + packages that make use of the GNU project's `autoconf` package and + `configure` shell script files. That may be the case particularly if + there is no corresponding short name ('8 dot 3' name) for the directory + in the path with the space (which may be the case if '8 dot 3' names + have been stripped or their creation not enabled by default). If there + are problems building, it will be necessary to override the default + location of Stack's 'programs' directory to specify an alternative path + that does not contain space characters. Examples of packages on + Hackage that make use of `configure` are `network` and `process`. + + On Windows, the length of filepaths may be limited (to + [MAX_PATH](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd)), + and things can break when this limit is exceeded. Setting a Stack root with + a short path to its location (for example, `C:\sr`) can help. + +=== "XDG Base Directory Specification" + + The Stack root is `<XDG_DATA_HOME>/stack`. If the `XDG_DATA_HOME` + environment variable does not exist, the default is `~/.local/share/stack` + on Unix-like operating systems and `%APPDIR%\stack` on Windows. + + The location of `config.yaml` is `<XDG_CONFIG_HOME>/stack`. If the + `XDG_CONFIG_HOME` environment variable does not exist, the default is + `~/.config/stack` on Unix-like operating systems and `%APPDIR%\stack` on + Windows. + + This approach treats: + + * the project-level configuration file that is common to all projects + without another such file in their project directory or its ancestor + directories as _data_ rather than as part of Stack's own + _configuration_; + + * the snapshots database as essential data rather than as non-essential + data that would be part of a _cache_, notwithstanding that Stack will + rebuild that database as its contents are needed; and + + * the Pantry store as essential data rather than as non-essential data + that would be part of a _cache_, notwithstanding that Stack will + download the package index and rebuild the store if it is absent. + +An alternative to the default location of tools such as GHC can be specified +with the +[`local-programs-path`](../configure/yaml/non-project.md#local-programs-path) +configuration option. + +The location of the Stack root is reported by command: + +~~~text +stack path --stack-root +~~~ + +The full path of Stack's global configuration file is reported by command: + +~~~text +stack path --global-config +~~~ + +The location of tools such as GHC for the current platform is reported by +command: + +~~~text +stack path --programs +~~~ + +## Contents + +The contents of the Stack root depend on the operating system, whether Stack is +configured to use the XDG Base Directory Specification, and/or whether an +alternative location to Stack's default 'programs' directory has been specified. + +=== "Unix-like" + + The Stack root contains snapshot packages; (by default) tools such as GHC, + in a `programs` directory; Stack's global + [configuration](../configure/yaml-configuration.md) file + (`config.yaml`); and Stack's + [`global-projects`](../configure/yaml-configuration.md) directory. + +=== "Windows" + + The Stack root contains snapshot packages; Stack's global + [configuration](../configure/yaml-configuration.md) file (`config.yaml`); + and Stack's [`global-projects`](../configure/yaml-configuration.md) + directory. The default location of tools such as GHC and MSYS2 is outside of + the Stack root. + +=== "XDG Base Directory Specification" + + If Stack is following the XDG Base Directory Specification, the Stack root + contains what it would otherwise contain for the operating system, but + Stack's global configuration file (`config.yaml`) may be located elsewhere. + +### `config.yaml` + +This is Stack's global configuration file. For further information, see the +documentation for non-project specific +[configuration](../configure/yaml/non-project.md#non-project-specific-configuration). + +If the file is deleted, and Stack needs to consult it, then Stack will create a +file with default contents. + +### `stack.sqlite3` + +This is a 'user' database that Stack uses to cache certain information. The +associated lock file is `stack.sqlite3.pantry-write-lock`. + +### `.stack-work` directory (optional) + +Stack can build when there is no project-level configuration file (including one +in the `global-project` directory of the Stack root); for example, as a result +of a [`stack script`](../commands/script_command.md) command (at the command +line or in a [Stack interpreter options comment](scripts.md) in a Haskell script +file). When it does so, the directory corresponding to a project directory is +the Stack root. Stack will create its work directory, named `.stack-work` by +default, in the Stack root. + +If the work directory is deleted, and Stack needs that work directory, then +Stack will recreate it. + +### `global-project` directory + +This contains: + +* an explanation of the directory (`README.txt`); +* the project-level configuration file (`stack.yaml`) for the global project + and its associated lock file (`stack.yaml.lock`); and +* if created, Stack's working directory (`.stack-work`) for the global project. + +If the project-level configuration file is deleted, and Stack needs to consult +it, then Stack will recreate the contents of the directory. + +### `pantry\hackage` directory + +This contains a local cache of the package index. If the contents of the +directory are deleted, and Stack needs to consult the package index, then Stack +will seek to download the latest package index. + +!!! info + + Stack depends on package `pantry` which, in turn, depends on package + `hackage-security`. The latter handles the local cache of the package index. + The type `CacheLayout` represents the location of the files that are cached. + `pantry` uses `cabalCacheLayout :: CacheLayout`, the layout that Cabal (the + tool) uses. That is what specifies the names of the files used to cache the + package index, including `00-index.tar` and `00-index.tar.gz`. + +### `pantry` directory + +This contains: + +* the Pantry database used by Stack (`pantry.sqlite3`) and its associated lock + file (`pantry.sqlite2.pantry-write-lock`). If the database is deleted, and + Stack needs to consult it, then Stack will seek to create and initialise it. + The database is initialised with information from the package index; and +* a database of package versions that come with each version of GHC + (`global-hints-cache.yaml`). + +### `programs` directory + +This contains a directory for the platform. That directory contains for each +installed Stack-supplied tool: + +* the archive file for the tool. This can be deleted; +* a file indicating the tool is installed (`<tool_name>.installed`); and +* a directory for the tool. + +To remove a Stack-supplied tool, delete all of the above. If Stack needs a +Stack-supplied tool and it is unavailable, then Stack will seek to obtain it. + +### `scripts` directory (optional) + +If the `--compile` or `--optimize` and `--use-root` flags are used with the +[`stack script`](../commands/script_command.md) command, then this contains: + +* script-specific locations, each containing all the compilation outputs + (inclduing the executable) generated by the command. + +If the `scripts` directory, or a script-specific location within it, is deleted, +and Stack needs that directory, then Stack will recreate it. + +### `setup-exe-cache` directory + +This contains a directory for the platform. That directory contains, for each +version of GHC (an associated version of Cabal (the library)) that Stack has +used, an executable that Stack uses to access Cabal (the library). + +If the contents of the directory are deleted, and Stack needs the executable, +then Stack will seek to rebuild it. + +### `setup-exe-src` directory + +See the documentation for the +[`setup-exe-cache` directory](#setup-exe-cache-directorysetup-exe-cache). This +contains the two source files (`setup-<hash>.hs` and `setup-shim-<hash>.hs`) +that Stack uses to build the executable. + +If the contents of the directory are deleted, and Stack needs the executable, +then Stack will recreate them. + +The hash in the names of the source files is a hash of arguments passed to GHC +when building the executable and the contents of the two source files. + +The content of the `setup-<hash>.hs` file is the familiar: + +~~~haskell +import Distribution.Simple +main = defaultMain +~~~ + +The content of the `setup-shim-<hash>.hs` file uses `main` except when the +executable is called with arguments `repl` and `stack-initial-build-steps`. Then +Stack uses Cabal (the library) to create the autogenerated files for every +configured component. Stack's `stack ghci` or `stack repl` commands call the +executable with those arguments. + +### `snapshots` directory + +This contains a directory for each snapshot that Stack creates when building +immutable dependencies of projects. + +If the contents of the directory are deleted, and the snapshot is not available +to Stack when it builds, then Stack will recreate the snapshot. + +### `templates` directory + +This contains a `.hsfile` for each project template that Stack has used. For +further information, see the +[`stack templates`](../commands/templates_command.md) command documentation. + +If the contents of the directory are deleted, an Stack needs a project template, +then Stack will seek to download the template. + +### `upload` directory + +This may contain saved credentials for uploading packages to Hackage +(`credentials.json`).
+ doc/topics/stack_work.md view
@@ -0,0 +1,148 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Stack work directories + +Stack work directories are directories within a local project or package +directory in which Stack stores files created during the build process. Stack +can be used without an understanding of the content of those directories. In +particular, the [`stack exec`](../commands/exec_command.md) command sets up an +environment where relevant subdirectories of the project Stack work directory +are on the PATH. + +## Naming + +By default, Stack work directories are named `.stack-work`. The name can be +overidden by: + +* the use of the + [`STACK_WORK` environment variable](../configure/environment_variables.md#stack_work); +* the [`work-dir`](../configure/yaml/non-project.md#work-dir) non-project + specific configuration option; or +* the [`--work-dir`](../configure/global_flags.md#-work-dir-option) command line + option. + +Given the location of Stack work directories, the name of the work directories +must be a relative path to a directory. + +## Location + +If the work directory does not already exist, it will be created by the +[`stack build`](../commands/build_command.md) command as a subdirectory of each +project package directory and, if different, the project directory. + +## Project package Stack work directory + +The Stack work directory for a project package will contain a `dist` directory. +This directory will contain a path to a directory containing: + +* a `build` directory; +* a `package.conf.inplace` directory; +* a `stack-build-caches` directory; +* a `build-lock` file; +* a `setup-config` file; +* a `stack-cabal-mod` file. This file is used by Stack only for its modification + time; +* a `stack-project-root` file. This file contains an absolute path to the + project root directory; and +* a `stack-setup-config-mod` file. This file is used by Stack only for its + modification time. + +The directory, relative to the project package directory or the project +directory, is the one reported by +[`stack path --dist-dir`](../commands/path_command.md). + +=== "Unix-like" + + On Unix-like operating systems, the path to the directory is a directory + named after the platform (including Stack's classification of variants of + Linux distributions) followed by a directory named after the GHC version. + +=== "Windows" + + On Windows, the path to the directory is an eight-character hash of the + path that applies on Unix-like operating systems. + +## Project Stack work directory + +The Stack work directory for a project will contain a `install` directory. +This directory will contain a path to a directory containing: + +* a `bin` directory, containing built executable files; +* a `doc` directory, containing a directory for each project package. This is + the directory reported by + [`stack path --local-doc-root`](../commands/path_command.md); +* if the [`stack hpc`](hpc_command.md) command is used, a `hpc` directory. This + is the directory reported by + [`stack path --local-hpc-root`](../commands/path_command.md); +* a `lib` directory, containing a directory named after the platform and the + GHC version and, within that, a directory for each project package; +* a `pkgdb` directory. This is the directory reported by + [`stack path --local-pkg-db`](../commands/path_command.md); +* a `stack.sqlite3` file; and +* a `stack.sqlite3.pantry-write-lock` file. + +The directory is the one reported by +[`stack path --local-install-root`](../commands/path_command.md). + +=== "Unix-like" + + On Unix-like operating systems, the path to the directory is a directory + named after the platform (including Stack's classification of variants of + Linux distributions) followed by a directory named after a SHA 256 hash + (see further below) followed by a directory named after the version number + of GHC. + + The SHA 256 hash is a hash of the following information: + + * the path to the specified compiler; + * the information about the compiler provided by `ghc --info`; + * the options that Stack passes to GHC for package that is not a project + package; and + * information about the immutable dependencies: their location, whether or + not Haddock documentation is to be built, their flags, their GHC options, + and their Cabal configuration options. + + The options that Stack passes to GHC for a package that is not a project + package depend on: + + * the specification of + [profiling](https://docs.haskellstack.org/en/stable/build_command/#flags-affecting-ghcs-behaviour); + * the specification of + [stripping](https://docs.haskellstack.org/en/stable/build_command/#flags-affecting-ghcs-behaviour); and + * if + [`apply-ghc-options: everything`](../configure/yaml/non-project.md#apply-ghc-options) + is specified, any GHC command line options specified on the command line. + + !!! note + + As a consequence, the path reported by the following commands will + differ (and similarly for the paths established by the + [`stack exec`](../commands/exec_command.md) command): + + ~~~text + stack path --local-install-root + stack --profile path --local-install-root + stack --no-strip path --local-install-root + stack --profile --no-strip path --local-install-root + ~~~ + +=== "Windows" + + On Windows, the path to the directory is an eight-character hash of the + path that applies on Unix-like operating systems. + +Following a `stack ghci` or `stack repl` command, the Stack work directory for +a project will contain a `ghci` directory. This directory will contain paths to +`cabal_macos.h` files that are generated automatically by Cabal. + +!!! note + + Haskell Language Server makes use of the `stack ghci` command to obtain + information. + +If the [`stack hoogle`](../commands/hoogle_command.md) command is used, the +Stack work directory for a project will contain a `hoogle` directory. This +directory will contain a directory being the one reported by +[`stack path --local-hoogle-root`](../commands/path_command.md). The naming of +the path to the directory is same as for the path to the directory in the +`install` directory.
+ doc/topics/stack_yaml_vs_cabal_package_file.md view
@@ -0,0 +1,162 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# stack.yaml versus package.yaml versus a Cabal file + +What is the difference between a `stack.yaml` file, a `package.yaml` file and a +Cabal file (named `<package_name>.cabal`)? This page aims to make that clear. + +In short: + +* `stack.yaml` contains project-level configuration for Stack, and may contain + project-specific options and non-project-specific options. + +* `package.yaml` contains a description of a package in the + [Hpack](https://github.com/sol/hpack) format. Hpack, including Stack's + built-in version, uses the file to create a Cabal file. + +* a Cabal file also contains a description of a package, but in the format used + by Cabal. + +## package.yaml versus a Cabal file + +Why two different formats to describe packages? Hpack is considered to have some +advantages over the underlying Cabal format, which are explained its project +repository. They include that the Hpack format supports YAML syntax and the +automatic generation of the lists of `exposed-modules` used in the Cabal format. + +The remainder of this page will focus on the difference between a `stack.yaml` +file and a package description file. + +## Package versus project + +Stack is a tool for building Haskell code and it uses Cabal, a build system. +Cabal defines the concept of a _package_. A package has: + +* A name and version +* optionally, one library +* optionally, one or more executables +* A Cabal file (or, as mentioned above, an [Hpack](https://github.com/sol/hpack) + `package.yaml` file that generates a Cabal file) +* And a bunch more + +There is a one-to-one correspondence between a package and a Cabal file. + +Stack defines a new concept called a _project_. A project has: + +* A snapshot _resolver_ (more on this later) +* Extra dependencies on top of the snapshot +* Optionally, one or more local Cabal packages +* Flag and GHC options configurations +* And a bunch more Stack configuration + +Often you will have a project that defines only one local Cabal package that you +are working on. If you need to specify a dependency, a source of confusion can +be why you need to specify it both in the `stack.yaml` file _and_ +in the Cabal file. To explain, let's take a quick detour to talk about snapshots +and how Stack resolves dependencies. + +## Snapshots and resolvers + +Stack follows a rule that says, for any project, there is precisely one version +of each package available. Obviously, for many packages there are _many_ +versions available in the world. But when resolving a `stack.yaml` file, Stack +requires that you have chosen a specific version for each package available. + +The most common means by which this set of packages is defined is via a +snapshot provided by Stackage. For example, if you go to the page +<https://www.stackage.org/lts-22.28>, you will see a list of 3,373 packages at +specific version numbers. When you then specify `snapshot: lts-22.28` or, +alternatively, `resolver: lts-22.28`, you're telling Stack to use those package +versions in resolving dependencies down to specific versions of packages. + +Sometimes a snapshot doesn't have all of the packages that you want. Or you want +a different version of a package. Or you want to work on a local modification of +a package. In all of those cases, you can add more configuration data to your +`stack.yaml` file to override the values it received from your +[`snapshot`](../configure/yaml/project.md#snapshot) or +[`resolver`](../configure/yaml/project.md#resolver) setting. At the end of the +day, each of your projects will end up with some way of resolving a package name +into a specific version of that package. + +## Why specify dependencies twice? + +The package `acme-missiles` is not included in any Stackage snapshots. When you +add something like this to your `stack.yaml` file: + +~~~yaml +extra-deps: +- acme-missiles-0.3 +~~~ + +what you're saying to Stack is: "if at any point you find that you need to build +the `acme-missiles` package, please use version `0.3`". You are _not_ saying +"please build `acme-missiles` now." You are also not saying "my package depends +on `acme-missiles`." You are simply making it available should the need arise. + +When you add to your `package.yaml` file: + +~~~yaml +dependencies: +- acme-missiles +~~~ + +or, alternatively, you add directly to your Cabal file: + +~~~yaml +build-depends: acme-missiles +~~~ + +you're saying "this package requires that `acme-missiles` be available." Since +`acme-missiles` doesn't appear in your snapshot, without also modifying your +`stack.yaml` to mention it via `extra-deps`, Stack will complain about the +dependency being unavailable. + +You may challenge: but why go through all of that annoyance? Stack knows what +package I want, why not just go grab it? The answer is that, if Stack just +grabbed `acme-missiles` for you without it being specified in the `stack.yaml` +somehow, you'd lose reproducibility. How would Stack know which version to use? +It may elect to use the newest version, but if a new version is available in +the future, will it automatically switch to that? + +Stack's core philosophy is that build plans are always reproducible. The +purpose of the `stack.yaml` file is to define an immutable set of packages. No +matter when in time you use it, and no matter how many new release happen in +the interim, the build plan generated should be the same. + +(There is, however, at least one hole in this theory today, which is Hackage +revisions. When you specify `extra-deps: [acme-missiles-0.3]`, it doesn't +specify which revision of the Cabal file to use, and Stack will just choose the +latest. Stack has the ability to specify exact revisions of Cabal files, but +this isn't enforced as a requirement, because it is so different from the way +most people work with packages.) + +And now, how about the other side: why doesn't Stack automatically add +`acme-missiles` to `build-depends` in your Cabal file if you add it as an +extra-dep? There are a surprising number reasons for this: + +* The Cabal specification doesn't support anything like that +* There can be multiple packages in a project, and how do we know which package + actually needs the dependency? +* There can be multiple components (libraries, executable, etc) in a package, + and how do we know which of those actually needs the dependency? +* The dependency may only be conditionally needed, based on flags, operating + system, or architecture. As an extreme example, we wouldn't want a Linux-only + package to be built by force on Windows. + +While for simple use cases it seems like automatically adding dependencies from +the Cabal file to the `stack.yaml` file or vice-versa would be a good thing, it +breaks down immediately for any semi-difficult case. Therefore, Stack requires +you to add it to both places. + +And a final note, in case it wasn't clear. The example above used +`acme-missiles`, which is not in Stackage snapshots. If, however, you want to +depend on a package already present in the snapshot you've selected, there's no +need to add it explicitly to your `stack.yaml` file: it's already there +implicitly via the `snapshot` setting. This is what you do the majority of the +time, such as when you add `vector` or `mtl` as a `build-depends` value. + +## Should I check-in automatically generated Cabal files? + +Yes, you should. This recommendation was changed in +[issue #5210](https://github.com/commercialhaskell/stack/issues/5210). Please +see the discussion there.
+ doc/topics/travis_ci.md view
@@ -0,0 +1,182 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Travis CI + +This page documents how to use Stack on +[Travis CI](https://travis-ci.org/). We assume you have basic +familiarity with Travis. We provide two fully baked example files +ready to be used on your projects: + +* [The simple Travis configuration](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/resources/travis-simple.yml) + is intended for applications that do not require multiple GHC + support or cross-platform support. It builds and tests your project + with just the settings present in your `stack.yaml` file. +* [The complex Travis configuration](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/resources/travis-complex.yml) + is intended for projects that need to support multiple GHC versions + and multiple OSes, such as open source libraries to be released to + Hackage. It tests against cabal-install, as well as Stack on Linux + and macOS. The configuration is significantly more involved to allow + for all of this branching behavior. + + !!! note + It is likely going to be necessary to modify this configuration to match + the needs of your project, such as tweaking the build matrix to alter + which GHC versions you test against, or to specify GHC-version-specific + `stack.yaml` files if necessary. Don't be surprised if it doesn't work + the first time around. See the multiple GHC section below for more + information. + +Each of these configurations is ready to be used immediately, just +copy-paste the content into the `.travis.yml` file in the root or your +repo, enable Travis on the repo, and you're good to go. + +You may also be interested in using AppVeyor, which supports Windows +builds, for more cross-platform testing. There's a +[short blog post available on how to do this](http://www.snoyman.com/blog/2016/08/appveyor-haskell-windows-ci), +or just copy in +[the appveyor.yml file](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/resources/appveyor.yml) + +The rest of this document explains the details of common Travis +configurations for those of you who want to tweak the above +configuration files or write your own. + +*Note:* both Travis and Stack infrastructures are actively developed. We try to + document best practices at the moment. + +## Container infrastructure + +For Stack on Travis to be practical, we must use caching. Otherwise build times +will take an incredibly long time, about 30 minutes versus 3-5. Caching is +currently available only for +[container-based Travis infrastructure](http://docs.travis-ci.com/user/workers/container-based-infrastructure/). +Shortly we have to add + +~~~yaml +sudo: false + +# Caching so the next build will be fast too. +cache: + directories: + - $HOME/.stack +~~~ + +To the `.travis.yml`. This however restricts how we can install GHC and Stack on +the Travis machines. + +## Installing Stack + +Currently there is only one reasonable way to install Stack: fetch precompiled +binary from the GitHub. + +~~~yaml +before_install: +# Download and unpack the stack executable +- mkdir -p ~/.local/bin +- export PATH=$HOME/.local/bin:$PATH +- travis_retry curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' +~~~ + +## Installing GHC + +There are two ways to install GHC: + +- Let Stack download GHC +- Install GHC using [apt plugin](http://docs.travis-ci.com/user/apt/) + +See the above scripts for an example of the first option (letting Stack +download GHC). Here, we will explain the second option. With single GHC the +situation is simple: + +~~~yaml +before_install: + # Install stack as above + # ... + # Configure stack to use the system GHC installation + - stack config set system-ghc --global true + - export PATH=/opt/ghc/7.10.2/bin:$PATH + +addons: + apt: + sources: + - hvr-ghc + packages: + - ghc-7.10.2 +~~~ + +### Multiple GHC - parametrised builds + +Travis apt plugin doesn't yet support installing apt packages dynamically +(https://github.com/travis-ci/travis-ci/issues/4291). That for we need to write +a bit repetitive `.travis.yml`. + +Also for different GHC versions, you probably want to use different `stack.yaml` +files. + +~~~yaml +# N.B. No top-level env: declaration! + +matrix: + include: + - env: GHCVER=7.8.4 STACK_YAML=stack.yaml + addons: + apt: + sources: + - hvr-ghc + packages: + - ghc-7.8.4 + - env: GHCVER=7.10.1 STACK_YAML=stack-7.10.yaml + addons: + apt: + sources: + - hvr-ghc + packages: + - ghc-7.10.1 + - env: GHCVER=head STACK_YAML=stack-head.yaml + addons: + apt: + sources: + - hvr-ghc + packages: + - ghc-head + allow_failures: + - env: GHCVER=head STACK_YAML=stack-head.yaml + +before_install: + # ghc + - export PATH=/opt/ghc/$GHCVER/bin:$PATH +~~~ + +Especially to use ghc `HEAD` you need to pass `--skip-ghc-check` option to Stack. + +## Running tests + +After the environment setup, actual test running is simple: + +~~~yaml +script: + - stack --no-terminal --skip-ghc-check test +~~~ + +In case you're wondering: we need `--no-terminal` because stack does some fancy +sticky display on smart terminals to give nicer status and progress messages, +and the terminal detection is broken on Travis. + +## Other details + +Some Stack commands will run for long time (when cache is cold) without +producing any output. To avoid timeouts, use the built in [travis_wait](https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received). + + +~~~yaml +install: + - travis_wait stack --no-terminal --skip-ghc-check setup + - travis_wait stack --no-terminal --skip-ghc-check test --only-snapshot +~~~ + +## Examples + +- [futurice/fum2github](https://github.com/futurice/fum2github/blob/master/.travis.yml) +- [haskell-distributed/cloud-haskell](https://github.com/haskell-distributed/cloud-haskell/blob/master/.travis.yml) +- [simonmichael/hledger](https://github.com/simonmichael/hledger/blob/master/.travis.yml) +- [fpco/wai-middleware-crowd](https://github.com/fpco/wai-middleware-crowd/blob/master/.travis.yml) +- [commercialhaskell/all-cabal-hashes-tool](https://github.com/commercialhaskell/all-cabal-hashes-tool/blob/master/.travis.yml)
− doc/travis_ci.md
@@ -1,182 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Travis CI - -This page documents how to use Stack on -[Travis CI](https://travis-ci.org/). We assume you have basic -familiarity with Travis. We provide two fully baked example files -ready to be used on your projects: - -* [The simple Travis configuration](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/travis-simple.yml) - is intended for applications that do not require multiple GHC - support or cross-platform support. It builds and tests your project - with just the settings present in your `stack.yaml` file. -* [The complex Travis configuration](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/travis-complex.yml) - is intended for projects that need to support multiple GHC versions - and multiple OSes, such as open source libraries to be released to - Hackage. It tests against cabal-install, as well as Stack on Linux - and macOS. The configuration is significantly more involved to allow - for all of this branching behavior. - - !!! note - It is likely going to be necessary to modify this configuration to match - the needs of your project, such as tweaking the build matrix to alter - which GHC versions you test against, or to specify GHC-version-specific - `stack.yaml` files if necessary. Don't be surprised if it doesn't work - the first time around. See the multiple GHC section below for more - information. - -Each of these configurations is ready to be used immediately, just -copy-paste the content into the `.travis.yml` file in the root or your -repo, enable Travis on the repo, and you're good to go. - -You may also be interested in using AppVeyor, which supports Windows -builds, for more cross-platform testing. There's a -[short blog post available on how to do this](http://www.snoyman.com/blog/2016/08/appveyor-haskell-windows-ci), -or just copy in -[the appveyor.yml file](https://raw.githubusercontent.com/commercialhaskell/stack/stable/doc/appveyor.yml) - -The rest of this document explains the details of common Travis -configurations for those of you who want to tweak the above -configuration files or write your own. - -*Note:* both Travis and Stack infrastructures are actively developed. We try to - document best practices at the moment. - -## Container infrastructure - -For Stack on Travis to be practical, we must use caching. Otherwise build times -will take an incredibly long time, about 30 minutes versus 3-5. Caching is -currently available only for -[container-based Travis infrastructure](http://docs.travis-ci.com/user/workers/container-based-infrastructure/). -Shortly we have to add - -~~~yaml -sudo: false - -# Caching so the next build will be fast too. -cache: - directories: - - $HOME/.stack -~~~ - -To the `.travis.yml`. This however restricts how we can install GHC and Stack on -the Travis machines. - -## Installing Stack - -Currently there is only one reasonable way to install Stack: fetch precompiled -binary from the GitHub. - -~~~yaml -before_install: -# Download and unpack the stack executable -- mkdir -p ~/.local/bin -- export PATH=$HOME/.local/bin:$PATH -- travis_retry curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' -~~~ - -## Installing GHC - -There are two ways to install GHC: - -- Let Stack download GHC -- Install GHC using [apt plugin](http://docs.travis-ci.com/user/apt/) - -See the above scripts for an example of the first option (letting Stack -download GHC). Here, we will explain the second option. With single GHC the -situation is simple: - -~~~yaml -before_install: - # Install stack as above - # ... - # Configure stack to use the system GHC installation - - stack config set system-ghc --global true - - export PATH=/opt/ghc/7.10.2/bin:$PATH - -addons: - apt: - sources: - - hvr-ghc - packages: - - ghc-7.10.2 -~~~ - -### Multiple GHC - parametrised builds - -Travis apt plugin doesn't yet support installing apt packages dynamically -(https://github.com/travis-ci/travis-ci/issues/4291). That for we need to write -a bit repetitive `.travis.yml`. - -Also for different GHC versions, you probably want to use different `stack.yaml` -files. - -~~~yaml -# N.B. No top-level env: declaration! - -matrix: - include: - - env: GHCVER=7.8.4 STACK_YAML=stack.yaml - addons: - apt: - sources: - - hvr-ghc - packages: - - ghc-7.8.4 - - env: GHCVER=7.10.1 STACK_YAML=stack-7.10.yaml - addons: - apt: - sources: - - hvr-ghc - packages: - - ghc-7.10.1 - - env: GHCVER=head STACK_YAML=stack-head.yaml - addons: - apt: - sources: - - hvr-ghc - packages: - - ghc-head - allow_failures: - - env: GHCVER=head STACK_YAML=stack-head.yaml - -before_install: - # ghc - - export PATH=/opt/ghc/$GHCVER/bin:$PATH -~~~ - -Especially to use ghc `HEAD` you need to pass `--skip-ghc-check` option to Stack. - -## Running tests - -After the environment setup, actual test running is simple: - -~~~yaml -script: - - stack --no-terminal --skip-ghc-check test -~~~ - -In case you're wondering: we need `--no-terminal` because stack does some fancy -sticky display on smart terminals to give nicer status and progress messages, -and the terminal detection is broken on Travis. - -## Other details - -Some Stack commands will run for long time (when cache is cold) without -producing any output. To avoid timeouts, use the built in [travis_wait](https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received). - - -~~~yaml -install: - - travis_wait stack --no-terminal --skip-ghc-check setup - - travis_wait stack --no-terminal --skip-ghc-check test --only-snapshot -~~~ - -## Examples - -- [futurice/fum2github](https://github.com/futurice/fum2github/blob/master/.travis.yml) -- [haskell-distributed/cloud-haskell](https://github.com/haskell-distributed/cloud-haskell/blob/master/.travis.yml) -- [simonmichael/hledger](https://github.com/simonmichael/hledger/blob/master/.travis.yml) -- [fpco/wai-middleware-crowd](https://github.com/fpco/wai-middleware-crowd/blob/master/.travis.yml) -- [commercialhaskell/all-cabal-hashes-tool](https://github.com/commercialhaskell/all-cabal-hashes-tool/blob/master/.travis.yml)
+ doc/tutorial/building_existing_projects.md view
@@ -0,0 +1,139 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 3. Building existing projects + +Alright, enough playing around with simple projects. Let's take an open source +package and try to build it. We'll be ambitious and use +[yackage](https://hackage.haskell.org/package/yackage), a local package server +using [Yesod](http://www.yesodweb.com/). To get the code, we'll use the +`stack unpack` command from the root directory for all our Haskell projects: + +~~~text +stack unpack yackage +Unpacked yackage-0.8.1 to <root_directory>/yackage-0.8.1/ +~~~ + +You can also unpack to the directory of your liking instead of the current one +by issuing the command: + +~~~text +stack unpack yackage --to <desired_directory> +~~~ + +This will create a `yackage-0.8.1` directory inside `<desired_directory>`. + +We will change to that directory, with the command: + +~~~text +cd yackage-0.8.1 +~~~ + +## The `stack init` command + +This new directory does not have a `stack.yaml` file, so we need to make one +first. We could do it by hand, but let's be lazy instead with the `stack init` +command: + +~~~text +stack init +# init output ... +~~~ + +`stack init` does quite a few things for you behind the scenes: + +* Finds all of the Cabal files in your current directory and subdirectories + (unless you use `--ignore-subdirs`) and determines the packages and versions + they require +* Finds the best combination of snapshot and package flags that allows + everything to compile with minimum external dependencies +* It tries to look for the best matching snapshot from latest LTS, latest + nightly, other LTS versions in that order + +Assuming it finds a match, it will write your `stack.yaml` file, and everything +will work. + +!!! note + + The `yackage` package does not currently support Hpack, but you can also use + `hpack-convert` should you need to generate a `package.yaml` file. + +### Excluded Packages + +Sometimes multiple packages in your project may have conflicting requirements. +In that case `stack init` will fail, so what do you do? + +You could manually create `stack.yaml` by omitting some packages to resolve the +conflict. Alternatively you can ask `stack init` to do that for you by +specifying `--omit-packages` flag on the command line. Let's see how that +works. + +To simulate a conflict we will use `acme-missiles-0.3` in `yackage` and we will +also copy `yackage.cabal` to another directory and change the name of the file +and package to `yackage-test`. In this new package we will use +`acme-missiles-0.2` instead. Let's see what happens when we command `stack init` +again: + +~~~text +stack init --force --omit-packages +# init failure output ... +~~~ + +Looking at `stack.yaml`, you will see that the excluded packages have been +commented out under the `packages` field. In case wrong packages are excluded +you can uncomment the right one and comment the other one. + +Packages may get excluded due to conflicting requirements among user packages or +due to conflicting requirements between a user package and the snapshot +compiler. If all of the packages have a conflict with the compiler then all of +them may get commented out. + +When packages are commented out you will see a warning every time you run a +command which needs the configuration file. The warning can be disabled by +editing the configuration file and removing it. + +### Using a specific snapshot + +Sometimes you may want to use a specific snapshot for your project instead of +`stack init` picking one for you. You can do that by using +`stack init --snapshot <snapshot>`. + +You can also init with a compiler snapshot if you do not want to use a +Stackage snapshot. That will result in all of your project's dependencies being +put under the `extra-deps` section. + +### Installing the compiler + +Stack will automatically install the compiler when you run `stack build` but you +can manually specify the compiler by running `stack setup <GHC-VERSION>`. + +### Miscellaneous and diagnostics + +_Add selected packages_: If you want to use only selected packages from your +project directory you can do so by explicitly specifying the package directories +on the command line. + +_Duplicate package names_: If multiple packages under the directory tree have +same name, `stack init` will report those and automatically ignore one of them. + +_Ignore subdirectories_: By default `stack init` searches all the subdirectories +for Cabal files. If you do not want that then you can use `--ignore-subdirs` +command line switch. + +_Cabal warnings_: `stack init` will show warnings if there were issues in +reading a Cabal file. You may want to pay attention to the warnings as sometimes +they may result in incomprehensible errors later on during dependency solving. + +_Package naming_: If the `Name` field defined in a Cabal file does not match +with the Cabal file name then `stack init` will refuse to continue. + +_User warnings_: When packages are excluded or external dependencies added Stack +will show warnings every time the configuration file is loaded. You can suppress +the warnings by editing the configuration file and removing the warnings from +it. You may see something like this: + +~~~text +stack build +Warning: Some packages were found to be incompatible with the resolver and have been left commented out in the packages section. +Warning: Specified resolver could not satisfy all dependencies. Some external packages have been added as dependencies. +You can suppress this message by removing it from stack.yaml +~~~
+ doc/tutorial/building_your_project.md view
@@ -0,0 +1,332 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 2. Building your project + +The [`stack build`](../commands/build_command.md) command is the heart of Stack. +It is the engine that powers building your code, testing it, getting +dependencies, and more. Much of the remainder of this getting started guide will +cover its features. + +!!! note + + Using the `build` command twice with the same options and arguments should + generally do nothing (besides things like rerunning test suites), and + should, in general, produce a reproducible result between different runs. + +## Adding dependencies + +A Haskell package often depends on code exposed by other Haskell packages. + +Let's say we decide to modify our existing `helloworld` package source code to +use a new library, the one provided by the +[`text`](https://hackage.haskell.org/package/text) package. + +We can modify `src/Lib.hs` so that its contents are as follows (click +:material-plus-circle: to learn more): + +~~~haskell +{-# LANGUAGE OverloadedStrings #-} -- (1)! + +module Lib + ( someFunc + ) where + +import qualified Data.Text.IO as T -- (2)! + +someFunc :: IO () +someFunc = T.putStrLn "someFunc" --(3)! +~~~ + +1. Enables overloaded string literals. String literals now have type + `(IsString a) => a`. + +2. The module is exposed by the library of the `text` package. + +3. `Data.Text.IO.putStrLn :: Text -> IO ()`. + +If we command: + +~~~text +stack build +~~~ + +Stack will report Stack error [S-7282] during the build, with output like the +following: + +~~~text +... +Building library for helloworld-0.1.0.0.. +[1 of 2] Compiling Lib [Source file changed] + +src\Lib.hs:7:1: error: + Could not load module ‘Data.Text.IO’ + It is a member of the hidden package ‘text-2.0.2’. + Perhaps you need to add ‘text’ to the build-depends in your .cabal file. + Use -v (or `:set -v` in ghci) to see a list of the files searched for. + | +7 | import qualified Data.Text.IO as T + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Error: [S-7282] + Stack failed to execute the build plan. + + While executing the build plan, Stack encountered the error: + + [S-7011] + While building package helloworld-0.1.0.0 (scroll up to its section to + see the error) using: + ... + Process exited with code: ExitFailure 1 +~~~ + +The error `Could not load module ...` means that the package exposing the module +in question is not available. + +To tell Stack that the `text` package is a dependency of the `helloworld` +package, you need to update the package description file (`package.yaml`). +Specifically, you need to add `text` under the `dependencies` key, like this: + +~~~yaml +dependencies: +- base >= 4.7 && < 5 +- text # added +~~~ + +Now, if we command: + +~~~text +stack build +~~~ + +we should get a successful result. + +The output means that the `text` package was downloaded, configured, built, and +locally installed. Once that was done, we moved on to building our project +package (`helloworld`). At no point did we need to ask Stack to build +dependencies — it does so automatically. + +## Listing dependencies + +Let's have Stack add a few more dependencies to our project. First, we'll +include two new packages in the `dependencies` section for our library in our +`package.yaml`: + +~~~yaml +dependencies: +- base >= 4.7 && < 5 +- text +- filepath # added +- containers # added +~~~ + +After adding these two dependencies, we can again command: + +~~~text +stack build +~~~ + +to have them downloaded, configured, built, and locally installed. + +To find out which versions of these packages Stack installed, we can command: + +~~~text +stack ls dependencies +~~~ + +## Packages not in the snapshot + +The packages `text`, `filepath` and `containers` have something in common: they +are all provided with GHC (referred to as GHC boot packages). + +Let's try a dependency on a more off-the-beaten-track package: the joke +[acme-missiles](http://www.stackage.org/package/acme-missiles) package. + +We can further modify `src/Lib.hs` so that its contents are as follows: + +~~~haskell +module Lib + ( someFunc + ) where + +import Acme.Missiles ( launchMissiles ) + +someFunc :: IO () +someFunc = launchMissiles +~~~ + +As before, to tell Stack that the `acme-missiles` package is a dependency of the +`helloworld` package, we must update the package description file +(`package.yaml`). The relevant part of that file now looks like this: + +~~~yaml +dependencies: +- base >= 4.7 && < 5 +- text +- filepath +- containers +- acme-missiles # added +~~~ + +However, if we command: + +~~~text +stack build +~~~ + +Stack will report Stack error [S-4804] during the build, with output like the +following: + +~~~text +Error: [S-4804] + Stack failed to construct a build plan. + + While constructing the build plan, Stack encountered the following + errors. The 'Stack configuration' refers to the set of package versions + specified by the snapshot (after any dropped packages, or pruned GHC boot + packages; if a boot package is replaced, Stack prunes all other such + packages that depend on it) and any extra-deps: + + In the dependencies for helloworld-0.1.0.0: + * acme-missiles needed, but no version is in the Stack configuration + (latest matching version is 0.3). + The above is/are needed since helloworld is a build target. + + Some different approaches to resolving some or all of this: + + * Recommended action: try adding the following to your extra-deps in + ...\helloworld\stack.yaml (project-level configuration): + + - acme-missiles-0.3@sha256:2ba66a092a32593880a87fb00f3213762d7bca65a6 +87d45965778deb8694c5d1,613 +~~~ + +The error message explains that Stack was unable to construct a build plan and +why: the package `acme-missiles` was needed but no version of that package is +in the set of package versions specified by the snapshot. Stack makes a +suggestion to fix that. + +This brings us to the next major topic in using Stack. + +## Extending snapshots + +A snapshot specifies a version of GHC and a set of package versions chosen to +work well together. However, sometimes you will want to use package versions +that are not specified by the snapshot. That may be because the package is not +in the snapshot or because a different version of the package is in the +snapshot. + +Remember above when `stack new` selected some +[LTS snapshot](https://github.com/commercialhaskell/lts-haskell#readme) for us? +That defined our build plan and available packages. When we tried using the +`text` package, it just worked, because it was part of the LTS *package set*. + +We have updated the description of the `helloworld` package (in `package.yaml`) +to specify that it depends on the `acme-missiles` package, but `acme-missiles` +is not a member of the set of package versions specified by the snapshot. So +building failed. + +To add a version of `acme-missiles` to the available package versions, we'll use +the `extra-deps` key in Stack's project-level configuration file (`stack.yaml`). +That key defines extra package versions, not present in the snapshot, that will +be needed as dependencies. You can add this like so: + +~~~yaml +extra-deps: +- acme-missiles-0.3 # not in the LTS snapshot +~~~ + +Now, if we command: + +~~~text +stack build +~~~ + +we should get a successful result. + +## Stackage snapshots + +With that out of the way, let's dig a little bit more into these snapshots. We +mentioned the LTS snapshots, and you can get information about it at +[https://www.stackage.org/lts](https://www.stackage.org/lts), including: + +* The appropriate value (`lts-22.30`, as is currently the latest LTS) +* The GHC version used +* A full list of all packages versions available in this snapshot +* The ability to perform a Hoogle search on the packages in this snapshot +* A [list of all modules](https://www.stackage.org/lts/docs) in a snapshot, + which can be useful when trying to determine which package to add to your + `package.yaml` file. + +You can also see a +[list of all available snapshots](https://www.stackage.org/snapshots). You'll +notice two flavors: LTS (for "Long Term Support") and Nightly. You can read more +about them on the +[LTS Haskell GitHub page](https://github.com/commercialhaskell/lts-haskell#readme). +If you're not sure which to use, start with LTS Haskell (which Stack will lean +towards by default as well). + +## Snapshots and GHC versions + +As mentioned, a snapshot specifies a version of GHC as well as a set of package +versions. + +Let's try using an older LTS snapshot. We'll use the Stackage LTS Haskell 21.25 +snapshot with the command: + +~~~text +stack --snapshot lts-21.25 build +~~~ + +Stackage LTS Haskell 21.25 specifies GHC 9.4.8. If that version of GHC is not +already available, Stack will try to fetch it and install it before starting the +rest of the build. + +## Specifying a snapshot + +A snapshot must be specified in Stack's project-level configuration file +(`stack.yaml`, by default). For further information, see the +[`snapshot`](../configure/yaml/project.md#snapshot) project-specific +configuration option documentation. + +As we have seen, a snapshot can also be specified on the command line. That can +be useful in a Continuous Integration (CI) setting. + +When passed on the command line, you also get some additional "short-cut" +versions of snapshots: `--snapshot nightly` will use the newest Nightly snapshot +available, `--snapshot lts` will use the newest LTS, and `--snapshot lts-22` +will use the newest LTS in the 22.x series. The reason these are only available +on the command line and not in your `stack.yaml` file is that using them: + +1. Will slow down your build (since Stack then needs to download information on + the latest available LTS each time it builds) +2. Produces unreliable results (since a build run today may proceed differently + tomorrow because of changes outside of your control) + +## Cleaning up your project + +Stack creates files during the build process and stores those files in +directories within a local project or package directory known as +[Stack work directories](../topics/stack_work.md). Stack can be used without an +understanding of the content of those directories. + +if you wish, you can clean up files created during the build process for your +project using the `stack clean` and `stack purge` commands. + +### The `stack clean` command + +`stack clean` deletes the local working directories containing compiler output. +By default, that means the contents of directories in `.stack-work/dist`, for +all the `.stack-work` directories within a project. + +Use `stack clean <specific-package>` to delete the output for the package +_specific-package_ only. + +### The `stack purge` command + +`stack purge` deletes the local stack working directories, including extra-deps, +git dependencies and the compiler output (including logs). It does not delete +any snapshot packages, compilers or programs installed using `stack install`. +This essentially reverts the project to a completely fresh state, as if it had +never been built. + +`stack purge` is a shortcut for `stack clean --full`.
+ doc/tutorial/cabal_flags_and_ghc_options.md view
@@ -0,0 +1,101 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 8. Cabal flags and GHC options + +There are two common ways to alter how a package will install: with Cabal flags +and with GHC options. + +## Cabal flag management + +To change a Cabal flag setting, we can use the command line `--flag` option. The +`yackage` package has an `upload` flag that is enabled by default. We can +command: + +~~~text +stack build --flag yackage:-upload +~~~ + +This means: when compiling the `yackage` package, turn off the `upload` flag +(thus the `-` in `-upload`). Unlike other tools, Stack is explicit about which +package's flag you want to change. It does this for two reasons: + +1. There's no global meaning for Cabal flags, and therefore two packages can + use the same flag name for completely different things. +2. By following this approach, we can avoid unnecessarily recompiling snapshot + packages that happen to use a flag that we're using. + +You can also change flag values on the command line for extra-dep and snapshot +packages. If you do this, that package will automatically be promoted to an +extra-dep, since the build plan is different than what the plan snapshot +definition would entail. + +## GHC options + +GHC options follow a similar logic as in managing Cabal flags, with a few +nuances to adjust for common use cases. Let's consider the command: + +~~~text +stack build --ghc-options="-Wall -Werror" +~~~ + +This will set the `-Wall -Werror` options for all *local targets*. Note that +this will not affect extra-dep and snapshot packages at all. This design +provides us with reproducible and fast builds. + +(By the way: the above GHC options have a special convenience flag: +`--pedantic`.) + +There's one extra nuance about command line GHC options: Since they only apply +to local targets, if you change your local targets, they will no longer apply +to other packages. Let's play around with an example from the `wai` repository, +which includes the `wai` and `warp` packages, the latter depending on the +former. If we command again: + +~~~text +stack build --ghc-options=-O0 wai +~~~ + +It will build all of the dependencies of `wai`, and then build `wai` with all +optimizations disabled. Now let's add in `warp` as well. Command: + +~~~text +stack build --ghc-options=-O0 wai warp +~~~ + +This builds the additional dependencies for `warp`, and then builds `warp` with +optimizations disabled. Importantly: it does not rebuild `wai`, since `wai`'s +configuration has not been altered. Now the surprising case. Command: + +~~~text +stack build --ghc-options=-O0 warp +wai-3.0.3.0-5a49351d03cba6cbaf906972d788e65d: unregistering (flags changed from ["--ghc-options","-O0"] to []) +warp-3.1.3-a91c7c3108f63376877cb3cd5dbe8a7a: unregistering (missing dependencies: wai) +wai-3.0.3.0: configure +~~~ + +You may expect this to be a no-op: neither `wai` nor `warp` has changed. +However, Stack will instead recompile `wai` with optimizations enabled again, +and then rebuild `warp` (with optimizations disabled) against this newly built +`wai`. The reason: reproducible builds. If we'd never built `wai` or `warp` +before, trying to build `warp` would necessitate building all of its +dependencies, and it would do so with default GHC options (optimizations +enabled). This dependency would include `wai`. So when we command: + +~~~text +stack build --ghc-options=-O0 warp +~~~ + +We want its behavior to be unaffected by any previous build steps we took. +While this specific corner case does catch people by surprise, the overall goal +of reproducible builds is - in the Stack maintainers' views - worth the +confusion. + +Final point: if you have GHC options that you'll be regularly passing to your +packages, you can add them to your `stack.yaml` file. For more information, see +the [ghc-options](../configure/yaml/non-project.md#ghc-options) non-project +specific configuration option documentation. + +!!! note + + That's it, the heavy content of this guide is done! Everything from here on + out is simple explanations of commands. Congratulations!
+ doc/tutorial/executing_commands.md view
@@ -0,0 +1,62 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 10. Executing commands + +We've already used `stack exec` multiple times in this guide. As you've likely +already guessed, it allows you to run executables, but with a slightly modified +environment. + +## The `stack exec` command + +In particular: `stack exec` looks for executables on Stack's bin +paths, and sets a few additional environment variables (like adding those paths +to the PATH, and setting `GHC_PACKAGE_PATH`, which tells GHC which package +databases to use). + +If you want to see exactly what the modified environment looks like, try +command: + +~~~text +stack exec env +~~~ + +The only issue is how to distinguish flags to be passed to Stack versus those +for the underlying program. Thanks to the `optparse-applicative` library, Stack +follows the Unix convention of `--` to separate these. For example, command: + +~~~text +stack exec --package stm -- echo I installed the stm package via --package stm +~~~ + +yields output like: + +~~~text +Run from outside a project, using implicit global project config +Using latest snapshot resolver: lts-22.21 +Writing global (non-project-specific) config file to: /home/michael/.stack/global/stack.yaml +Note: You can change the snapshot via the resolver field there. +I installed the stm package via --package stm +~~~ + +Flags worth mentioning: + +* `--package foo` can be used to force a package to be installed before running + the given command. +* `--no-ghc-package-path` can be used to stop the `GHC_PACKAGE_PATH` environment + variable from being set. Some tools — notably Cabal (the tool) — do not behave + well with that variable set. + +You may also find it convenient to use `stack exec` to launch a subshell +(substitute `bash` with your preferred shell) where your compiled executable is +available at the front of your PATH. Command: + +~~~text +stack exec bash +~~~ + +## The `stack ghc` and `stack runghc` commands + +You'll sometimes want to just compile (or run) a single Haskell source file, +instead of creating an entire Cabal package for it. You can use `stack exec ghc` +or `stack exec runghc` for that. As simple helpers, we also provide the +`stack ghc` and `stack runghc` commands, for these common cases.
+ doc/tutorial/hello_world_example.md view
@@ -0,0 +1,442 @@+<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 1. A Hello World example + +With Stack installed, let's create a new project and walk through the most +common Stack commands. + +In this guide, unless stated otherwise, the working directory is the project's +root directory. + +## The `stack new` command + +We'll start off with the [`stack new`](../commands/new_command.md) command to +create a new *project* from a project template. We'll use the `new-template` +project template. This template is used by default, but in our example we will +refer to it expressly. + +That template will create a project with a package of the same name. So, we need +to pick a name for the project that is a valid package name. We'll call our +project `helloworld`. + +??? question "How do project packages relate to projects?" + + A project can have one or more packages. Each project package has its own + root directory. In the case of a single-package project, the project + directory and the package directory can be the same directory. + +??? question "What is a valid package name?" + + A valid package name consists of one or more alphanumeric words separated by + hyphens. Each word must contain at least one letter. That is, the word must + not be interpreted as a number. + + The names of packages are intended to be unique. + +??? question "Are other project templates available?" + + Yes. For further information about project templates, command: + ~~~text + stack templates + ~~~ + +From the root directory for all our Haskell projects, we command: + +~~~text +stack new helloworld new-template +~~~ + +For this first Stack command, Stack will do some setting up. For example, it +will create the [Stack root](../topics/stack_root.md) directory. + +Other than any setting up, Stack will: +* create the project directory; +* download the project template; +* attempt to populate the project template based on parameters; and +* create and initialise Stack's project-level configuration file. + +Unless the parameters have been configured, Stack will note that parameters were +needed by the template but not provided. That can be ignored for now. + +??? question "How can I configure project template paramaters?" + + For further information, see the + [`templates`](../configure/yaml/non-project.md#templates) non-project + specific configuration option. + + As noted in Stack's output, parameters to populate project templates can + also be set at the command line by using the options of the `stack new` + command. + +??? question "Can I create a new project in the current working directory?" + + Yes. Pass the `--bare` flag to cause Stack to create the project in the + current working directory rather than in a new project directory. + +We now have a project in the `helloworld` directory! We will change to that +directory, with command: + +~~~text +cd helloworld +~~~ + +## The `stack build` command + +Next, we'll run the most important Stack command, +[`stack build`](../commands/build_command.md). We command: + +~~~text +stack build +~~~ + +Stack needs a version of GHC and, on Windows, a version of MSYS2, in order to +build your project. Stack will discover that you are missing it and will install +it for you. + +You'll get intermediate download percentage statistics while the download is +occurring. This command may take some time, depending on download speeds. + +??? question "Where is the Stack-supplied GHC located?" + + You can use the [`stack path`](../commands/path_command.md) command for path + information. To identify where GHC is installed, command: + + === "Unix-like" + + ~~~text + stack exec -- which ghc + /home/<user_name>/.stack/programs/x86_64-linux/ghc-9.6.5/bin/ghc + ~~~ + + === "Windows (with PowerShell)" + + ~~~text + stack exec -- where.exe ghc + C:\Users\<user_name>\AppData\Local\Programs\stack\x86_64-windows\ghc-9.6.5\bin\ghc.exe + ~~~ + + As you can see from that path, the installation is placed to not interfere + with any other GHC installation, whether system-wide or different GHC + versions installed by Stack. + +??? question "Can I use that version of GHC by commanding `ghc`?" + + No. GHC will be installed to the Stack programs directory, which is likely + not on the PATH, so commanding `ghc` will not work. However, that version of + GHC can be used in the Stack environment. For more information, see the + [`stack exec`](../commands/exec_command.md) command, + [`stack ghc`](../commands/ghc_command.md) command, and + [`stack runghc`](../commands/ghc_command.md) command documentation. + +Once a version of GHC and, on Windows, a version of MSYS2, is installed, Stack +will then build your project. The end of the output should look similar to this: + +=== "Unix-like" + + ~~~text + ... + helloworld> configure (lib + exe) + Configuring helloworld-0.1.0.0... + helloworld> build (lib + exe) with ghc-9.6.6 + Preprocessing library for helloworld-0.1.0.0.. + Building library for helloworld-0.1.0.0.. + [1 of 2] Compiling Lib + [2 of 2] Compiling Paths_helloworld + Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0.. + Building executable 'helloworld-exe' for helloworld-0.1.0.0.. + [1 of 2] Compiling Main + [2 of 2] Compiling Paths_helloworld + [3 of 3] Linking .stack-work/dist/x86_64-linux-tinfo6/ghc-9.6.6/build/helloworld-exe/helloworld-exe + helloworld> copy/register + Installing library in .../helloworld/.stack-work/install/x86_64-linux-tinfo6/a2caceceda039eb4f791856f85a68f9582d4daf3d0527344693ff3d1fcd92ba4/9.6.6/lib/x86_64-linux-ghc-9.6.6/helloworld-0.1.0.0-KFyX8zLxDvzLZURq3JaCVX + Installing executable helloworld-exe in .../helloworld/.stack-work/install/x86_64-linux-tinfo6/a2caceceda039eb4f791856f85a68f9582d4daf3d0527344693ff3d1fcd92ba4/9.6.6/bin + Registering library for helloworld-0.1.0.0.. + ~~~ + +=== "Windows" + + ~~~text + ... + helloworld> configure (lib + exe) + Configuring helloworld-0.1.0.0... + helloworld> build (lib + exe) with ghc-9.6.6 + Preprocessing library for helloworld-0.1.0.0.. + Building library for helloworld-0.1.0.0.. + [1 of 2] Compiling Lib + [2 of 2] Compiling Paths_helloworld + Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0.. + Building executable 'helloworld-exe' for helloworld-0.1.0.0.. + [1 of 2] Compiling Main + [2 of 2] Compiling Paths_helloworld + [3 of 3] Linking .stack-work\dist\effaccc7\build\helloworld-exe\helloworld-exe.exe + helloworld> copy/register + Installing library in ...\helloworld\.stack-work\install\c8c71a24\lib\x86_64-windows-ghc-9.6.6\helloworld-0.1.0.0-KFyX8zLxDvzLZURq3JaCVX + Installing executable helloworld-exe in ...\helloworld\.stack-work\install\c8c71a24\bin + Registering library for helloworld-0.1.0.0.. + ~~~ + + On Windows, Stack uses hashes of certain information to keep paths short. + +Stack aims not to rebuild unnecessarily. If we command `stack build` a second +time, nothing happens. + +## The `stack exec` command + +The output of the previous command has three main steps. You can see, from the +first two steps, that a library (lib) and an executable (exe) are being built +and that the final step involved the installation of an executable named +`helloworld-exe` (on Windows, the file is `helloworld-exe.exe`) (extract): + +~~~text +helloworld> configure (lib + exe) +... +helloworld> build (lib + exe) with ghc-9.6.6 +... +helloworld> copy/register +... +Installing executable helloworld-exe in .../helloworld/.stack-work/.../bin +~~~ + +The executable is installed in a location in the project's `.stack-work` +directory. + +Now, let's use the [`stack exec`](../commands/exec_command.md) command to run +our executable. We command: + +~~~text +stack exec helloworld-exe +~~~ + +and the output is just: + +~~~text +someFunc +~~~ + +??? question "Why is the output just `someFunc`?" + + The code in the `new-template` project template is very simple. The package + has a Haskell module `Lib`: + ~~~haskell + module Lib + ( someFunc + ) where + + someFunc :: IO () + someFunc = putStrLn "someFunc" + ~~~ + + and a Haskell module `Main`: + ~~~haskell + module Main (main) where + + import Lib + + main :: IO () + main = someFunc + ~~~ + + `putStrLn "someFunc"` is an action that, when executed, outputs the string + `someFunc` to the standard output channel. + +`stack exec` works by providing the same reproducible environment that was used +to build your project to the command that you are running. Thus, it knew where +to find `helloworld-exe` even though it is not on the PATH outside of that +environment. + +??? question "How I can find the PATH used in the Stack environment?" + + Command `stack path --bin-path` to see the PATH in the Stack environment. + +!!! info + + On Windows, the Stack environment includes the `\mingw64\bin`, `\usr\bin` + and `\usr\local\bin` directories of the Stack-supplied MSYS2. If your + executable depends on files (for example, dynamic-link libraries) in those + directories and you want ro run it outside of the Stack environment, you + will need to ensure copies of those files are on the PATH. + +## The `stack test` command + +Finally, like all good software, `helloworld` actually has a test suite. + +Let's run it with the [`stack test`](../commands/test_command.md) command. We +command: + +~~~text +stack test +~~~ + +The start of the output should look similar to this: + +=== "Unix-like" + + ~~~text + helloworld-0.1.0.0: unregistering (components added: test:helloworld-test) + helloworld> configure (lib + exe + test) + Configuring helloworld-0.1.0.0... + helloworld> build (lib + exe + test) with ghc-9.6.6 + Preprocessing library for helloworld-0.1.0.0.. + Building library for helloworld-0.1.0.0.. + Preprocessing test suite 'helloworld-test' for helloworld-0.1.0.0.. + Building test suite 'helloworld-test' for helloworld-0.1.0.0.. + [1 of 2] Compiling Main + [2 of 2] Compiling Paths_helloworld + [3 of 3] Linking .stack-work/dist/x86_64-linux-tinfo6/ghc-9.6.6/build/helloworld-test/helloworld-test + Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0.. + Building executable 'helloworld-exe' for helloworld-0.1.0.0.. + helloworld> copy/register + Installing library in .../helloworld/.stack-work/install/x86_64-linux-tinfo6/a2caceceda039eb4f791856f85a68f9582d4daf3d0527344693ff3d1fcd92ba4/9.6.6/lib/x86_64-linux-ghc-9.6.6/helloworld-0.1.0.0-KFyX8zLxDvzLZURq3JaCVX + Installing executable helloworld-exe in .../helloworld/.stack-work/install/x86_64-linux-tinfo6/a2caceceda039eb4f791856f85a68f9582d4daf3d0527344693ff3d1fcd92ba4/9.6.6/bin + Registering library for helloworld-0.1.0.0.. + ~~~ + +=== "Windows" + + ~~~text + helloworld-0.1.0.0: unregistering (components added: test:helloworld-test) + helloworld> configure (lib + exe + test) + Configuring helloworld-0.1.0.0... + helloworld> build (lib + exe + test) with ghc-9.6.6 + Preprocessing library for helloworld-0.1.0.0.. + Building library for helloworld-0.1.0.0.. + Preprocessing test suite 'helloworld-test' for helloworld-0.1.0.0.. + Building test suite 'helloworld-test' for helloworld-0.1.0.0.. + [1 of 2] Compiling Main + [2 of 2] Compiling Paths_helloworld + [3 of 3] Linking .stack-work\dist\effaccc7\build\helloworld-test\helloworld-test.exe + Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0.. + Building executable 'helloworld-exe' for helloworld-0.1.0.0.. + helloworld> copy/register + Installing library in ...\helloworld\.stack-work\install\0aa166fa\lib\x86_64-windows-ghc-9.6.6\helloworld-0.1.0.0-KFyX8zLxDvzLZURq3JaCVX + Installing executable helloworld-exe in ...\helloworld\.stack-work\install\0aa166fa\bin + Registering library for helloworld-0.1.0.0.. + ~~~ + +Again, Stack does not rebuild unnecessarily. Only the test suite component is +compiled and linked. + +The output should then conclude: + +~~~text +helloworld> test (suite: helloworld-test) + +Test suite not yet implemented + + + +helloworld> Test suite helloworld-test passed +Completed 2 action(s). +~~~ + +Having build the test suite executable, Stack then automatically runs it. + +## Inner workings of Stack + +Let's look at the `helloworld` example in more detail to understand better how +Stack works. + +The files in the project include: + +~~~text +app/Main.hs +src/Lib.hs +test/Spec.hs +ChangeLog.md +README.md +LICENSE +.gitignore +package.yaml +helloworld.cabal +Setup.hs +stack.yaml +~~~ + +The `app/Main.hs`, `src/Lib.hs`, and `test/Spec.hs` files are all Haskell +source files that compose the actual functionality of our project. We won't +dwell on them here. + +The `ChangeLog.md`, `README.md`, `LICENSE` and `.gitignore` files have no effect +on the build. + +The files of interest here are `package.yaml`, `helloworld.cabal`, `Setup.hs` +and `stack.yaml`. + +### `package.yaml` + +Each package contains a file that describes the package. Stack uses the Cabal +build system and that system uses a Cabal file named after the package (such as +`helloworld.cabal`) to describe the package. + +However, Stack's preferred package description format is the +[Hpack](https://github.com/sol/hpack) format. + +The `package.yaml` file describes the package in the Hpack format. + +If a `package.yaml` file is present, Stack will use its built-in Hpack +functionality to create a Cabal file. + +??? question "What is covered by a package description?" + + A package description includes information such as the package name and + version, and the package's *components*. A package can have an optional + main library component and optional named sub-library components. It can + also have optional executable components, test suite components and + benchmark components. The description identifies other packages on which + those components depend. + + The + [Cabal User Guide](https://cabal.readthedocs.io/en/stable/cabal-package.html) + is the definitive reference for the Cabal package description format. + + The [Hpack](https://github.com/sol/hpack#quick-reference) documentation + is the reference for the Hpack package description format. + +### `helloworld.cabal` + +The `helloworld.cabal` file is updated automatically as part of the +`stack build` process and should not be modified. + +### `Setup.hs` + +The `Setup.hs` file is a component of the Cabal build system. + +Technically, it is not needed by Stack, but it is considered good practice to +include it. The file we're using is boilerplate: + +~~~haskell +import Distribution.Simple +main = defaultMain +~~~ + +### `stack.yaml` + +Stack requires a Stack project-level configuration file for every project. +`stack.yaml` is that file. The contents of the file define project-specific +options and non-project-specific options that apply to the project. + +The contents of the file include comments beginning `#`. Ignoring those +comments, the contents will look something like this: + +~~~yaml +resolver: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/21.yaml +packages: +- . +~~~ + +The key [`resolver`](../configure/yaml/project.md#resolver) is a +project-specific configuration option. Its value tells Stack *how* to build your +package: which GHC version to use, which versions of package dependencies to +use, and so on. Our value here says to use +[LTS Haskell 22.21](https://www.stackage.org/lts-22.21), which implies GHC 9.6.5 +(which is why `stack build` installs that version of GHC if it is not already +available to Stack). There are a number of values you can use for `resolver`, +which we'll cover later. + +The key [`packages`](../configure/yaml/project.md#packages) is another +project-specific configuration option. Its value tells Stack which project +packages, located locally, to build. In our simple example, we have only a +single project package, located in the same directory, so '`.`' suffices. +However, Stack has powerful support for multi-package projects, which we'll +describe as this guide progresses.
+ doc/tutorial/index.md view
@@ -0,0 +1,59 @@+--- +Title: Getting started +--- + + <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# Getting started + +Stack is a program for developing [Haskell](https://www.haskell.org/) projects. + +This guide to getting started takes a new Stack user through the ways that Stack +is typically used. It will not teach Haskell or involve much code, and it +requires no prior experience of Stack or other Haskell tools. + +??? question "What are other Haskell tools?" + + Haskell code is compiled by the + [Glasgow Haskell Compiler](https://www.haskell.org/ghc/) (GHC), which can + also be used interactively. Stack can manage versions of GHC. GHC provides + commands such as `ghc`, `ghci`, `runghc` and `ghc-pkg`. + + Cabal (the tool) is a tool provided by the + [`cabal-install`](https://hackage.haskell.org/package/cabal-install) Haskell + package. It aims to simplify the process of managing Haskell software by + automating the fetching, configuration, compilation and installation of + Haskell libraries and programs. These are goals that Stack shares. Stack can + be used independently of Cabal (the tool) but users can also use both, if + they wish. + + Haskell Language Server (HLS) is an implementation of the Language Server + Protocol for Haskell and used by Haskell extensions for code editors. + + [GHCup](https://www.haskell.org/ghcup/) is a tool that can manage other + Haskell tools, including Stack, GHC, HLS and Cabal (the tool). Stack can use + GHCup to manage versions of GHC, as well as manage GHC directly. + +Terms used in the guide will be explained as they are introduced and are also +defined in the [glossary](../glossary.md). + +Some of Stack's features will not be needed regularly or by all users. Other +parts of Stack's documentation include its [commands](../commands/index.md) and +its [configuration](../configure/index.md). + +## Setting up + +The goal of setting up is a `stack` executable on the PATH. As we will see, when +Stack is used, it sets other things up as needed. + +*[PATH]: An environment variable that specifies a list of directories searched for executable files. + +For further information about setting up, see the +[documentation](../install_and_upgrade.md) on that topic. Return here when you +know that Stack is on the PATH. + +This guide assumes that the directory where Stack install executables (the +location reported by `stack path --local-bin`) has been added to the PATH. + +This guide assumes that your computer's operating system is one of Linux, macOS +or Windows. Stack's commands are the same on all operating systems.
+ doc/tutorial/installed_package_databases.md view
@@ -0,0 +1,110 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 4. Installed package databases + +Time to take a short break from hands-on examples and discuss a little +architecture. Stack has the concept of multiple *databases*. + +A database consists of a GHC package database (which contains the compiled +version of a library), executables, and a few other things as well. To give you +an idea, the contents of the parent directory of the `stack path --local-pkg-db` +directory are the directories: + +~~~text +bin +doc +lib +pkgdb +~~~ + +Databases in Stack are *layered*. For example, the database listing we just gave +is called a *local* database (also known as a *mutable* database). That is +layered on top of a *snapshot* database (also known as a *write-only* database). +The snapshot database contains the libraries and executables that are considered +to be *immutable*. Finally, GHC itself ships with a number of libraries and +executables, also considered to be immutable, which forms the *global* database. + +To get a quick idea of this, we can look at the output of the +`stack exec -- ghc-pkg list` command in our `helloworld` project: + +~~~text +<stack path --global-pkg-db directory> + Cabal-3.6.3.0 + Win32-2.12.0.1 + array-0.5.4.0 + base-4.16.2.0 + binary-0.8.9.0 + bytestring-0.11.3.1 + containers-0.6.5.1 + deepseq-1.4.6.1 + directory-1.3.6.2 + exceptions-0.10.4 + filepath-1.4.2.2 + (ghc-9.2.3) + ghc-bignum-1.2 + ghc-boot-9.2.3 + ghc-boot-th-9.2.3 + ghc-compact-0.1.0.0 + ghc-heap-9.2.3 + ghc-prim-0.8.0 + ghci-9.2.3 + haskeline-0.8.2 + hpc-0.6.1.0 + integer-gmp-1.1 + libiserv-9.2.3 + mtl-2.2.2 + parsec-3.1.15.0 + pretty-1.1.3.6 + process-1.6.13.2 + rts-1.0.2 + stm-2.5.0.2 + template-haskell-2.18.0.0 + text-1.2.5.0 + time-1.11.1.1 + transformers-0.5.6.2 + xhtml-3000.2.2.1 + +<stack path --snapshot-pkg-db directory> + acme-missiles-0.3 + +<stack path --local-pkg-db directory> + helloworld-0.1.0.0 +~~~ + +where `<stack path --global-pkg-db directory>` refers to the directory output by +the command `stack path --global-pkg-db`, and so on. + +Notice that `acme-missiles` ends up in the *snapshot* database. Any package +which comes from Hackage, an archive, or a repository is considered to be an +*immutable* package. + +Anything which is considered *mutable*, or depends on something mutable, ends up +in the *local* database. This includes your own code and any other packages +located on a local file path. + +The reason we have this structure is that: + +* it lets multiple projects reuse the same binary builds of immutable packages, +* but doesn't allow different projects to "contaminate" each other by putting + non-standard content into the shared snapshot database. + +As you probably guessed, there can be multiple snapshot databases available. See +the contents of the `snapshots` directory in the +[Stack root](../topics/stack_root.md). + +* On Unix-like operating systems, each snapshot is in the last of a sequence of + three subdirectories named after the platform, a 256-bit hash of the source + map (how the package should be built -- including the compiler, options, and + immutable dependencies), and the GHC version. + +* On Windows, each snapshot is in a subdirectory that is a shorter hash (eight + characters) of the sequence of three directories used on Unix-like operating + systems. This is done to avoid problems created by default limits on file + path lengths on Windows systems. + +These snapshot databases don't get layered on top of each other; they are each +used separately. + +In reality, you'll rarely — if ever — interact directly with these databases, +but it's good to have a basic understanding of how they work so you can +understand why rebuilding may occur at different points.
+ doc/tutorial/locations_used_by_stack.md view
@@ -0,0 +1,86 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 9. Locations used by Stack + +Generally, you don't need to worry about where Stack stores various files. But +some people like to know this stuff. That's when the `stack path` command is +useful. + +## The `stack path` command + +`stack path --help` explains the available options and, consequently, +the output of the command: + +~~~text +--stack-root Global Stack root directory +--global-config Global Stack configuration file +--project-root Project root (derived from stack.yaml file) +--config-location Configuration location (where the stack.yaml file is) +--bin-path PATH environment variable +--programs Install location for GHC and other core tools (see + 'stack ls tools' command) +--compiler-exe Compiler binary (e.g. ghc) +--compiler-bin Directory containing the compiler binary (e.g. ghc) +--compiler-tools-bin Directory containing binaries specific to a + particular compiler +--local-bin Directory where Stack installs executables (e.g. + ~/.local/bin (Unix-like OSs) or %APPDATA%\local\bin + (Windows)) +--extra-include-dirs Extra include directories +--extra-library-dirs Extra library directories +--snapshot-pkg-db Snapshot package database +--local-pkg-db Local project package database +--global-pkg-db Global package database +--ghc-package-path GHC_PACKAGE_PATH environment variable +--snapshot-install-root Snapshot installation root +--local-install-root Local project installation root +--snapshot-doc-root Snapshot documentation root +--local-doc-root Local project documentation root +--local-hoogle-root Local project documentation root +--dist-dir Dist work directory, relative to package directory +--local-hpc-root Where HPC reports and tix files are stored +~~~ + +In addition, `stack path` accepts the flags above on the command line to state +which keys you're interested in. This can be convenient for scripting. As a +simple example, let's find out the sandboxed versions of GHC that Stack +installed: + +=== "Unix-like" + + Command: + + ~~~text + ls $(stack path --programs)/*.installed + /home/<user_name>/.stack/programs/x86_64-linux/ghc-9.0.2.installed + ~~~ + +=== "Windows (with PowerShell)" + + Command: + + ~~~text + dir "$(stack path --programs)/*.installed" + + Directory: C:\Users\mikep\AppData\Local\Programs\stack\x86_64-windows + + Mode LastWriteTime Length Name + ---- ------------- ------ ---- + -a--- 27/07/2022 5:40 PM 9 ghc-9.0.2.installed + -a--- 25/02/2022 11:39 PM 9 msys2-20210604.installed + ~~~ + +While we're talking about paths, to wipe our Stack install completely, here's +what typically needs to be removed: + +1. the Stack root folder (see `stack path --stack-root`, before you uninstall); +2. if different, the folder containing Stack's global configuration file (see + `stack path --global-config`, before you uninstall); +3. on Windows, the folder containing Stack's tools (see `stack path --programs`, + before you uninstall), which is located outside of the Stack root folder; and +4. the `stack` executable file (see `which stack`, on Unix-like operating + systems, or `where.exe stack`, on Windows). + +You may also want to delete `.stack-work` folders in any Haskell projects that +you have built using Stack. The `stack uninstall` command provides information +about how to uninstall Stack.
+ doc/tutorial/multi-package_projects.md view
@@ -0,0 +1,63 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 7. Multi-package projects + +Until now, everything we've done with Stack has used a single-package project. +However, Stack's power truly shines when you're working on multi-package +projects. All the functionality you'd expect to work just does: dependencies +between packages are detected and respected, dependencies of all packages are +just as one cohesive whole, and if anything fails to build, the build commands +exits appropriately. + +Let's demonstrate this with the `wai-app-static` and `yackage` packages, +starting in the root directory for all our Haskell projects. Command: + +~~~text +mkdir multi +cd multi +stack unpack wai-app-static yackage +Unpacked wai-app-static (from Hackage) to .../multi/wai-app-static-3.1.7.4/ +Unpacked yackage (from Hackage) to .../multi/yackage-0.8.1/ +stack init +Looking for .cabal or package.yaml files to use to init the project. +Using cabal packages: +- wai-app-static-3.1.7.4/ +- yackage-0.8.1/ + +Cabal file warning in .../multi/yackage-0.8.1/yackage.cabal@47:40: version operators used. To use version operators the package needs to specify at least 'cabal-version: >= 1.8'. +Cabal file warning in .../multi/yackage-0.8.1/yackage.cabal@21:36: version operators used. To use version operators the package needs to specify at least 'cabal-version: >= 1.8'. +Selecting the best among 18 snapshots... + +* Matches ... + +Selected resolver: ... +Initialising configuration using resolver: ... +Total number of user packages considered: 2 +Writing configuration to file: stack.yaml +stack build --haddock --test +# Goes off to build a whole bunch of packages +~~~ + +If you look at the `stack.yaml` file, you'll see exactly what you'd expect: + +~~~yaml +resolver: + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/17.yaml +packages: +- wai-app-static-3.1.7.4 +- yackage-0.8.1 +~~~ + +Notice that multiple directories are listed in the `packages` key. + +In addition to local directories, you can also refer to packages available in a +Git repository or in a tarball over HTTP/HTTPS. This can be useful for using a +modified version of a dependency that hasn't yet been released upstream. + +!!! note + + When adding upstream packages directly to your project it is important to + distinguish _project packages_ located locally from the upstream + _dependency packages_. Otherwise you may have trouble running `stack ghci`. + See [stack.yaml documentation](../configure/yaml/project.md#packages) for + more details.
+ doc/tutorial/stack_build_synonyms.md view
@@ -0,0 +1,94 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 5. `stack build` synonyms + +Let's look at a subset of the `stack --help` output: + +~~~text +build Build the package(s) in this directory/configuration +install Shortcut for 'build --copy-bins' +test Shortcut for 'build --test' +bench Shortcut for 'build --bench' +haddock Shortcut for 'build --haddock' +~~~ + +Four of these commands are just synonyms for the `build` command. They are +provided for convenience for common cases (e.g., `stack test` instead of +`stack build --test`) and so that commonly expected commands just work. + +What's so special about these commands being synonyms? It allows us to make +much more composable command lines. For example, we can have a command that +builds executables, generates Haddock documentation (Haskell API-level docs), +and builds and runs your test suites, with: + +~~~text +stack build --haddock --test +~~~ + +You can even get more inventive as you learn about other flags. For example, +take the following command: + +~~~text +stack build --pedantic --haddock --test --exec "echo Yay, it succeeded" --file-watch +~~~ + +This command will: + +* turn on all warnings and errors (the `--pedantic` flag) +* build your library and executables +* generate Haddocks (the `--haddock` flag) +* build and run your test suite (the `--test` flag) +* run the command `echo Yay, it succeeded` when that completes (the `--exec` + option) +* after building, watch for changes in the files used to build the project, and + kick off a new build when done (the `--file-watch` flag) + +## The `stack install` command and `copy-bins` option + +It's worth calling out the behavior of the `install` command and `--copy-bins` +option, since this has confused a number of users (especially when compared to +behavior of other tools like Cabal (the tool)). The `install` command does +precisely one thing in addition to the build command: it copies any generated +executables to the local binary directory. You may recognize the default value +for that path: + +On Unix-like operating systems, command: + +~~~text +stack path --local-bin +/home/<user_name>/.local/bin +~~~ + +On Windows, command: + +~~~text +stack path --local-bin +C:\Users\<user_name>\AppData\Roaming\local\bin +~~~ + +That's why the download page recommends adding that directory to your PATH. This +feature is convenient, because now you can simply run `executable-name` in your +shell instead of having to run `stack exec executable-name` from inside your +project directory. + +Since it's such a point of confusion, let me list a number of things Stack does +*not* do specially for the `install` command: + +* Stack will always build any necessary dependencies for your code. The install + command is not necessary to trigger this behavior. If you just want to build a + project, run `stack build`. +* Stack will *not* track which files it's copied to your local binary directory + nor provide a way to automatically delete them. There are many great tools out + there for managing installation of binaries, and Stack does not attempt to + replace those. +* Stack will not necessarily be creating a relocatable executable. If your + executables hard-codes paths, copying the executable will not change those + hard-coded paths. + + * At the time of writing, there's no way to change those kinds of paths with + Stack, but see + [issue #848 about --prefix](https://github.com/commercialhaskell/stack/issues/848) + for future plans. + +That's really all there is to the `install` command: for the simplicity of what +it does, it occupies a much larger mental space than is warranted.
+ doc/tutorial/stack_build_targets.md view
@@ -0,0 +1,107 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 6. `stack build` targets + +We haven't discussed this too much yet, but, in addition to having a number of +synonyms *and* taking a number of options on the command line, the `build` +command *also* takes many arguments. These are parsed in different ways, and can +be used to achieve a high level of flexibility in telling Stack exactly what you +want to build. + +We're not going to cover the full generality of these arguments here; instead, +there's documentation covering the full +[build command syntax](../commands/build_command.md). Here, we'll just point out +a few different types of arguments: + +* You can specify a *package name*, e.g. `stack build vector`. + * This will attempt to build the `vector` package, whether it's a local + package, in your extra-deps, in your snapshot, or just available upstream. + If it's just available upstream but not included in your locals, + extra-deps, or snapshot, the newest version is automatically promoted to + an extra-dep. +* You can also give a *package identifier*, which is a package name plus + version, e.g. `stack build yesod-bin-1.4.14`. + * This is almost identical to specifying a package name, except it will (1) + choose the given version instead of latest, and (2) error out if the given + version conflicts with the version of a project package. +* The most flexibility comes from specifying individual *components*, e.g. + `stack build helloworld:test:helloworld-test` says "build the test suite + component named helloworld-test from the helloworld package." + * In addition to this long form, you can also shorten it by skipping what + type of component it is, e.g. `stack build helloworld:helloworld-test`, or + even skip the package name entirely, e.g. `stack build :helloworld-test`. +* Finally, you can specify individual *directories* to build to trigger building + of any project packages included in those directories or subdirectories. + +When you give no specific arguments on the command line (e.g., `stack build`), +it's the same as specifying the names of all of your project packages. If you +just want to build the package for the directory you're currently in, you can +use `stack build .`. + +## Components, --test, and --bench + +Here's one final important yet subtle point. Consider our `helloworld` package: +it has a library component, an executable `helloworld-exe`, and a test suite +`helloworld-test`. When you run `stack build helloworld`, how does it know which +ones to build? By default, it will build the library (if any) and all of the +executables but ignore the test suites and benchmarks. + +This is where the `--test` and `--bench` flags come into play. If you use them, +those components will also be included. So `stack build --test helloworld` will +end up including the helloworld-test component as well. + +You can bypass this implicit adding of components by being much more explicit, +and stating the components directly. For example, the following will not build +the `helloworld-exe` executable: + +~~~text +stack purge +stack build :helloworld-test +helloworld> configure (lib + test) +Configuring helloworld-0.1.0.0... +helloworld> build (lib + test) with ghc-9.6.5 +Preprocessing library for helloworld-0.1.0.0.. +Building library for helloworld-0.1.0.0.. +[1 of 2] Compiling Lib +[2 of 2] Compiling Paths_helloworld +Preprocessing test suite 'helloworld-test' for helloworld-0.1.0.0.. +Building test suite 'helloworld-test' for helloworld-0.1.0.0.. +[1 of 2] Compiling Main +[2 of 2] Compiling Paths_helloworld +[3 of 3] Linking .stack-work\dist\<hash>\build\helloworld-test\helloworld-test.exe +helloworld> copy/register +Installing library in ...\helloworld\.stack-work\install\... +Registering library for helloworld-0.1.0.0.. +helloworld> test (suite: helloworld-test) + +Test suite not yet implemented + + + +helloworld> Test suite helloworld-test passed +Completed 2 action(s). +~~~ + +We first purged our project to clear old results so we know exactly what Stack +is trying to do. + +The last line shows that our command also *runs* the test suite it just built. +This may surprise some people who would expect tests to only be run when using +`stack test`, but this design decision is what allows the `stack build` command +to be as composable as it is (as described previously). The same rule applies to +benchmarks. To spell it out completely: + +* The `--test` and `--bench` flags simply state which components of a package + should be built, if no explicit set of components is given +* The default behavior for any test suite or benchmark component which has been + built is to also run it + +You can use the `--no-run-tests` and `--no-run-benchmarks` flags to disable +running of these components. You can also use `--no-rerun-tests` to prevent +running a test suite which has already passed and has not changed. + +!!! note + + Stack doesn't build or run test suites and benchmarks for non-local + packages. This is done so that a command like `stack test` doesn't need to + run 200 test suites!
+ doc/tutorial/stack_configuration.md view
@@ -0,0 +1,75 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 12. Stack configuration + +Whenever you run something with Stack, it needs a project-level configuration +file. The algorithm Stack uses to find such a file is: + +1. Check for a `--stack-yaml` option on the command line +2. Check for a `STACK_YAML` environment variable +3. Check the current directory and all ancestor directories for a `stack.yaml` + file + +The first two provide a convenient method for using an alternate configuration. +For example: `stack build --stack-yaml stack-ghc-9.2.3.yaml` can be used by your +CI system to check your code against GHC 9.2.3. Setting the `STACK_YAML` +environment variable can be convenient if you're going to be running commands +like `stack ghc` in other directories, but you want to use the configuration you +defined in a specific project. + +If Stack does not find a project level configuration file in any of the three +specified locations, the *implicit global* logic kicks in. You've probably +noticed that phrase a few times in the output from commands above. Implicit +global is essentially a hack to allow Stack to be useful in a non-project +setting. When no implicit global configuration file exists, Stack creates one +for you with the latest LTS snapshot. This allows you to do things like: + +* compile individual files easily with `stack ghc` +* build executables without starting a project, e.g. `stack install pandoc` + +Keep in mind that there's nothing magical about this implicit global +configuration. It has no effect on projects at all. Every package you install +with it is put into isolated databases just like everywhere else. The only magic +is that it's the catch-all project whenever you're running Stack somewhere else. + +## Package description vs project-level configuration + +Now that we've covered a lot of ways to use Stack, this quick summary of +package description files versus Stack's project-level configuration file will +hopefully make sense and be a good reminder for future uses of Stack: + +<div class="grid cards" markdown> + +- __Package description__ + + Each package has a package description file in the Cabal format (a Cabal + file named after the package. + + A package may have a package description file in the Hpack format + (`package.yaml`). If one exists, Stack will use it to generate the Cabal + file. + + --- + + Specifies which other Haskell packages are dependencies of the package. + + --- + + Specifies the components, modules, and Cabal flags provided by the package. + +- __Project-level configuration__ + + Each project has a project-level configuration file (named `stack.yaml`, by + default). + + A project can have one or more project packages. + + --- + + Specifies which package versions are available to be used. + + --- + + Can override the Cabal flag settings for individual packages. + +</div>
+ doc/tutorial/tutorial_conclusion.md view
@@ -0,0 +1,43 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 13. In conclusion + +Stack is not the only tool available for building Haskell code. If you are +happy building Haskell code with other tools, you may not need Stack. If +you're experiencing problems with other tools, give Stack a try. + +If you're a new user who has no experience with other tools, we recommend Stack. +It aims to be easy to use and its defaults match modern best practices in +Haskell development. + +Other key features of Stack include: + +<div class="grid cards" markdown> + +- __Sandboxing__ + + A 'sandbox' is a development environment that is isolated from other parts + of the system. The concept of sandboxing is built in to Stack. + +- __Snapshots__ + + --- + + A snapshot specifies a GHC versions and a set of package versions that work + well together. Stack uses snapshots to define precisely the set of package + versions available for a project. + +- __Reproducibility__ + + --- + + Stack goes to great lengths to ensure that `stack build` today does the + same thing tomorrow. Changing the build plan is always an explicit decision. + +- __Building dependencies__ + + --- + + Stack automatically builds dependencies. + +</div>
+ doc/tutorial/using_ghc_interactively.md view
@@ -0,0 +1,31 @@+ <div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> + +# 11. Using GHC interactively + +GHCi is the interactive GHC environment, a.k.a. the REPL. You *could* access it +with command: + +~~~text +stack exec ghci +~~~ + +But that won't load up locally written modules for access. For that, use the +`stack ghci` or `stack repl` commands, which are equivalent. + +## The `stack ghci` or `stack repl` command + +To then load +modules from your project in GHCi, use the `:module` command (`:m` for short) +followed by the module name. + +!!! note + + If you have added packages to your project please make sure to mark them as + extra-deps for faster and reliable usage of `stack ghci`. Otherwise GHCi may + have trouble due to conflicts of compilation flags or having to + unnecessarily interpret too many modules. See Stack's project-level + [configuration](../configure/yaml/project.md#extra-deps) to learn how to + configure a package as an extra-dep. + +For further information, see the [REPL environment](../commands/ghci_command.md) +documentation.
− doc/uninstall_command.md
@@ -1,11 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack uninstall` command - -~~~text -stack uninstall -~~~ - -`stack uninstall` provides information to the standard output stream about how -to uninstall Stack or a Stack-supplied tool (such as GHC or, on Windows, MSYS2). -It does not itself uninstall Stack or a Stack-supplied tool.
− doc/unpack_command.md
@@ -1,51 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack unpack` command - -~~~text -stack unpack TARGET [--candidate] [--to DIR] -~~~ - -`stack unpack` downloads an archive file for one or more specified target -packages from the package index (e.g. Hackage), or one or more specified target -package candidates, and unpacks each archive into a subdirectory named after the -package version. - -In the case of packages from the package index, a target can be a package -name only. In that case, by default: - -* if Stack's `--snapshot` option is not specified, the download is for the - most recent version of the package in the package index. Stack will first - seek to update the index; and - -* if Stack's `--snapshot` option is specified, the download is for the version - of the package included directly in the specified snapshot. - -!!! note - - Stackage snapshots do not include directly most GHC boot packages (packages - that come with GHC and are included in GHC's global package database) but - some snapshots may include directly some boot packages. In particular, some - snapshots include directly `Win32` (which is a boot package on Windows) - while others do not. - -Otherwise, a target should specify a package name and version (for example, -`acme-missiles-0.3`). In the case of package versions from the package index, -optionally, a revision in the package index can be specified by appending -`@rev:<number>` or `@sha256:<sha>` (for example, `acme-missiles-0.3@rev:0`). - -By default: - -* the download is from the package index. Pass the flag `--candidate` to - specify package candidates; and - - !!! note - - Stack assumes that a package candidate archive is a `.tar.gz` file named - after the package version and located at endpoint - `package\<package_version>\candidate\`. This is true of Hackage. - -* the target is unpacked into a subdirectory of the current directory. Pass - the option `--to <directory>` to specify an alternative destination - directory to the current directory. The destination directory can be an - absolute one or relative to the current directory.
− doc/update_command.md
@@ -1,12 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack update` command - -~~~text -stack update -~~~ - -Generally, Stack automatically updates the package index when necessary. - -`stack update` will download the most recent set of packages from your package -indices (e.g. Hackage).
− doc/upgrade_command.md
@@ -1,103 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack upgrade` command - -Either: - -~~~text -stack upgrade [--binary-only] [--binary-platform ARG] [--force-download] - [--[no-]only-local-bin] [--binary-version ARG] [--github-org ARG] - [--github-repo ARG] -~~~ - -or: - -~~~text -stack upgrade [--source-only] [--git] [--git-repo ARG] [--git-branch ARG] -~~~ - -`stack upgrade` will get a new version of Stack. It can also get a version -before the current version (downgrade). - -!!! warning - - If you use GHCup to install Stack, use only GHCup to upgrade Stack. - -By default: - -* the new version will be from an existing binary distribution. Pass the - `--source-only` flag to specify compiling from source code. The - `--binary-only` and `--source-only` flags are alternatives; - -* the new version will not overwrite the existing version unless it is newer. - Pass the `--force-download` flag to force a download; - -* when an existing binary distribution is applicable, it will be put in Stack's - local binary directory (see `stack path --local-bin`) and named `stack` - (replacing any existing executable named `stack` there); - -* if the current running Stack executable is named `stack` (or, on Windows, - `stack.exe`) (this is case insensitive), an existing binary distribution will - replace it. If the executable is located outside of Stack's local binary - directory, pass the `--only-local-bin` flag to skip that step; - -* if the current running Stack executable is named other than `stack` (and, on - Windows, `stack.exe`), an existing binary distribution will only be put in - Stack's local binary directory and named `stack`. Pass the - `--no-only-local-bin` flag to replace also the current running executable; - -* the new version will be the latest available. Pass the - `--binary-version <version>` option to specify the version (this implies - `--force-download`); - -* the binary distribution will be sought from the GitHub organisation/user - `commercialhaskell`. Pass the `--github-org <user>` option to specify a - different GitHub user; - -* the binary distribution will be sought from the GitHub repository `stack`. - Pass the `--github-repo <repository>` option to specify a different - repository; and - -* the binary distribution will be sought for the current platform. Pass the - `--binary-platform <platform>` option to specify a different platform - (`<operating_system>-<architecture>-<suffix>`). - -When compiling from source code, by default: - -* Stack will obtain the source code for the most recent version in the package - index (eg Hackage). Pass the flag `--git` to specify the most recent version - from the `master` branch of Stack's repository (pass the option - `--git-branch <branch>` to specify a different branch and the option - `--git-repo <repo_url>` to specify a different repository). - -!!! note - - An earlier version of Stack could be inconsistent with some of the current - contents of the Stack root. For further information about the contents of - the Stack root and configuring its location, see the documentation about the - [Stack root](stack_root.md). - -## Examples - -* `stack upgrade` seeks an upgrade to the latest version of Stack available as a - binary distribution for the platform, if newer. - -* `stack upgrade --force-download` seeks an upgrade to the latest version of - Stack available as a binary distribution for the platform, even if not newer. - -* If the Stack executable is named `my-stack`, `my-stack upgrade` seeks only to - put the latest version of Stack available as a binary distribution for the - platform, if newer, in Stack's local binary directory and name it `stack`. - `my-stack upgrade --no-only-local-bin` seeks also to upgrade `my-stack` to the - latest version of Stack available. - -* `stack upgrade --binary-version 2.15.1` seeks an upgrade to Stack 2.15.1 if - available as a binary distribution for the platform, even if not newer. - -* `stack upgrade --source-only` seeks an upgrade by building Stack with - Stack from the latest version of the source code in the package index - (i.e. Hackage). - -* `stack upgrade --source-only --git` seeks an upgrade by building Stack with - Stack from the latest version of the source code in the `master` branch of - Stack's repository.
− doc/upload_command.md
@@ -1,131 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# The `stack upload` command - -~~~text -stack upload [ITEM] [-d|--documentation] [--pvp-bounds PVP-BOUNDS] - [--ignore-check] [--[no-]test-tarball] [--tar-dir ARG] - [--candidate] [--setup-info-yaml URL] - [--snapshot-location-base URL] -~~~ - -By default: - -* the command uploads one or more packages. Pass the flag `--documentation` - (`-d` for short) to upload documentation for one or more packages; and - -* the upload is a package to be published or documentation for a published - package. Pass the flag `--candidate` to upload a - [package candidate](http://hackage.haskell.org/upload#candidates) or - documentation for a package candidate. - -At least one `ITEM` must be specified. For example, if the current working -directory is a package directory: - -~~~text -stack upload . -~~~ - -## Upload one or more packages - -Hackage accepts packages for uploading in a standard form, a compressed archive -('tarball') in the format produced by Cabal's `sdist` action. - -If `ITEM` is a relative path to an sdist tarball, `stack upload` uploads the -package to Hackage. - -If `ITEM` is a relative path to a package directory, `stack upload` generates a -file for your package, in the format accepted by Hackage for uploads, and -uploads the package to Hackage. - -By default: - -* the command will check each package for common mistakes. Pass the flag - `--ignore-check` to disable such checks; - -* Stack will not test the resulting package archive. Pass the flag - `--test-tarball` to cause Stack to test each resulting package archive, by - attempting to build it. - -The `--pvp-bounds <pvp_bounds_mode>` option determines whether and, if so, how -PVP version bounds should be added to the Cabal file of the package. The -available modes for basic use are: `none`, `lower`, `upper`, and `both`. The -available modes for use with Cabal file revisions are `lower-revision`, -`upper-revision` and `both-revision`. - -For futher information, see the -[YAML configuration](yaml_configuration.md#pvp-bounds) documentation. - -The `--tar-dir <path_to_directory>` option determines whether the package -archive should be copied to the specified directory. - -## Upload documentation for a package - -:octicons-beaker-24: Experimental - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -Hackage accepts documentation for a package for uploading in a standard form and -in a compressed archive ('tarball') in the `.tar.gz` format. - -For further information about how to create such an archive file, see the -documentation for the -[`stack haddock --haddock-for-hackage`](build_command.md#-no-haddock-for-hackage-flag) -command. - -If `ITEM` is a relative path to a package directory, -`stack upload <package_directory> --documentation` uploads an existing archive -file of documentation for the specified package to Hackage. - -If the `--documentation` flag is passed then flags specific to package upload -are ignored. - -## The `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` environment variables - -[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) - -`stack upload` will request a Hackage username and password to authenticate. -This can be avoided by setting the `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` -environment variables. For -example: - -=== "Unix-like" - - ~~~text - export $HACKAGE_USERNAME="<username>" - export $HACKAGE_PASSWORD="<password>" - stack upload . - ~~~ - -=== "Windows (with PowerShell)" - - ~~~text - $Env:HACKAGE_USERNAME='<username>' - $Env:HACKAGE_PASSWORD='<password>' - stack upload . - ~~~ - -## The `HACKAGE_KEY` environment variable - -[:octicons-tag-24: 2.7.5](https://github.com/commercialhaskell/stack/releases/tag/v2.7.5) - -Hackage allows its members to register an API authentification token and to -authenticate using the token. - -A Hackage API authentification token can be used with `stack upload` instead of -username and password, by setting the `HACKAGE_KEY` environment variable. For -example: - -=== "Unix-like" - - ~~~text - HACKAGE_KEY=<api_authentification_token> - stack upload . - ~~~ - -=== "Windows (with PowerShell)" - - ~~~text - $Env:HACKAGE_KEY=<api_authentification_token> - stack upload . - ~~~
− doc/yaml_configuration.md
@@ -1,2069 +0,0 @@-<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div> - -# Configuration and customisation - -Stack is configured by the content of YAML files. Some Stack operations can also -be customised by the use of scripts. - -!!! info - - A Haskell package is an organised collection of Haskell code and related - files. It is described by a Cabal file or a `package.yaml` file (which can - be used to generate a Cabal file). The package description is itself part of - the package. Its file is located in the root directory of a project package - or dependency located locally. - - A Stack project is a local directory that contains a Stack project-level - configuration file (`stack.yaml`, by default). A project may relate to more - than one project package. A single-package project's directory will usually - also be the project package's root directory. - -## YAML configuration - -Stack's YAML configuration options break down into -[project-specific](#project-specific-configuration) options and -[non-project-specific](#non-project-specific-configuration) options. The former -are configured at the project level. The latter are configured at the project -level or globally. - -The **project-level** configuration file (`stack.yaml`, by default) contains -project-specific options and may contain non-project-specific options. However, -non-project-specific options in the project-level configuration file in the -`global-project` directory (see below) are ignored by Stack. - -Stack obtains project-level configuration from one of the following (in order of -preference): - -1. A file specified by the `--stack-yaml` command line option. -2. A file specified by the `STACK_YAML` environment variable. -3. A file named `stack.yaml` in the current directory or an ancestor directory. -4. A file name `stack.yaml` in the `global-project` directory in the - [Stack root](stack_root.md). - -The **global** configuration file (`config.yaml`) contains only -non-project-specific options. The location of this file depends on the operating -system and whether Stack is configured to use the XDG Base Directory -Specification. - -=== "Unix-like" - - `config.yaml` is located in `/etc/stack` (for system-wide options); and/or - in the [Stack root](stack_root.md) (for user-specific options). - -=== "Windows" - - `config.yaml` is located in the [Stack root](stack_root.md). - -=== "XDG Base Directory Specification" - - On Unix-like operating systems and Windows, Stack can be configured to - follow the XDG Base Directory Specification if the environment variable - `STACK_XDG` is set to any non-empty value. However, Stack will ignore that - configuration if the [Stack root](stack_root.md) location has been set on - the command line or the `STACK_ROOT` environment variable exists. - - If Stack is following the XDG Base Directory Specification, the location of - `config.yaml` (for user-specific options) is `<XDG_CONFIG_HOME>/stack`. If - the `XDG_CONFIG_HOME` environment variable does not exist, the default is - `~/.config/stack` on Unix-like operating systems and `%APPDIR%\stack` on - Windows. - -This page is intended to document fully all YAML configuration options. If you -identify any inaccuracies or incompleteness, please update the page, and if -you're not sure how, open an issue labeled "question". - -If you wish to understand the difference between a `stack.yaml` files and a -Cabal file (named `<package_name>.cabal`), see the -[stack.yaml vs a Cabal file](stack_yaml_vs_cabal_package_file.md) documentation. - -## Project-specific configuration - -Project-specific configuration options are valid only in a project-level -configuration file (`stack.yaml`, by default). - -Each of the Haskell packages to which a Stack project relates is either a -**project package** that is part of the project and located locally or a package -on which one or more of the project packages depends (directly or indirectly). -The latter is referred to as a **dependency** and it may be located locally or -elsewhere. - -!!! info - - Project packages are built by default. Dependencies are only built when - needed. Building can target individual components of a project package. The - individual components of dependencies cannot be targeted. Test suite and - benchmark components of a project package can be built and run. The library - and executable components of a dependency, and only those components, are - built when the dependency is needed. - -In your project-specific options, you specify both **which project packages** to -build and **which dependencies to use** when building these packages. - -A dependency specified as an [extra-dep](#extra-deps) will shadow a package of -the same name specified in a [snapshot](#snapshot). A project package will -shadow a dependency of the same name. - -### snapshot - -Command line equivalent (takes precedence): -[`--snapshot`](global_flags.md#snapshot-option) or -[`--resolver`](global_flags.md#resolver-option) option - -The `snapshot` key specifies which snapshot is to be used for this project. A -snapshot defines a GHC version, the package version of packages available for -installation, and various settings like build flags. It is also called a -resolver since a snapshot states how dependencies are resolved. There are -currently four snapshot types: - -* LTS Haskell snapshots, e.g. `snapshot: lts-22.21` -* Stackage Nightly snapshots, e.g. `snapshot: nightly-2024-05-06` -* No snapshot, just use packages shipped with the compiler. For GHC this looks - like `snapshot: ghc-9.6.5` -* Custom snapshot, via a URL or relative file path. For further information, see - the [snapshot and package location](pantry.md) documentation. - -Each of these snapshots will also determine what constraints are placed on the -compiler version. See the [compiler-check](#compiler-check) option for some -additional control over compiler version. - -A package version specified in a snapshot can be shadowed by an -[extra-dep](#extra-deps) of the same name or a [project package](#packages) of -the same name. - -### resolver - -`resolver` and [`snapshot`](#snapshot) are synonyms. Only one of these keys is -permitted, not both. - -### packages - -Default: - -~~~yaml -packages: -- . -~~~ - -The `packages` key specifies a list of the project packages that are part of -your project. These are specified via paths to local directories. A path is -considered relative to the directory containing the project-level configuration -file (`stack.yaml`, by default). For example, if the `stack.yaml` file is -located at `/dir1/dir2/stack.yaml`, and has: - -~~~yaml -packages: -- my-package -- dir3/my-other-package -~~~ - -the configuration means "project packages in directories `/dir1/dir2/my-package` -and `/dir1/dir2/dir3/my-other-package`". - -The `packages` key is optional. The default value, '`.`', means that the -project has a single project package located in the current directory. - -A project package will shaddow a dependency of the same name. - -A package version specified in a snapshot can be shadowed by an -[extra-dep](#extra-deps) of the same name or a [project package](#packages) of -the same name. - -Each specified project package directory must have a valid Cabal file or Hpack -`package.yaml` file present. Any subdirectories of the directory are not -searched for Cabal files. A subdirectory has to be specified as an independent -item in the list of project packages. - -A project package is different from a dependency (located locally or elsewhere) -specified as an [extra-dep](#extra-deps) or via a [snapshot](#snapshot). For -example: - -* a project package will be built by default by commanding - [`stack build`](build_command.md) without specific targets. A dependency will - only be built if it is needed; and -* test suites and benchmarks may be built and run for a project package. They - are never run for a dependency. - -### extra-deps - -Default: `[]` - -The `extra-deps` key specifies a list of extra dependencies on top of what is -defined in the [snapshot](#snapshot). A dependency may come from either a Pantry -package location or a local file path. - -A Pantry package location is one or three different kinds of sources: - -* the package index (Hackage); -* an archive (a tarball or zip file, either local or over HTTP or HTTPS); or -* a Git or Mercurial repository. - -For further information on the format for specifying a Pantry package location, -see the [Pantry](pantry.md) documentation. For example: - -~~~yaml -extra-deps: -# The latest revision of a package in the package index (Hackage): -- acme-missiles-0.3 -# A specific revision of a package in the package index (Hackage): -- acme-missiles-0.3@rev:0 -# An *.tar.gz archive file over HTTPS: -- url: https://github.com/example-user/my-repo/archive/08c9b4cdf977d5bcd1baba046a007940c1940758.tar.gz - subdirs: - - my-package -# A Git repository at a specific commit: -- git: https://github.com/example-user/my-repo.git - commit: '08c9b4cdf977d5bcd1baba046a007940c1940758' -# An archive of files at a point in the history of a GitHub repository -# (identified by a specific commit): -- github: example-user/my-repo - commit: '08c9b4cdf977d5bcd1baba046a007940c1940758' - subdirs: - - my-package -~~~ - -!!! note - - GHC boot packages are special. An extra-dep with the same package name and - version as a GHC boot package will be ignored. - -!!! note - - The `commit:` key expects a YAML string. A commit hash, or partial hash, - comprised only of digits represents a YAML number, unless it is enclosed in - quotation marks. - -For a local file path source, the path is considered relative to the directory -containing the `stack.yaml` file. For example, if the `stack.yaml` is located -at `/dir1/dir2/stack.yaml`, and has: - -~~~yaml -extra-deps: -- my-package -- dir3/my-other-package -~~~ - -the configuration means "extra-deps packages in directories -`/dir1/dir2/my-package` and `/dir1/dir2/dir3/my-other-package`". - -!!! note - - A local file path that has the format of a package identifier will be - interpreted as a reference to a package on Hackage. Prefix it with `./` to - avoid that confusion. - -!!! note - - A specified extra-dep that does not have the format of a valid Pantry - package location (for example, a reference to a package on Hackage that - omits the package's version) will be interpreted as a local file path. - -An extra-dep will shadow a dependency specified in a [snapshot](#snapshot) of -the same name. An extra-dep can be shadowed by a [project package](#packages) of -the same name. - -!!! info - - Some Haskell packages published on Hackage, for example `base` and `ghc`, - are referred to as 'wired-in' to one or more versions of GHC or as 'magic'. - They can be distinguished from normal packages by the contents of their - Cabal files: GHC's `-this-unit-id` option is set as the name of the package - without a version. For example, the `base.cabal` for `base-4.19.1.0` - includes: - - ~~~yaml - -- We need to set the unit id to base (without a version number) - -- as it's magic. - ghc-options: -this-unit-id base - ~~~ - - The GHC boot packages that are 'wired-in' cannot be shaddowed with different - versions of the same package. Given their dependencies, the use of these - boot packages in a build plan may limit what can be specified as an - extra-dep. - - For example, GHC boot package `ghc-9.8.2` has a dependency on `process`. Its - `*.conf` file identifies the dependency as `process-1.6.18.0-4fb7`. If - package `ghc-9.8.2` is part of a build plan and a different version of - `process` is specified as an extra-dep, during a build, Stack will identify - that the build plan refers to two versions of `process` and warn that the - build is likely to fail. - - Stack treats the following as the names of 'wired-in' packages: `base`, - `dph-par`, `dph-seq`, `ghc-bignum`, `ghc-prim`, `ghc`, `integer-gmp`, - `integer-simple`, `interactive`, `rts` and `template-haskell`. - -### flags - -Default: `{}` - -Command line equivalent (takes precedence): -[`stack build --flag`](build_command.md#-flag-option) option - -Cabal flags can be set for each package separately. For example: - -~~~yaml -flags: - package-name: - flag-name: true -~~~ - -This overrides all Cabal flag specifications (if any) for the specified packages -in the snapshot. - -!!! note - - For a package included directly in the snapshot, if the Cabal flag - specifications differ from the Cabal flag specifications (if any) in the - snapshot, then the package will automatically be promoted to be an - [extra-dep](#extra-deps). - -!!! note - - In order to set a Cabal flag for a GHC boot package, the package must be - specified as an [extra-dep](#extra-deps). - -### drop-packages - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -Default: `[]` - -Packages which, when present in the snapshot specified in the -[`snapshot`](#snapshot) or [`resolver`](#resolver) key, should not be included -in our project. This can be used for a few different purposes, e.g.: - -* Ensure that packages you don't want used in your project cannot be used in a - `package.yaml` file (e.g., for license reasons) -* When using a custom GHC build, avoid incompatible packages (see this - [comment](https://github.com/commercialhaskell/stack/pull/4655#issuecomment-477954429)). - -~~~yaml -drop-packages: -- buggy-package -- package-with-unacceptable-license -~~~ - -!!! info - - Stackage snapshots LTS Haskell 14.27 (GHC 8.6.5) and earlier, and Nightly - 2022-02-08 (GHC 8.8.2) and earlier, included directly the `Cabal` package. - Later snapshots do not include directly that package (which is a GHC boot - package). - - For the older Stackage snapshots, it could be handy to drop the - snapshot-specified `Cabal` package, to avoid building that version of the - package. For the later snapshots, there is no package version to drop. - -### user-message - -If present, specifies a message to be displayed every time the configuration is -loaded by Stack. It can serve as a reminder for the user to review the -configuration and make any changes if needed. The user can delete this message -if the generated configuration is acceptable. - -For example, a user-message is inserted by `stack init` when it omits packages -or adds external dependencies, namely: - -~~~yaml -user-message: ! 'Warning: Some packages were found to be incompatible with the resolver - and have been left commented out in the packages section. - - Warning: Specified resolver could not satisfy all dependencies. Some external packages - have been added as dependencies. - - You can omit this message by removing it from stack.yaml - -' -~~~ - -### custom-preprocessor-extensions - -Default: `[]` - -Command line equivalent: `--customer-preprocessor-extensions` option - -In order for Stack to be aware of any custom preprocessors you are using, add -their extensions here - -~~~yaml -custom-preprocessor-extensions: -- erb -~~~ - -TODO: Add a simple example of how to use custom preprocessors. - -### extra-package-dbs - -[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) - -Default: `[]` - -A list of relative or absolute paths to package databases. These databases will -be added on top of GHC's global package database before the addition of other -package databases. - -!!! warning - - Use of this feature may result in builds that are not reproducible, as Stack - has no control over the contents of the extra package databases. - -### curator - -:octicons-beaker-24: Experimental - -[:octicons-tag-24: 2.1.0.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.0.1) - -Default: `{}` - -Configuration intended for use only by the -[`curator` tool](https://github.com/commercialhaskell/curator), which uses Stack -to build packages. For given package names (which need not exist in the -project), Stack can be configured to ignore (skip) silently building test -suites, building benchmarks and/or creating Haddock documentation or to expect -that building test suites, building benchmarks and/or creating Haddock -documentation will fail. - -For example: - -~~~yaml -curator: - skip-test: - - my-package1 - expect-test-failure: - - my-package2 - skip-bench: - - my-package3 - expect-benchmark-failure: - - my-package4 - skip-haddock: - - my-package5 - expect-haddock-failure: - - my-package6 -~~~ - -## Non-project-specific configuration - -Non-project configuration options can be included in a project-level -configuration file (`stack.yaml`, by default) or in global configuration files -(`config.yaml`). However, non-project-specific options in the project-level -configuration file in the `global-project` directory are ignored by Stack. The -options below are listed in alphabetic order. - -### allow-different-user - -[:octicons-tag-24: 1.0.1.0](https://github.com/commercialhaskell/stack/releases/tag/v1.0.1.0) - -Restrictions: POSIX systems only. - -Default: `false` - -Command line equivalent (takes precedence): `--[no-]allow-different-user` flag - -Allow users other than the owner of the [Stack root](stack_root.md) to use the -Stack installation. - -~~~yaml -allow-different-user: true -~~~ - -The intention of this option is to prevent file permission problems, for example -as the result of a Stack command executed under `sudo`. - -The option is automatically enabled when Stack is re-spawned in a Docker -process. - -### allow-newer - -[:octicons-tag-24: 0.1.8.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.8.0) - -Default: `false` - -Whether to ignore version bounds in Cabal files. This also ignores lower bounds. -The name `allow-newer` is chosen to match the commonly-used Cabal option. - - -~~~yaml -allow-newer: true -~~~ - -### allow-newer-deps - -:octicons-beaker-24: Experimental - -[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) - -Default: `none` - -Determines a subset of packages to which `allow-newer` should apply. This option -has no effect (but warns) if `allow-newer` is `false`. - -~~~yaml -allow-newer-deps: - - foo - - bar -~~~ - -### apply-ghc-options - -[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) - -Default: `locals` - -Related command line: -[`stack build --ghc-options`](build_command.md#-ghc-options-option) option - -Determines to which packages any GHC command line options specified on the -command line are applied. Possible values are: `everything` (all packages, -project packages or otherwise), `locals` (all project packages, targets or -otherwise), and `targets` (all project packages that are targets). - -!!! note - - The use of `everything` can break invariants about your snapshot database. - -!!! info - - Before Stack 0.1.6.0, the default value was `targets`. - -### apply-prog-options - -[:octicons-tag-24: 2.11.1](https://github.com/commercialhaskell/stack/releases/tag/v2.11.1) - -Default: `locals` - -Related command line: -[`stack build --PROG-option`](build_command.md#-prog-option-options) options - -Determines to which packages all and any `--PROG-option` command line options -specified on the command line are applied. Possible values are: `everything` -(all packages, project packages or otherwise), `locals` (all project packages, -targets or otherwise), and `targets` (all project packages that are targets). - -!!! note - - The use of `everything` can break invariants about your snapshot database. - -### arch - -Default: The machine architecture on which Stack is running. - -Command line equivalent (takes precedence): -[`--arch`](global_flags.md#-arch-option) option - -Stack identifies different GHC executables by platform (operating system and -machine architecture), (optional) GHC variant and (optional) GHC build. -See [`setup-info`](#setup-info). - -`arch` sets the machine architecture. Values can be those recognized by Cabal -(the library) (which are case-insensitive and include `i386`, `x86_64`, and -`aarch64` / `arm64`), or other values (which are case-sensitive and treated as -an unknown 'other' architecture of the specified name). - -By default, Stack will warn the user if the specified machine architecture is an -unknown 'other' architecture. The warning can be muted; see -[`notify-if-arch-unknown`](#notify-if-arch-unknown) - -!!! note - - The machine architecture on which Stack is running is as classified by - Cabal (the library). Cabal does not distinguish between certain - architectures. Examples are `ppc64`/`powerpc64`/`powerpc64le` (classified as - `ppc64`) and `arm`/`armel`/`armeb` (classified as `arm`). - -!!! note - - As Cabal (the library) does not distinguish between machine architectures - `powerpc64` and `powerpc64le`, the latter can be specified in Stack's - configuration as an 'other' architecture, such as `arch: ppc64le`. - -### build - -[:octicons-tag-24: 1.1.0](https://github.com/commercialhaskell/stack/releases/tag/v1.1.0) - -Default: - -~~~yaml -build: - library-profiling: false - executable-profiling: false - library-stripping: true - executable-stripping: true - - # NOTE: global usage of haddock can cause build failures when documentation is - # incorrectly formatted. This could also affect scripts which use Stack. - haddock: false - haddock-arguments: - - # Additional arguments passed to haddock. The corresponding command line - # option is --haddock-arguments. Example of use: - # - # haddock-args: - # - "--css=/home/user/my-css" - haddock-args: [] - - # The corresponding command line flag is --[no-]open. - open-haddocks: false - - # If Stack is configured to build Haddock documentation, defaults to true. - haddock-deps: false - - # The configuration is ignored, if haddock-for-hackage: true. - haddock-internal: false - - # The configuration is ignored, if haddock-for-hackage: true. - haddock-hyperlink-source: true - - # If specified, implies haddock-internal: false and - # haddock-hyperlink-source: true. Since Stack 2.15.1. - haddock-for-hackage: false - copy-bins: false - copy-compiler-tool: false - prefetch: false - keep-going: false - keep-tmp-files: false - - # These are inadvisable to use in your global configuration, as they make the - # Stack build command line behave quite differently. - force-dirty: false - test: false - test-arguments: - rerun-tests: true # Rerun successful tests - - # The corresponding command line option is --test-arguments. Example of use: - # - # additional-args: - # - "--fail-fast" - additional-args: [] - coverage: false - no-run-tests: false - bench: false - benchmark-opts: - - # Example of use: - # - # benchmark-arguments: "--csv bench.csv" - benchmark-arguments: "" - no-run-benchmarks: false - reconfigure: false - cabal-verbosity: normal - cabal-verbose: false - split-objs: false - skip-components: [] # --skip - - # Since Stack 1.8. Starting with Stack 2.0, the default is true - interleaved-output: true - - # Since Stack 2.13.1. Available options are none, count-only, capped and full. - progress-bar: capped - - # Since Stack 1.10. - ddump-dir: "" -~~~ - -Command line equivalents (take precedence): Yes, see below. - -Allows setting build options which are usually specified on the command line. - -The meanings of these settings correspond directly with the command line flags -of the same name. For further information, see the -[`stack build` command](build_command.md) documentation and the -[users guide](GUIDE.md#the-build-command). - -### casa - -[:octicons-tag-24: 2.13.1](https://github.com/commercialhaskell/stack/releases/tag/v2.13.1) - -Default: - -~~~yaml -casa: - enable: true # Use a Casa server? - repo-prefix: https://casa.stackage.org # Unless casa-repo-prefix is set. - max-keys-per-request: 1280 # Maximum number of keys per request. -~~~ - -This option specifies whether or not Stack should use a Casa -(content-addressable storage archive) server to cache Cabal files and all other -files in packages; and, if so, the prefix for the URL used to pull information -from the server and the maximum number of keys per request. For further -information, see this blog post about -[Casa and Stack](https://www.fpcomplete.com/blog/casa-and-stack/). - -`repo-prefix` replaces [`casa-repo-prefix`](#casa-repo-prefix) (which is -deprecated) and has precedence if both keys are set. - -### casa-repo-prefix - -[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) - -Deprecated in favour of [`casa`](#casa), which takes precedence if present. - -Default: `https://casa.stackage.org` - -This option specifies the prefix for the URL used to pull information from the -Casa server. - -### color - -Command line equivalent (takes precedence): `--color` option - -This option specifies when to use color in output. The option is used as -`color: <WHEN>`, where `<WHEN>` is 'always', 'never', or 'auto'. On Windows -versions before Windows 10, for terminals that do not support color codes, the -default is 'never'; color may work on terminals that support color codes. - -(The British English spelling (colour) is also accepted. In yaml configuration -files, the American spelling is the alternative that has priority.) - -### compiler - -[:octicons-tag-24: 0.1.8.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.8.0) - -Command line equivalent (takes precedence): `--compiler` option - -Overrides the compiler version in the snapshot. Note that the `compiler-check` -flag also applies to the version numbers. This uses the same syntax as compiler -snapshots like `ghc-9.6.5`. This can be used to override the compiler for a -Stackage snapshot, like this: - -~~~yaml -snapshot: lts-22.21 -compiler: ghc-9.6.4 -compiler-check: match-exact -~~~ - -#### Building GHC from source - -:octicons-beaker-24: Experimental - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -Stack supports building the GHC compiler from source, using -[Hadrian](https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/README.md) (the -build system for GHC). The GHC version to build and to use is defined by a a Git -commit ID and a Hadrian "flavour", with the following syntax: - -~~~yaml -compiler: ghc-git-<commit_id>-<Hadrian_flavour> -~~~ - -In the following example the commit ID is "5be7ad..." and the flavour is -"quick": - -~~~yaml -compiler: ghc-git-5be7ad7861c8d39f60b7101fd8d8e816ff50353a-quick -~~~ - -By default, the code is retrieved from the main GHC repository. If you want to -select another repository, use the `compiler-repository` option: - -~~~yaml -compiler-repository: git://my/ghc/repository -# default -# compiler-repository: https://gitlab.haskell.org/ghc/ghc.git -~~~ - -Stack does not check the compiler version when it uses a compiler built from -source. It is assumed that the built compiler is recent enough as Stack doesn't -enable any known workaround to make older compilers work. - -Building the compiler can take a very long time (more than one hour). For faster -build times, use Hadrian flavours that disable documentation generation. - -#### Bootstrap compiler - -Building GHC from source requires a working GHC (known as the bootstrap -compiler). As we use a Stack based version of Hadrian (`hadrian/build-stack` in -GHC sources), the bootstrap compiler is configured into `hadrian/stack.yaml` and -fully managed by Stack. - -!!! note - - For some commit IDs, the snapshot specified in `hadrian/stack.yaml` - specifies a version of GHC that cannot be used to build GHC. This results in - GHC's `configure` script reporting messages similar to the following before - aborting: - - ~~~text - checking version of ghc... 9.0.2 - configure: error: GHC version 9.2 or later is required to compile GHC. - ~~~ - - The resolution is: (1) to specify an alternative snapshot (one that - specifies a sufficiently recent version of GHC) on the command line, using - Stack's option `--snapshot <snapshot>`. Stack will use that snapshot when - running GHC's `configure` script; and (2) to set the contents of the `STACK` - environment variable to be `stack --snapshot <snapshot>`. Hadrian's - `build-stack` script wil refer to that environment variable for the Stack - command it uses. - -#### Hadrian prerequisites - -The Hadrian build system has certain -[prerequisites](https://gitlab.haskell.org/ghc/ghc/-/wikis/building/preparation). -It requires certain versions of the `happy` and `alex` executables on the PATH. -Stack will build and install `happy` and `alex`, if not already on the PATH. - -=== "macOS" - - Hadrian requires, or case use, certain tools or Python packages that do not - come with macOS by default and that need to be installed using `brew` or - `pip3` (Python). Hadrian's LaTeX documentation also requires the - [DejaVu fonts](https://dejavu-fonts.github.io/) to be installed. - - ~~~zsh - brew install python@3.11 - # GHC uses a Python script named `boot`. - brew install automake - # Tool for generating GNU Standards-compliant Makefiles. - brew install texinfo - # Official documentation format of the GNU project. - pip3 install -U sphinx - # Sphinx is the Python documentation generator. - brew install --cask mactex - # MacTeX: Full TeX Live distribution with GUI applications - ~~~ - -=== "Windows" - - Hadrian requires, or can use, certain MSYS2 or Python packages that do not - come with the Stack-supplied MSYS2 by default and need to be installed - using `pacman` (MSYS2) or `pip` (Python). Hadrian's LaTeX documentation also - requires the [DejaVu fonts](https://dejavu-fonts.github.io/) to be - installed. - - ~~~pwsh - stack exec -- pacman --sync --refresh - # Synchronize MSYS2 package databases - stack exec -- pacman --sync mingw-w64-x86_64-python-pip - # The PyPA recommended tool (pip) for installing Python packages. Also - # installs Python as a dependency. GHC uses a Python script named `boot`. - # The package must be the one from the `mingw64` MSYS2 repository, as Python - # from the `msys` repository cannot interpret Windows file paths correctly. - stack exec -- pacman --sync mingw-w64-x86_64-autotools - # The GNU autotools build system, including `autoreconf`, `aclocal` - # and `make`. GHC uses a sh script named `configure` which is itself created - # from a file named `configure.ac`. - stack exec -- pacman --sync patch - # A utility to apply patch files to original sources. - stack exec -- pacman --sync texinfo - # Utilities to work with and produce manuals, ASCII text, and on-line - # documentation from a single source file, including `makeinfo`. - stack exec -- pacman --sync mingw-w64-x86_64-ca-certificates - # Common CA (certificate authority) certificates. - stack exec -- pip install -U sphinx - # Sphinx is the Python documentation generator. - ~~~ - - Hadrian may require certain LaTeX packages and may prompt for these to be - installed duing the build process. - -#### Global packages - -The GHC compiler you build from sources may depend on unreleased versions of -some global packages (e.g. Cabal). It may be an issue if a package you try to -build with this compiler depends on such global packages because Stack may not -be able to find versions of those packages (on Hackage, etc.) that are -compatible with the compiler. - -The easiest way to deal with this issue is to drop the offending packages as -follows. Instead of using the packages specified in the snapshot, the global -packages bundled with GHC will be used. - -~~~yaml -drop-packages: -- Cabal -- ... -~~~ - -Another way to deal with this issue is to add the relevant packages as -`extra-deps` built from source. To avoid mismatching versions, you can use -exactly the same commit id you used to build GHC as follows: - -~~~ -extra-deps: -- git: https://gitlab.haskell.org/ghc/ghc.git - commit: '5be7ad7861c8d39f60b7101fd8d8e816ff50353a' - subdirs: - - libraries/Cabal/Cabal - - libraries/... -~~~ - -### compiler-check - -[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) - -Default: `match-minor` - -Specifies how the compiler version in the snapshot is matched against concrete -versions. Valid values: - -* `match-minor`: make sure that the first three components match, but allow - patch-level differences. For example< 7.8.4.1 and 7.8.4.2 would both match - 7.8.4. This is useful to allow for custom patch levels of a compiler. -* `match-exact`: the entire version number must match precisely -* `newer-minor`: the third component can be increased, e.g. if your snapshot is - `ghc-7.10.1`, then 7.10.2 will also be allowed. This was the default up - through Stack 0.1.3 - -### concurrent-tests - -[:octicons-tag-24: 0.1.2.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.2.0) - -Default: `true` - -This option specifies whether test suites should be executed concurrently with -each other. The default is `true` since this is usually fine and it often means -that tests can complete earlier. However, if some test suites require exclusive -access to some resource, or require a great deal of CPU or memory resources, -then it makes sense to set this to `false`. - -~~~yaml -concurrent-tests: false -~~~ - -### configure-options - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -Related command line (takes precedence): -[`stack build --PROG-option`](build_command.md#prog-option-options) options - -`configure-options` can specify Cabal (the library) options (including -`--PROG-option` or `--PROG-options` options) for the configure step of the Cabal -build process for a named package, all project packages that are targets (using -the `$targets` key), all project packages (targets or otherwise) (using the -`$locals` key), or all packages (project packages or otherwise) (using the -`$everything` key). - -~~~yaml -configure-options: - $everything: - - --with-gcc - - /some/path - $locals: - - --happy-option=--ghc - $targets: - # Only works on platforms where GHC supports linking against shared Haskell - # libraries: - - --enable-executable-dynamic - my-package: - - --another-flag -~~~ - -On platforms where GHC supports linking against shared Haskell libraries (that -currently excludes Windows), Cabal's `--enable-executable-dynamic` flag (which -implies `--enable-shared`, unless `--disable-shared` is specified) links -dependent Haskell libraries into executables dynamically. - -### connection-count - -Default: `8` - -Integer indicating how many simultaneous downloads are allowed to happen. - -### default-template - -Default: `new-template` in the -[stack-templates](https://github.com/commercialhaskell/stack-templates/) -repository. - -This option specifies which template to use with `stack new`, when none is -specified. Other templates are listed in the -[stack-templates](https://github.com/commercialhaskell/stack-templates/) -repository. See the output of `stack templates`. - -### docker - -Command line equivalents: `--docker-*` flags and options (see -`stack --docker-help` for details). - -For further information, see the -[Docker integration](docker_integration.md#configuration) documentation. - -### dump-logs - -[:octicons-tag-24: 1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v1.3.0) - -Default: `warning` - -Command line equivalent (takes precedence): `--[no-]dump-logs` flag - -In the case of *non-interleaved* output and *more than one* target package, -Stack sends the build output from GHC for each target package to a log file, -unless an error occurs that prevents that. For further information, see the -[`stack build --[no-]interleaved-output` flag](build_command.md#-no-interleaved-output-flag) -documentation. - -The value of the `dump-logs` key controls what, if any, log file content is sent -('dumped') to the standard error stream of the console at the end of the build. -Possible values are: - -~~~yaml -dump-logs: none # don't dump the content of any log files -dump-logs: warning # dump the content of any log files that include GHC warnings -dump-logs: all # dump the content of all log files -~~~ - -At the command line, `--no-dump-logs` is equivalent to `dump-logs: none` and -`--dump-logs` is equivalent to `dump-logs: all`. - -If GHC reports an error during the build and a log file is created, that build -output will be included in the log file. Stack will also report errors during -building to the standard error stream. That stream can be piped to a file. For -example, for a file named `stderr.log`: - -~~~text -stack --no-dump-logs --color always build --no-interleaved-output 2> stderr.log -~~~ - -### extra-include-dirs - -Default: `[]` - -Command line equivalent: `--extra-include-dirs` option (repeat for each -directory) - -A list of extra paths to be searched for header files. Paths should be absolute - -~~~yaml -extra-include-dirs: -- /opt/foo/include -~~~ - -Since these are system-dependent absolute paths, it is recommended that you -specify these in your `config.yaml` file. If you control the build environment -in your project's ``stack.yaml``, perhaps through docker or other means, then it -may well make sense to include these there as well. - -### extra-lib-dirs - -Default: `[]` - -Command line equivalent: `--extra-lib-dirs` option (repeat for each directory) - -A list of extra paths to be searched for libraries. Paths should be absolute - -~~~yaml -extra-lib-dirs: -- /opt/foo/lib -~~~ - -Since these are system-dependent absolute paths, it is recommended that you -specify these in your `config.yaml` file. If you control the build environment -in your project's ``stack.yaml``, perhaps through Docker or other means, then it -may well make sense to include these there as well. - -### extra-path - -[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) - -This option specifies additional directories to prepend to the PATH. These will -be used when resolving the location of executables, and will also be visible in -the PATH of processes run by Stack. - -For example, to prepend `/path-to-some-dep/bin` to your PATH: - -~~~yaml -extra-path: -- /path-to-some-dep/bin -~~~ - -Other paths added by Stack - things like the project's binary directory and the -compiler's binary directory - will take precedence over those specified here -(the automatic paths get prepended). - -### ghc-build - -[:octicons-tag-24: 1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v1.3.0) - -Default: `standard` - -Command line equivalent (takes precedence): `--ghc-build` option - -Stack identifies different GHC executables by platform (operating system and -machine architecture), (optional) GHC variant and (optional) GHC build. -See [`setup-info`](#setup-info). - -`ghc-build` specifies a specialized architecture for the GHC executable. -Normally this is determined automatically, but it can be overridden. Possible -arguments include `standard`, `gmp4`, `nopie`, `tinfo6`, `tinfo6-libc6-pre232`, -`tinfo6-nopie`, `ncurses6`, `int-native` and `integersimple`. - -### ghc-options - -[:octicons-tag-24: 0.1.4.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.4.0) - -Default: `{}` - -Related command line (takes precedence): -[`stack build --ghc-options`](build_command.md#-ghc-options-option) option - -GHC command line options can be specified for a package in its Cabal file -(including one created from a `package.yaml` file). This option augments and, if applicable (see below), overrides any such GHC command line options. - -`ghc-options` can specify GHC command line options for a named package, all -project packages that are targets (using the `$targets` key), all project -packages (targets or otherwise) (using the `$locals` key), or all packages -(project packages or otherwise) (using the `$everything` key). - -~~~yaml -ghc-options: - "$everything": -O2 - "$locals": -Wall - "$targets": -Werror - some-package: -DSOME_CPP_FLAG -~~~ - -GHC's command line options are _order-dependent_ and evaluated from left to -right. Later options can override the effect of earlier ones. Stack applies -options (as applicable) in the order of `$everything`, `$locals`, `$targets`, -and then those for the named package. Any GHC command line options for a package -specified at Stack's command line are applied after those specified in Stack's -YAML configuration files. - -Since Stack 1.6.1, setting a GHC options for a specific package will -automatically promote it to a project package (much like setting a custom -package flag). However, setting options via `$everything` on all flags will not -do so (see -[GitHub discussion](https://github.com/commercialhaskell/stack/issues/849#issuecomment-320892095) -for reasoning). This can lead to unpredictable behavior by affecting your -snapshot packages. - -!!! info - - Before Stack 1.6.1, the key `*` (then deprecated) had the same function as - the key `$everything`. - -### ghc-variant - -[:octicons-tag-24: 0.1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.5.0) - -Default: `standard` - -Command line equivalent (takes precedence): `--ghc-variant` option - -Stack identifies different GHC executables by platform (operating system and -machine architecture), (optional) GHC variant and (optional) GHC build. -See [`setup-info`](#setup-info). - -`ghc-variant` specifies a variant of the GHC executable. Known values are: - -* `standard`: Use the standard GHC binary distribution -* `int-native`: From GHC 9.4.1, use a GHC bindist that uses the Haskell-native - big-integer - [backend](https://downloads.haskell.org/~ghc/9.0.2/docs/html/users_guide/9.0.1-notes.html#highlights). - For further information, see this [article](https://iohk.io/en/blog/posts/2020/07/28/improving-haskells-big-numbers-support/). -* `integersimple`: Use a GHC bindist that uses - [integer-simple instead of GMP](https://ghc.haskell.org/trac/ghc/wiki/ReplacingGMPNotes) -* any other value: Use a custom GHC bindist. You should specify - [setup-info](#setup-info) or [setup-info-locations](#setup-info-locations) - so `stack setup` knows where to download it, - or pass the `stack setup --ghc-bindist` argument on the command-line - -This option is incompatible with `system-ghc: true`. - -### hackage-base-url - -[:octicons-tag-24: 1.9.1](https://github.com/commercialhaskell/stack/releases/tag/v1.9.1) - -Default: `https://hackage.haskell.org/` - -Sets the address of the Hackage server to upload the package to. - -~~~yaml -hackage-base-url: https://hackage.example.com/ -~~~ - -### hide-source-paths - -Default: `true` -([:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1)) - -Whether to use the `-fhide-source-paths` option by default for GHC >= 8.2: - -~~~yaml -hide-source-paths: false -~~~ - -Build output when enabled: - -~~~text -... -[1 of 2] Compiling Lib -[2 of 2] Compiling Paths_test_pr -... -~~~ - -Build output when disabled: - -~~~text -... -[1 of 2] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/Lib.o ) -... -~~~ - -### hide-th-loading - -Default: `true` - -Strip out the "Loading ..." lines from GHC build output, produced when using -Template Haskell. - -### ignore-revision-mismatch - -(Removed 1.11) - -This flag was introduced in Stack 1.6, and removed on the move to Pantry. You -will receive a warning if this configuration value is set. - -### install-ghc - -Default: `true` -([:octicons-tag-24: 1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v1.5.0)) - -Command line equivalent (takes precedence): `--[no-]install-ghc` flag - -Whether or not to automatically install GHC when necessary. - -### jobs - -Default: the number of CPUs (cores) that the machine has. - -Command line equivalent (takes precedence): -[`-j`, `--jobs` option](global_flags.md#-jobs-or-j-option) - -Specifies the number of concurrent jobs (principally, Stack actions during -building - see further below) to run. - -When [building GHC from source](#building-ghc-from-source), specifies the -`-j[<n>]` flag of GHC's Hadrian build system. - -In some circumstances, the default can cause some machines to run out of memory -during building. If those circumstances arise, specify `jobs: 1`. - -This configuration option is distinct from GHC's own `-j[<n>]` flag, which -relates to parallel compilation of modules within a package. - -### local-bin-path - -Default (on Unix-like operating systems): `~/.local/bin` - -Default (on Windows): `%APPDATA%\local\bin` - -Command line equivalent (takes precedence): `--local-bin-path` option - -Specifies the target directory for -[`stack build --copy-bins`](build_command.md#-no-copy-bins-flag) and -`stack install`. An absolute or relative path can be specified. - -If the project-level configuration is provided in the `global-project` directory -in the [Stack root](stack_root.md), a relative path is assumed to be relative to -the current directory. Otherwise, it is assumed to be relative to the directory -of the project-level configuration file. - -### local-programs-path - -[:octicons-tag-24: 1.3.0](https://github.com/commercialhaskell/stack/releases/tag/v1.3.0) - -This overrides the location of the Stack 'programs' directory, where tools like -GHC get installed. The path must be an absolute one. - -Stack's defaults differ between Unix-like operating systems and Windows. - -=== "Unix-like" - - Default: `programs` directory in the [Stack root](stack_root.md). - -=== "Windows" - - Default: `%LOCALAPPDATA%\Programs\stack`, if the `%LOCALAPPDATA%` - environment variable exists. Otherwise, the `programs` directory in the - [Stack root](stack_root.md). - - The MSYS2 tool is also installed in the Stack 'programs' directory. - - !!! warning - - If there is a space character in the path to Stack's 'programs' - directory this may cause problems with building packages that make use - of the GNU project's `autoconf` package and `configure` shell script - files. That may be the case particularly if there is no corresponding - short name ('8 dot 3' name) for the directory in the path with the space - (which may be the case if '8 dot 3' names have been stripped or their - creation not enabled by default). If there are problems building, it - will be necessary to specify an alternative path that does not contain - space characters. Examples of packages on Hackage that make use of - `configure` are `network` and `process`. - -### modify-code-page - -[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) - -Restrictions: Windows systems only. - -Default: `true` - -Command line equivalent (takes precedence): `--[no-]modify-code-page` flag - -Whether to modify the code page for UTF-8 output. - -~~~yaml -modify-code-page: false -~~~ - -### nix - -[:octicons-tag-24: 0.1.10.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.10.0) - -Default: - -~~~yaml -nix: - enable: false # Except on NixOS, where `enable: true` - pure: true - packages: [] - shell-file: - nix-shell-options: [] - path: [] - add-gc-roots: false -~~~ - -Command line equivalents: `--nix-*` flags and options (see `stack --nix-help` -for details). - -For further information, see the -[Nix integration](nix_integration.md#configuration) documentation. - -### notify-if-arch-unknown - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -Default: `true` - -If the specified machine architecture value is unknown to Cabal (the library), -should Stack notify the user of that? - -### notify-if-cabal-untested - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -Default: `true` - -If Stack has not been tested with the version of Cabal (the library) that has -been found, should Stack notify the user of that? - -### notify-if-ghc-untested - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -Default: `true` - -If Stack has not been tested with the version of GHC that is being used, should -Stack notify the user of that? - -### notify-if-nix-on-path - -[:octicons-tag-24: 2.15.1](https://github.com/commercialhaskell/stack/releases/tag/v2.15.1) - -Default: `true` - -If Stack's integration with the Nix package manager is not enabled, should Stack -notify the user if a `nix` executable is on the PATH? - -### package-index - -[:octicons-tag-24: 2.9.3](https://github.com/commercialhaskell/stack/releases/tag/v2.9.3) - -Default: - -~~~yaml -package-index: - download-prefix: https://hackage.haskell.org/ - hackage-security: - keyids: - - 0a5c7ea47cd1b15f01f5f51a33adda7e655bc0f0b0615baa8e271f4c3351e21d - - 1ea9ba32c526d1cc91ab5e5bd364ec5e9e8cb67179a471872f6e26f0ae773d42 - - 2c6c3627bd6c982990239487f1abd02e08a02e6cf16edb105a8012d444d870c3 - - 51f0161b906011b52c6613376b1ae937670da69322113a246a09f807c62f6921 - - fe331502606802feac15e514d9b9ea83fee8b6ffef71335479a2e68d84adc6b0 - key-threshold: 3 - ignore-expiry: true -~~~ - -Takes precedence over the `package-indices` key, which is deprecated. - -Specify the package index. The index must use the -[Hackage Security](https://hackage.haskell.org/package/hackage-security) format. -This setting is most useful for providing a mirror of the official Hackage -server for - -* bypassing a firewall; or -* faster downloads. - -If the setting specifies an index that does not mirror Hackage, it is likely -that will result in significant breakage, including most snapshots failing to -work. - -In the case of Hackage, the keys of its root key holders are contained in the -`haskell-infra/hackage-root-keys` -[repository](https://github.com/haskell-infra/hackage-root-keys). The Hackage -package index is signed. A signature is valid when three key holders have -signed. The Hackage timestamp is also signed. A signature is valid when one key -holder has signed. - -If the `hackage-security` key is absent, the Hackage Security configuration will -default to that for the official Hackage server. - -`key-threshold` specifies the minimum number of keyholders that must have signed -the package index for it to be considered valid. - -`ignore-expiry` specifies whether or not the expiration of timestamps should be -ignored. - -### package-indices - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -Deprecated in favour of [`package-index`](#package-index), which takes -precedence if present. - -Default: - -~~~yaml -package-indices: -- download-prefix: https://hackage.haskell.org/ - hackage-security: - keyids: - - 0a5c7ea47cd1b15f01f5f51a33adda7e655bc0f0b0615baa8e271f4c3351e21d - - 1ea9ba32c526d1cc91ab5e5bd364ec5e9e8cb67179a471872f6e26f0ae773d42 - - 2c6c3627bd6c982990239487f1abd02e08a02e6cf16edb105a8012d444d870c3 - - 51f0161b906011b52c6613376b1ae937670da69322113a246a09f807c62f6921 - - fe331502606802feac15e514d9b9ea83fee8b6ffef71335479a2e68d84adc6b0 - key-threshold: 3 - ignore-expiry: true -~~~ - -!!! info - - Before Stack 2.1.3, the default for `ignore-expiry` was `false`. For more - information, see - [issue #4928](https://github.com/commercialhaskell/stack/issues/4928). - -!!! info - - Before Stack 2.1.1, Stack had a different approach to `package-indices`. For - more information, see - [issue #4137](https://github.com/commercialhaskell/stack/issues/4137). - -Specify the package index. For further information, see the `package-index` -[documentation](#package-index). - -### pvp-bounds - -[:octicons-tag-24: 0.1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.5.0) - -Default: `none` - -Command line equivalent (takes precedence): `stack sdist --pvp-bounds` option or -`stack upload --pvp-bounds` option - -!!! warning - - As of Stack 1.6.0, this feature does not reliably work, due to issues with - the Cabal library's printer. Stack will generate a warning when a lossy - conversion occurs, in which case you may need to disable this setting. For - further information, see issue - [#3550](https://github.com/commercialhaskell/stack/issues/3550). - -When using the `sdist` and `upload` commands, this setting determines whether -the Cabal file's dependencies should be modified to reflect PVP lower and upper -bounds. - -#### Basic use - -Values are `none` (unchanged), `upper` (add upper bounds), `lower` (add -lower bounds), and both (and upper and lower bounds). The algorithm Stack -follows is: - -* If an upper or lower bound (other than `>= 0` - 'any version') already exists - on a dependency, it is left alone -* When adding a lower bound, Stack looks at the current version specified by - `stack.yaml`, and sets it as the lower bound (e.g., `foo >= 1.2.3`) -* When adding an upper bound, Stack sets it as less than the next major version - (e.g., `foo < 1.3`) - -~~~yaml -pvp-bounds: none -~~~ - -For further information, see the announcement -[blog post](https://www.fpcomplete.com/blog/2015/09/stack-pvp). - -#### Use with Cabal file revisions - -[:octicons-tag-24: 1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v1.5.0) - -Each of the values listed above supports adding `-revision` to the end of the -value, e.g. `pvp-bounds: both-revision`. This means that, when uploading to -Hackage, Stack will first upload your tarball with an unmodified Cabal file, and -then upload a Cabal file revision with the PVP bounds added. - -This can be useful - especially combined with the -[Stackage no-revisions feature](http://www.snoyman.com/blog/2017/04/stackages-no-revisions-field) - -as a method to ensure PVP compliance without having to proactively fix bounds -issues for Stackage maintenance. - -### recommend-stack-upgrade - -[:octicons-tag-24: 2.1.1](https://github.com/commercialhaskell/stack/releases/tag/v2.1.1) - -Default: `true` - -When Stack notices that a new version of Stack is available, should it notify -the user? - -### rebuild-ghc-options - -[:octicons-tag-24: 0.1.6.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.6.0) - -Default: `false` - -Should Stack rebuild a package when its GHC options change? - -The default value reflects that, in most cases, GHC options are used to affect -optimization levels and warning behavior, for which GHC does not recompile the -modules. - -!!! info - - Before Stack 0.1.6.0, Stack rebuilt a package when its GHC options changed. - -### require-stack-version - -Default: `"-any"` - -Require a version of Stack within the specified range -([cabal-style](https://www.haskell.org/cabal/users-guide/developing-packages.html#build-information)) -to be used for this project. Example: `require-stack-version: "== 0.1.*"` - -### save-hackage-creds - -[:octicons-tag-24: 1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v1.5.0) - -Default: `true` - -Controls whether, when using `stack upload`, the user's Hackage username and -password are stored in a local file. - -~~~yaml -save-hackage-creds: true -~~~ - -### setup-info - -[:octicons-tag-24: 0.1.5.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.5.0) - -The `setup-info` dictionary specifies download locations for tools to be -installed during set-up, such as GHC or, on Windows, 7z and MSYS2. The -dictionary maps `('Tool', 'Platform', 'Version')` to the location where it can -be obtained. For example, mapping `(GHC, 64-bit Windows, 9.2.3)` to the URL -hosting the archive file for GHC's installation. - -Possible usages of this configuration option are: - -1. Using Stack offline or behind a firewall. -2. Extending the tools known to Stack, such as cutting-edge versions of GHC or - builds for custom Linux distributions (for use with the - [ghc-variant](#ghc-variant) option). - -By default, Stack obtains the dictionary from -[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml). - -The `setup-info` dictionary is constructed in the following order: - -1. `setup-info` in the YAML configuration - inline configuration -2. `--setup-info-yaml` command line arguments - URLs or paths. Multiple - locations may be specified. -3. `setup-info-locations` in the YAML configuration - URLs or paths. See further - below. - -The format of this key is the same as in the default -[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml). -For example, GHC 9.2.3 of custom variant `myvariant` (see further below) on -64-bit Windows: - -~~~yaml -setup-info: - ghc: - windows64-custom-myvariant: - 9.2.3: - url: "https://example.com/ghc-9.2.3-x86_64-unknown-mingw32-myvariant.tar.xz" -~~~ - -'Platforms' are pairs of an operating system and a machine architecture (for -example, 32-bit i386 or 64-bit x86-64) (represented by the -`Cabal.Distribution.Systems.Platform` type). Stack currently (version 2.15.1) -supports the following pairs in the format of the `setup-info` key: - -|Operating system|I386 arch|X86_64 arch|Other machine architectures | -|----------------|---------|-----------|------------------------------------------------------------| -|Linux |linux32 |linux64 |AArch64: linux-aarch64, Arm: linux-armv7, Sparc: linux-sparc| -|OSX |macosx |macosx | | -|Windows |windows32|windows64 | | -|FreeBSD |freebsd32|freebsd64 |AArch64: freebsd-aarch64 | -|OpenBSD |openbsd32|openbsd64 | | - -For GHC, the distinguishing 'Version' in the key format includes a 'tag' for -any (optional) GHC variant (see [ghc-variant](#ghc-variant)) and a further 'tag' -for any (optional) specialised GHC build (see [ghc-build](#ghc-build)). - -The optional variant 'tag' is either `-integersimple` or -`-custom-<custom_variant_name>`. - -For example, for GHC 9.0.2 of specialised GHC build `tinfo6` on x86_64 Linux: -~~~yaml -setup-info: - ghc: - linux64-tinfo6: - 9.0.2: - url: "http://downloads.haskell.org/~ghc/9.0.2/ghc-9.0.2a-x86_64-fedora27-linux.tar.xz" - content-length: 237286244 - sha1: affc2aaa3e6a1c446698a884f56a0a13e57f00b4 - sha256: b2670e9f278e10355b0475c2cc3b8842490f1bca3c70c306f104aa60caff37b0 -~~~ - -On Windows, the required 7z executable and DLL tools are represented in the -format of the `setup-info` key simply by `sevenzexe-info` and `sevenzdll-info`. - -This configuration **adds** the specified setup information metadata to the -default. Specifying this configuration **does not** prevent the default -[stack-setup-2.yaml](https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml) -from being consulted as a fallback. If, however, you need to **replace** the -default `setup-info` dictionary, use the following: - -~~~yaml -setup-info-locations: [] -~~~ - -### setup-info-locations - -[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1) - -Command line equivalent (takes precedence): `--setup-info-yaml` option - -By way of introduction, see the [`setup-info`](#setup-info) option. This option -specifies the location(s) of `setup-info` dictionaries. - -The first location which provides a dictionary that specifies the location of a -tool - `('Tool', 'Platform', 'Version')` - takes precedence. For example, you -can extend the default tools, with a fallback to the default `setup-info` -location, as follows: - -~~~yaml -setup-info-locations: -- C:/stack-offline/my-stack-setup.yaml -- relative/inside/my/project/setup-info.yaml -- \\smbShare\stack\my-stack-setup.yaml -- http://stack-mirror.com/stack-setup.yaml -# Fallback to the default location -- https://github.com/commercialhaskell/stackage-content/raw/master/stack/stack-setup-2.yaml -~~~ - -Stack only refers to the default `setup-info` location if no locations are -specified in the `setup-info-locations` configuration or on the command line -using the `--setup-info-yaml` option. - -For example, both of the following will cause `stack setup` not to consult the -default `setup-info` location: - -~~~yaml -setup-info-locations: -- C:/stack-offline/my-stack-setup.yaml -~~~ - -and - -~~~yaml -setup-info-locations: [] -~~~ - -Relative paths are resolved relative to the `stack.yaml` file (either the one in -the local project or the global `stack.yaml`). - -Relative paths may also be used for the installation paths to tools (such as GHC -or 7z). This allows vendoring the tools inside a monorepo (a single repository -storing many projects). For example: - -Directory structure: - -~~~text -- src/ -- installs/ - - my-stack-setup.yaml - - 7z.exe - - 7z.dll - - ghc-9.2.3.tar.xz -- stack.yaml -~~~ - -In the project's `stack.yaml`: - -~~~yaml -setup-info-locations: -- installs/my-stack-setup.yaml -~~~ - -In `installs/my-stack-setup.yaml`: - -~~~yaml -sevenzexe-info: - url: "installs/7z.exe" - -sevenzdll-info: - url: "installs/7z.dll" - -ghc: - windows64: - 9.2.3: - url: "installs/ghc-9.2.3.tar.xz" -~~~ - -### skip-ghc-check - -Default: `false` - -Command line equivalent (takes precedence): `--[no-]skip-ghc-check` flag - -Should we skip the check to confirm that your system GHC version (on the PATH) -matches what your project expects? - -### skip-msys - -[:octicons-tag-24: 0.1.2.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.2.0) - -Restrictions: Windows systems only - -Default: `false` - -Command line equivalent (takes precedence): -[`--[no-]skip-msys`](global_flags.md#-no-skip-msys-option) flag - -Skips checking for the Stack-supplied MSYS2 (and installing that MSYS2, if it is -not installed) when Stack is setting up the environment. - -~~~yaml -skip-msys: true -~~~ - -!!! note - - Usually, the use of this option does not make sense in project-level - configuration and it is used only in global configuration. - -### snapshot-location-base - -[:octicons-tag-24: 2.5.1](https://github.com/commercialhaskell/stack/releases/tag/v2.5.1) - -Default: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/ -(as set in the `pantry` library) - -Command line equivalent (takes precedence): `--snapshot-location-base` option - -Sets the base location of the LTS Haskell or Stackage Nightly snapshots. - -For example: - -~~~yaml -snapshot-location-base: https://example.com/snapshots/location/ -~~~ - -has the following effect: - -* `lts-X.Y` expands to `https://example.com/snapshots/location/lts/X/Y.yaml` -* `nightly-YYYY-MM-DD` expands to - `https://example.com/snapshots/location/nightly/YYYY/M/D.yaml` - -This key is convenient in setups that restrict access to GitHub, for instance -closed corporate setups. In this setting, it is common for the development -environment to have general access to the internet, but not for testing/building -environments. To avoid the firewall, one can run a local snapshots mirror and -then use a custom `snapshot-location-base` in the closed environments only. - -### stack-colors - -Command line equivalent (takes precedence): `--stack-colors` option - -Stack uses styles to format some of its output. The default styles do not work -well with every terminal theme. This option specifies Stack's output styles, -allowing new styles to replace the defaults. The option is used as -`stack-colors: <STYLES>`, where `<STYLES>` is a colon-delimited sequence of -key=value, 'key' is a style name and 'value' is a semicolon-delimited list of -'ANSI' SGR (Select Graphic Rendition) control codes (in decimal). Use the -command `stack ls stack-colors --basic` to see the current sequence. - -The 'ANSI' standards refer to (1) standard ECMA-48 'Control Functions for Coded -Character Sets' (5th edition, 1991); (2) extensions in ITU-T Recommendation -(previously CCITT Recommendation) T.416 (03/93) 'Information Technology – Open -Document Architecture (ODA) and Interchange Format: Character Content -Architectures' (also published as ISO/IEC International Standard 8613-6); and -(3) further extensions used by 'XTerm', a terminal emulator for the X Window -System. The 'ANSI' SGR codes are described in a -[Wikipedia article](http://en.wikipedia.org/wiki/ANSI_escape_code) -and those codes supported on current versions of Windows in -[Microsoft's documentation](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences). - -For example, users of the popular -[Solarized Dark](https://ethanschoonover.com/solarized/) -terminal theme might wish to set the styles as follows: - -~~~yaml -stack-colors: error=31:good=32:shell=35:dir=34:recommendation=32:target=95:module=35:package-component=95:secondary=92:highlight=32 -~~~ -In respect of styles used in verbose output, some of that output occurs before -the configuration file is processed. - -(The British English spelling (colour) is also accepted. In YAML configuration -files, the American spelling is the alternative that has priority.) - -### stack-developer-mode - -[:octicons-tag-24: 2.3.3](https://github.com/commercialhaskell/stack/releases/tag/v2.3.3) - -Default (official distributed binaries): `false` - -Default (built from source): `true` - -Turns on a mode where some messages are printed at WARN level instead of DEBUG -level, especially useful for developers of Stack itself. - -~~~yaml -stack-developer-mode: false -~~~ - -### system-ghc - -Default: `false`, unless the [Docker](docker_integration.md) or -[Nix](nix_integration.md) integration is enabled. - -Command line equivalent (takes precedence): `--[no-]system-ghc` flag - -Enables or disables using the GHC available on the PATH. (Make sure PATH is -explicit, i.e., don't use ~.) Useful to enable if you want to save the time, -bandwidth or storage space needed to setup an isolated GHC. - -In a Nix-enabled configuration, Stack is incompatible with `system-ghc: false`. - -~~~yaml -# Turn on system GHC -system-ghc: true -~~~ - -### templates - -Command line equivalent (takes precedence): `stack new --param <key>:<value>` -(or `-p`) option - -Templates used with `stack new` have a number of parameters that affect the -generated code. These can be set for all new projects you create. The result of -them can be observed in the generated LICENSE and Cabal files. The value for all -of these parameters must be strings. - -The parameters are: `author-email`, `author-name`, `category`, `copyright`, -`year` and `github-username`. - -* _author-email_ - sets the `maintainer` property in Cabal -* _author-name_ - sets the `author` property in Cabal and the name used in - LICENSE -* _category_ - sets the `category` property in Cabal. This is used in Hackage. - For examples of categories see - [Packages by category](https://hackage.haskell.org/packages/). It makes sense - for `category` to be set on a per project basis because it is uncommon for all - projects a user creates to belong to the same category. The category can be - set per project by passing `-p "category:value"` to the `stack new` command. -* _copyright_ - sets the `copyright` property in Cabal. It is typically the - name of the holder of the copyright on the package and the year(s) from which - copyright is claimed. For example: `Copyright (c) 2023-2024 Joe Bloggs` -* _year_ - if `copyright` is not specified, `year` and `author-name` are used - to generate the copyright property in Cabal. If `year` is not specified, it - defaults to the current year. -* _github-username_ - used to generate `homepage` and `source-repository` in - Cabal. For instance `github-username: myusername` and - `stack new my-project new-template` would result: - -~~~yaml -homepage: http://github.com/myusername/my-project#readme - -source-repository head - type: git - location: https://github.com/myusername/my-project -~~~ - -These properties can be set in `config.yaml` as follows: -~~~yaml -templates: - params: - author-name: Your Name - author-email: youremail@example.com - category: Your Projects Category - copyright: 'Copyright (c) 2024 Your Name' - github-username: yourusername -~~~ - -Additionally, `stack new` can automatically initialize source control -repositories in the directories it creates. Source control tools can be -specified with the `scm-init` option. At the moment, only `git` is supported. - -~~~yaml -templates: - scm-init: git -~~~ - -### urls - -Default: - -~~~yaml -urls: - latest-snapshot: https://stackage-haddock.haskell.org/snapshots.json -~~~ - -Customize the URLs where Stack looks for snapshot build plans. - -!!! note - - The default for Stack 1.3.0 to 2.15.3 was - https://s3.amazonaws.com/haddock.stackage.org/snapshots.json. Following the - handover of the Stackage project to the Haskell Foundation in - early 2024, the file at that URL may not be up to date. Users of those - versions of Stack should configure the URL to be the default above. - -### with-gcc - -Command line equivalent (takes precedence): `--with-gcc` option - -Specify a path to GCC explicitly, rather than relying on the normal path -resolution. - -~~~yaml -with-gcc: /usr/local/bin/gcc-5 -~~~ - -### with-hpack - -Command line equivalent (takes precedence): `--with-hpack` option - -Use an [Hpack](https://github.com/sol/hpack) executable, rather than Stack's -in-built version of the Hpack functionality. - -~~~yaml -with-hpack: /usr/local/bin/hpack -~~~ - -### work-dir - -[:octicons-tag-24: 0.1.10.0](https://github.com/commercialhaskell/stack/releases/tag/v0.1.10.0) - -Default: `.stack-work` - -Command line equivalent (takes precedence): -[`--work-dir`](global_flags.md#-work-dir-option) option - -Environment variable alternative (lowest precedence): -[`STACK_WORK`](environment_variables.md#stack_work) - -`work-dir` specifies the path of Stack's work directory, within a local project -or package directory. The path must be a relative one, relative to the -root directory of the project or package. The relative path cannot include a -`..` (parent directory) component. - -## Customisation scripts - -### GHC installation customisation - -[:octicons-tag-24: 2.9.1](https://github.com/commercialhaskell/stack/releases/tag/v2.9.1) - -On Unix-like operating systems and Windows, Stack's installation procedure can -be fully customised by placing a `sh` shell script (a 'hook') in the -[Stack root](stack_root.md) directory at `hooks/ghc-install.sh`. On Unix-like -operating systems, the script file must be made executable. The script is run by -the `sh` application (which is provided by MSYS2 on Windows). - -The script **must** return an exit code of `0` and the standard output **must** -be the absolute path to the GHC binary that was installed. Otherwise Stack will -ignore the script and possibly fall back to its own installation procedure. - -The script is not run when `system-ghc: true`. - -When `install-ghc: false`, the script is still run, which allows you to ensure -that only your script will install GHC and Stack won't default to its own -installation logic, even when the script fails. - -The following environment variables are always available to the script: - -* `HOOK_GHC_TYPE = "bindist" | "git" | "ghcjs"` - -For "bindist", additional variables are: - -* `HOOK_GHC_VERSION = <ver>` - -For "git", additional variables are: - -* `HOOK_GHC_COMMIT = <commit>` -* `HOOK_GHC_FLAVOR = <flavor>` - -For "ghcjs", additional variables are: - -* `HOOK_GHC_VERSION = <ver>` -* `HOOK_GHCJS_VERSION = <ver>` - -An example script is: - -~~~sh -#!/bin/sh - -set -eu - -case $HOOK_GHC_TYPE in - bindist) - # install GHC here, not printing to stdout, e.g.: - # command install $HOOK_GHC_VERSION >/dev/null - ;; - git) - >&2 echo "Hook doesn't support installing from source" - exit 1 - ;; - *) - >&2 echo "Unsupported GHC installation type: $HOOK_GHC_TYPE" - exit 2 - ;; -esac - -echo "location/to/ghc/executable" -~~~ - -If the following script is installed by GHCup, GHCup makes use of it, so that if -Stack needs a version of GHC, GHCup takes over obtaining and installing that -version: - -~~~sh -#!/bin/sh - -set -eu - -case $HOOK_GHC_TYPE in - bindist) - ghcdir=$(ghcup whereis --directory ghc "$HOOK_GHC_VERSION" || ghcup run --ghc "$HOOK_GHC_VERSION" --install) || exit 3 - printf "%s/ghc" "${ghcdir}" - ;; - git) - # TODO: should be somewhat possible - >&2 echo "Hook doesn't support installing from source" - exit 1 - ;; - *) - >&2 echo "Unsupported GHC installation type: $HOOK_GHC_TYPE" - exit 2 - ;; -esac -~~~
− src/Codec/Archive/Tar/Utf8.hs
@@ -1,182 +0,0 @@-module Codec.Archive.Tar.Utf8 - ( module Codec.Archive.Tar - , entryPath - , unpack - ) where - --- | A module that is equivalent to "Codec.Archive.Tar" from the @tar@ package, --- except that @unpack@ assumes that the file paths in an archive are UTF8 --- encoded. - -import Codec.Archive.Tar hiding ( entryPath, unpack ) -import Codec.Archive.Tar.Check ( checkSecurity ) -import Codec.Archive.Tar.Entry ( Entry (..), TarPath, fromLinkTarget ) -import qualified Codec.Archive.Tar.Entry as Tar -import Control.Exception ( Exception, catch, throwIO ) -import Data.Bits ( (.|.), (.&.), shiftL ) -import qualified Data.ByteString.Lazy as LBS -import Data.Char ( chr, ord ) -import Data.Int ( Int64 ) -import Data.Maybe ( fromMaybe ) -import Data.Time.Clock.POSIX ( posixSecondsToUTCTime ) -import System.Directory - ( copyFile, createDirectoryIfMissing, setModificationTime ) -import System.FilePath ( (</>) ) -import qualified System.FilePath as FP -import System.IO.Error ( isPermissionError ) - -type EpochTime = Int64 - --- | Native 'FilePath' of the file or directory within the archive. --- --- Assumes that the 'TarPath' of an 'Entry' is UTF8 encoded. -entryPath :: Entry -> FilePath -entryPath = fromTarPath . entryTarPath - --- | Convert a 'TarPath' to a native 'FilePath'. --- --- The native 'FilePath' will use the native directory separator but it is not --- otherwise checked for validity or sanity. In particular: --- --- * The tar path may be invalid as a native path, eg the file name @\"nul\"@ --- is not valid on Windows. --- --- * The tar path may be an absolute path or may contain @\"..\"@ components. --- For security reasons this should not usually be allowed, but it is your --- responsibility to check for these conditions (eg using 'checkSecurity'). --- --- Assumes that the 'TarPath' is UTF8 encoded. -fromTarPath :: TarPath -> FilePath -fromTarPath tp = decodeIfUtf8Encoded $ Tar.fromTarPath tp - --- | Create local files and directories based on the entries of a tar archive. --- --- This is a portable implementation of unpacking suitable for portable --- archives. It handles 'NormalFile' and 'Directory' entries and has simulated --- support for 'SymbolicLink' and 'HardLink' entries. Links are implemented by --- copying the target file. This therefore works on Windows as well as Unix. --- All other entry types are ignored, that is they are not unpacked and no --- exception is raised. --- --- If the 'Entries' ends in an error then it is raised an an exception. Any --- files or directories that have been unpacked before the error was --- encountered will not be deleted. For this reason you may want to unpack --- into an empty directory so that you can easily clean up if unpacking fails --- part-way. --- --- On its own, this function only checks for security (using 'checkSecurity'). --- You can do other checks by applying checking functions to the 'Entries' that --- you pass to this function. For example: --- --- > unpack dir (checkTarbomb expectedDir entries) --- --- If you care about the priority of the reported errors then you may want to --- use 'checkSecurity' before 'checkTarbomb' or other checks. --- --- Assumes that the 'TarPath' of an `Entry` is UTF8 encoded. -unpack :: Exception e => FilePath -> Entries e -> IO () -unpack baseDir entries = unpackEntries [] (checkSecurity entries) - >>= emulateLinks - - where - -- We're relying here on 'checkSecurity' to make sure we're not scribbling - -- files all over the place. - - unpackEntries _ (Fail err) = either throwIO throwIO err - unpackEntries links Done = return links - unpackEntries links (Next entry es) = case entryContent entry of - NormalFile file _ -> extractFile path file mtime - >> unpackEntries links es - Directory -> extractDir path mtime - >> unpackEntries links es - HardLink link -> (unpackEntries $! saveLink path link links) es - SymbolicLink link -> (unpackEntries $! saveLink path link links) es - _ -> unpackEntries links es --ignore other file types - where - path = entryPath entry - mtime = entryTime entry - - extractFile path content mtime = do - -- Note that tar archives do not make sure each directory is created - -- before files they contain, indeed we may have to create several - -- levels of directory. - createDirectoryIfMissing True absDir - LBS.writeFile absPath content - setModTime absPath mtime - where - absDir = baseDir </> FP.takeDirectory path - absPath = baseDir </> path - - extractDir path mtime = do - createDirectoryIfMissing True absPath - setModTime absPath mtime - where - absPath = baseDir </> path - - saveLink path link links = seq (length path) - $ seq (length link') - $ (path, link'):links - where link' = fromLinkTarget link - - emulateLinks = mapM_ $ \(relPath, relLinkTarget) -> - let absPath = baseDir </> relPath - absTarget = FP.takeDirectory absPath </> relLinkTarget - in copyFile absTarget absPath - -setModTime :: FilePath -> EpochTime -> IO () -setModTime path t = - setModificationTime path (posixSecondsToUTCTime (fromIntegral t)) - `catch` \e -> - if isPermissionError e then return () else throwIO e - --- | If the given 'String' can be interpreted as a string of bytes that encodes --- a string using UTF8, then yields the string decoded, otherwise yields the --- given 'String'. - --- Inspired by the utf8-string package. -decodeIfUtf8Encoded :: String -> String -decodeIfUtf8Encoded s = fromMaybe s $ decode s - where - decode :: String -> Maybe String - decode [] = Just "" - decode (c:cs) - | c' < 0x80 = decode' c cs - | c' < 0xc0 = Nothing - | c' < 0xe0 = multi1 - | c' < 0xf0 = multiByte 2 0b1111 0x00000800 - | c' < 0xf8 = multiByte 3 0b0111 0x00010000 - | c' < 0xfc = multiByte 4 0b0011 0x00200000 - | c' < 0xfe = multiByte 5 0b0001 0x04000000 - | otherwise = Nothing - where - c' = ord c - isValidByte b = b <= 0xff && b .&. 0b11000000 == 0b10000000 - combine b1 b2 = (b1 `shiftL` 6) .|. (b2 .&. 0b00111111) - multi1 = case cs of - c1:ds | isValidByte c1' -> - let d = combine (c' .&. 0b00011111) c1' - in if d >= 0x80 - then decode' (chr d) ds - else Nothing - where - c1' = ord c1 - _ -> Nothing - multiByte :: Int -> Int -> Int -> Maybe String - multiByte i mask overlong = aux i cs (c' .&. mask) - where - aux 0 rs acc - | isValidAcc = decode' (chr acc) rs - | otherwise = Nothing - where - isValidAcc = overlong <= acc - && acc <= 0x10ffff - && (acc < 0xd800 || 0xdfff < acc) - && (acc < 0xfffe || 0xffff < acc) - aux n (r : rs) acc | isValidByte r' = aux (n - 1) rs $ combine acc r' - where - r' = ord r - aux _ _ _ = Nothing - decode' :: Char -> String -> Maybe String - decode' x xs = do - xs' <- decode xs - pure $ x : xs'
src/Data/Attoparsec/Interpreter.hs view
@@ -27,14 +27,14 @@ Here is an example of a single line comment: > #!/usr/bin/env stack - > -- stack --resolver lts-3.14 --install-ghc runghc --package random + > -- stack --snapshot lts-3.14 --install-ghc runghc --package random Here is an example of a multi line block comment: @ #!\/usr\/bin\/env stack {\- stack - --resolver lts-3.14 + --snapshot lts-3.14 --install-ghc runghc --package random
src/Options/Applicative/Builder/Extra.hs view
@@ -224,8 +224,8 @@ -> IO () execExtraHelp args helpOpt parser pd = when (args == ["--" ++ helpOpt]) $ - withArgs ["--help"] $ do - _ <- execParser (info + withArgs ["--help"] $ + void $ execParser (info ( hiddenHelper <*> ( (,) <$> parser @@ -234,7 +234,6 @@ ) ) (fullDesc <> progDesc pd)) - pure () where hiddenHelper = abortOption showHelpText (long "help" <> hidden <> internal)
src/Options/Applicative/Complicated.hs view
@@ -20,9 +20,9 @@ import Options.Applicative ( Parser, ParserFailure, ParserHelp, ParserResult (..) , abortOption, command, execParserPure, footer, fullDesc - , handleParseResult, header, help, info, infoOption, long - , metavar, noBacktrack, prefs, progDesc, showHelpOnEmpty - , hsubparser + , handleParseResult, header, help, hsubparser, info + , infoOption, long, metavar, noBacktrack, prefs, progDesc + , short, showHelpOnEmpty ) import Options.Applicative.Builder.Extra ( showHelpText ) import Stack.Prelude @@ -186,4 +186,5 @@ helpOption = abortOption showHelpText $ long "help" + <> short 'h' <> help "Show this help text."
src/Path/CheckInstall.hs view
@@ -6,7 +6,6 @@ ) where import Control.Monad.Extra ( (&&^), anyM ) -import qualified Data.Text as T import Stack.Prelude import Stack.Types.Config ( HasConfig ) import qualified System.Directory as D @@ -15,7 +14,11 @@ -- | Checks if the installed executable will be available on the user's PATH. -- This doesn't use @envSearchPath menv@ because it includes paths only visible -- when running in the Stack environment. -warnInstallSearchPathIssues :: HasConfig env => FilePath -> [Text] -> RIO env () +warnInstallSearchPathIssues :: + HasConfig env + => FilePath + -> [String] + -> RIO env () warnInstallSearchPathIssues destDir installed = do searchPath <- liftIO FP.getSearchPath destDirIsInPATH <- liftIO $ @@ -26,7 +29,7 @@ searchPath if destDirIsInPATH then forM_ installed $ \exe -> do - mexePath <- (liftIO . D.findExecutable . T.unpack) exe + mexePath <- (liftIO . D.findExecutable) exe case mexePath of Just exePath -> do exeDir <- @@ -34,12 +37,12 @@ unless (exeDir `FP.equalFilePath` destDir) $ prettyWarnL [ flow "The" - , style File . fromString . T.unpack $ exe + , style File . fromString $ exe , flow "executable found on the PATH environment variable is" , style File . fromString $ exePath , flow "and not the version that was just installed." , flow "This means that" - , style File . fromString . T.unpack $ exe + , style File . fromString $ exe , "calls on the command line will not use this version." ] Nothing -> @@ -47,7 +50,7 @@ [ flow "Installation path" , style Dir . fromString $ destDir , flow "is on the PATH but the" - , style File . fromString . T.unpack $ exe + , style File . fromString $ exe , flow "executable that was just installed could not be found on \ \the PATH." ]
src/Stack.hs view
@@ -9,6 +9,7 @@ ( main ) where +import Control.Monad.Extra ( whenJust ) import GHC.IO.Encoding ( mkTextEncoding, textEncodingName ) import Options.Applicative.Builder.Extra ( execExtraHelp ) import Stack.BuildInfo ( versionString' ) @@ -80,13 +81,10 @@ global <- globalOptsFromMonoid isTerminal globalMonoid when (global.logLevel == LevelDebug) $ hPutStrLn stderr versionString' - case global.reExecVersion of - Just expectVersion -> do - expectVersion' <- parseVersionThrowing expectVersion - unless (checkVersion MatchMinor expectVersion' stackVersion) $ - throwIO $ - InvalidReExecVersion expectVersion showStackVersion - _ -> pure () + whenJust global.reExecVersion $ \expectVersion -> do + expectVersion' <- parseVersionThrowing expectVersion + unless (checkVersion MatchMinor expectVersion' stackVersion) $ + throwIO $ InvalidReExecVersion expectVersion showStackVersion withRunnerGlobal global $ run `catches` [ Handler handleExitCode , Handler handlePrettyException @@ -99,12 +97,10 @@ hSetTranslit :: Handle -> IO () hSetTranslit h = do menc <- hGetEncoding h - case fmap textEncodingName menc of - Just name - | '/' `notElem` name -> do - enc' <- mkTextEncoding $ name ++ "//TRANSLIT" - hSetEncoding h enc' - _ -> pure () + whenJust (fmap textEncodingName menc) $ \name -> + unless ('/' `elem` name) $ do + enc' <- mkTextEncoding $ name ++ "//TRANSLIT" + hSetEncoding h enc' -- | Handle ExitCode exceptions. handleExitCode :: ExitCode -> RIO Runner a
src/Stack/Build.hs view
@@ -15,11 +15,11 @@ ) where import Data.Attoparsec.Args ( EscapingMode (Escaping), parseArgs ) +import qualified Data.Either.Extra as EE import Data.List ( (\\) ) import Data.List.Extra ( groupSort ) import qualified Data.Map as Map import qualified Data.Set as Set -import qualified Data.Text as T -- import qualified Distribution.PackageDescription as C -- import Distribution.Types.Dependency ( Dependency (..), depLibraries ) import Distribution.Version ( mkVersion ) @@ -41,7 +41,7 @@ ) import Stack.Types.Build.Exception ( BuildException (..), BuildPrettyException (..) ) -import Stack.Types.BuildConfig ( HasBuildConfig, stackYamlL ) +import Stack.Types.BuildConfig ( HasBuildConfig, configFileL ) import Stack.Types.BuildOpts ( BuildOpts (..) ) import Stack.Types.BuildOptsCLI ( BuildCommand (..), BuildOptsCLI (..), FileWatchOpts (..) ) @@ -50,10 +50,11 @@ , buildOptsMonoidInstallExesL, buildOptsMonoidTestsL ) import Stack.Types.Compiler ( getGhcVersion ) -import Stack.Types.CompilerPaths ( cabalVersionL ) +import Stack.Types.CompilerPaths ( HasCompiler, cabalVersionL ) +import Stack.Types.ComponentUtils + ( StackUnqualCompName, unqualCompToString ) import Stack.Types.Config - ( Config (..), HasConfig (..), buildOptsL - ) + ( Config (..), HasConfig (..), buildOptsL ) import Stack.Types.ConfigureOpts ( BaseConfigOpts (..) ) import Stack.Types.EnvConfig ( EnvConfig (..), HasEnvConfig (..), HasSourceMap @@ -83,15 +84,24 @@ "[S-5973]" <> line <> fillSep - [ flow "Stack does not support Cabal versions before 1.24, but \ - \version" + [ flow "Stack builds with the version of the Cabal package that comes \ + \with the specified version of GHC. However, Stack no longer \ + \supports such Cabal versions before 2.2. Version" , fromString $ versionString cabalVer - , flow "was found. To fix this, consider updating the snapshot to" - , style Shell "lts-7.0" - , flow "or later or to" - , style Shell "nightly-2016-05-26" - , flow "or later." + , flow "was found. To fix this, either use Stack" + , downgradeRecommendation + , flow "or earlier or use a snapshot that specifies a version of GHC \ + \that is 8.4 or later. Stackage LTS Haskell 12.0" + , parens (style Shell "lts-12.0") + , flow "or later or Nightly 2018-03-13" + , parens (style Shell "nightly-2018-03-13") + , flow "or later specify such GHC versions." ] + where + -- Due to a bug, Stack 2.15.1 does not support Cabal < 2. + downgradeRecommendation = if cabalVer < mkVersion [2] + then "2.15.3 or 2.13.1" + else "2.15.3" instance Exception CabalVersionPrettyException @@ -102,15 +112,20 @@ prettyThrowIO GHCProfOptionInvalid local (over globalOptsL modifyGO) $ case opts.fileWatch of - FileWatchPoll -> fileWatchPoll (inner . Just) - FileWatch -> fileWatch (inner . Just) + FileWatchPoll -> withFileWatchHook fileWatchPoll + FileWatch -> withFileWatchHook fileWatch NoFileWatch -> inner Nothing where + withFileWatchHook fileWatchAction = + -- This loads the full configuration in order to obtain the file-watch-hook + -- setting. That is likely not the most efficient approach. + withConfig YesReexec $ withEnvConfig NeedTargets opts $ + fileWatchAction (inner . Just) inner :: Maybe (Set (Path Abs File) -> IO ()) -> RIO Runner () inner setLocalFiles = withConfig YesReexec $ withEnvConfig NeedTargets opts $ - Stack.Build.build setLocalFiles + Stack.Build.build setLocalFiles -- Read the build command from the CLI and enable it to run modifyGO = case opts.command of @@ -144,11 +159,13 @@ sourceMap <- view $ envConfigL . to (.sourceMap) locals <- projectLocalPackages depsLocals <- localDependencies - let allLocals = locals <> depsLocals - boptsCli <- view $ envConfigL . to (.buildOptsCLI) -- Set local files, necessary for file watching - stackYaml <- view stackYamlL + configFile <- view configFileL + let allLocals = locals <> depsLocals + -- We are indifferent as to whether the configuration file is a + -- user-specifc global or a project-level one. + eitherConfigFile = EE.fromEither configFile for_ msetLocalFiles $ \setLocalFiles -> do files <- if boptsCli.watchAll @@ -162,7 +179,7 @@ lpFiles lp Just (TargetComps components) -> lpFilesForComponents components lp - liftIO $ setLocalFiles $ Set.insert stackYaml $ Set.unions files + liftIO $ setLocalFiles $ Set.insert eitherConfigFile $ Set.unions files checkComponentsBuildable allLocals @@ -185,6 +202,17 @@ localsIdents -> throwM $ LocalPackagesPresent localsIdents checkCabalVersion + haddockCompsSupported <- warnAboutHaddockComps bopts + let disableHaddockComps = + local $ over buildOptsL $ \bo -> + bo + { haddockExecutables = False + , haddockTests = False + , haddockBenchmarks = False + } + withHaddockCompsGuarded = if haddockCompsSupported + then id + else disableHaddockComps warnAboutSplitObjs bopts warnIfExecutablesWithSameNameCouldBeOverwritten locals plan @@ -192,17 +220,19 @@ preFetch plan if boptsCli.dryrun - then printPlan plan - else executePlan - boptsCli - baseConfigOpts - locals - globalDumpPkgs - snapshotDumpPkgs - localDumpPkgs - installedMap - sourceMap.targets.targets - plan + then + printPlan plan + else + withHaddockCompsGuarded $ executePlan + boptsCli + baseConfigOpts + locals + globalDumpPkgs + snapshotDumpPkgs + localDumpPkgs + installedMap + sourceMap.targets.targets + plan buildLocalTargets :: HasEnvConfig env @@ -221,7 +251,7 @@ checkCabalVersion :: HasEnvConfig env => RIO env () checkCabalVersion = do cabalVer <- view cabalVersionL - when (cabalVer < mkVersion [1, 24]) $ + when (cabalVer < mkVersion [2, 2]) $ prettyThrowM $ CabalVersionNotSupported cabalVer -- | See https://github.com/commercialhaskell/stack/issues/1198. @@ -241,7 +271,7 @@ "," [ style PkgComponent - (fromString $ packageNameString p <> ":" <> T.unpack exe) + (fromString $ packageNameString p <> ":" <> unqualCompToString exe) | p <- pkgs ] prettyWarnL $ @@ -263,21 +293,21 @@ | not (null otherLocals) ] where - -- Cases of several local packages having executables with the same name. + -- Cases of several project packages having executables with the same name. -- The Map entries have the following form: -- -- executable name: ( package names for executables that are being built - -- , package names for other local packages that have an + -- , package names for other project packages that have an -- executable with the same name -- ) - warnings :: Map Text ([PackageName],[PackageName]) + warnings :: Map StackUnqualCompName ([PackageName],[PackageName]) warnings = Map.mapMaybe (\(pkgsToBuild, localPkgs) -> case (pkgsToBuild, NE.toList localPkgs \\ NE.toList pkgsToBuild) of (_ :| [], []) -> - -- We want to build the executable of single local package - -- and there are no other local packages with an executable of + -- We want to build the executable of single project package + -- and there are no other project packages with an executable of -- the same name. Nothing to warn about, ignore. Nothing (_, otherLocals) -> @@ -285,12 +315,12 @@ -- 1) We are building two or more executables with the same -- name that will end up overwriting each other. -- 2) In addition to the executable(s) that we want to build - -- there are other local packages with an executable of the + -- there are other project packages with an executable of the -- same name that might get overwritten. -- Both cases warrant a warning. Just (NE.toList pkgsToBuild, otherLocals)) (Map.intersectionWith (,) exesToBuild localExes) - exesToBuild :: Map Text (NonEmpty PackageName) + exesToBuild :: Map StackUnqualCompName (NonEmpty PackageName) exesToBuild = collect [ (exe, pkgName') @@ -298,7 +328,7 @@ , TTLocalMutable lp <- [task.taskType] , exe <- (Set.toList . exeComponents . (.components)) lp ] - localExes :: Map Text (NonEmpty PackageName) + localExes :: Map StackUnqualCompName (NonEmpty PackageName) localExes = collect [ (exe, pkg.name) @@ -307,6 +337,36 @@ ] collect :: Ord k => [(k, v)] -> Map k (NonEmpty v) collect = Map.mapMaybe nonEmpty . Map.fromDistinctAscList . groupSort + +warnAboutHaddockComps :: + (HasCompiler env, HasTerm env) + => BuildOpts + -> RIO env Bool +warnAboutHaddockComps bopts = do + let haddockCompsWanted = + bopts.haddockExecutables + || bopts.haddockTests + || bopts.haddockBenchmarks + cabalVer <- view cabalVersionL + if haddockCompsWanted && cabalVer < mkVersion [3, 8, 1] + then do + prettyWarnL + [ flow "Stack builds Haddock documentation with the version of the \ + \Cabal package that comes with the specified version of GHC. \ + \Version" + , fromString $ versionString cabalVer + , flow "was found, which does not support the building of \ + \documentation for executables, test suites or benchmarks. \ + \Options to build such documentation will be ignored. To use \ + \the options, use a snapshot that specifies a version of GHC \ + \that is 9.4 or later. Stackage LTS Haskell 21.0" + , parens (style Shell "lts-21.0") + , flow "or later or Nightly 2022-11-19" + , parens (style Shell "nightly-2022-11-19") + , flow "or later specify such GHC versions." + ] + pure False + else pure haddockCompsWanted warnAboutSplitObjs :: HasTerm env => BuildOpts -> RIO env () warnAboutSplitObjs bopts | bopts.splitObjs =
src/Stack/Build/Cache.hs view
@@ -35,7 +35,6 @@ import Data.ByteString.Builder ( byteString ) import qualified Data.Map as M import qualified Data.Set as Set -import qualified Data.Text as T import qualified Data.Yaml as Yaml import Foreign.C.Types ( CTime ) import Path ( (</>), filename, parent, parseRelFile ) @@ -63,6 +62,8 @@ ) import Stack.Types.Cache ( ConfigCacheType (..) ) import Stack.Types.CompilerPaths ( cabalVersionL ) +import Stack.Types.ComponentUtils + ( StackUnqualCompName, unqualCompToString ) import Stack.Types.Config ( stackRootL ) import Stack.Types.ConfigureOpts ( BaseConfigOpts (..), ConfigureOpts (..) ) @@ -74,10 +75,11 @@ import Stack.Types.GhcPkgId ( ghcPkgIdString ) import Stack.Types.Installed (InstalledLibraryInfo (..), foldOnGhcPkgId' ) -import Stack.Types.NamedComponent ( NamedComponent (..) ) +import Stack.Types.NamedComponent + ( NamedComponent (..), componentCachePath ) import Stack.Types.SourceMap ( smRelDir ) import System.PosixCompat.Files - ( modificationTime, getFileStatus, setFileTimes ) + ( getFileStatus, modificationTime, setFileTimes ) -- | Directory containing files to mark an executable as installed exeInstalledDir :: (HasEnvConfig env) @@ -134,14 +136,7 @@ cachesDir <- buildCachesDir dir smh <- view $ envConfigL . to (.sourceMapHash) smDirName <- smRelDir smh - let nonLibComponent prefix name = prefix <> "-" <> T.unpack name - cacheFileName <- parseRelFile $ case component of - CLib -> "lib" - CSubLib name -> nonLibComponent "sub-lib" name - CFlib name -> nonLibComponent "flib" name - CExe name -> nonLibComponent "exe" name - CTest name -> nonLibComponent "test" name - CBench name -> nonLibComponent "bench" name + cacheFileName <- parseRelFile $ componentCachePath component pure $ cachesDir </> smDirName </> cacheFileName -- | Try to read the dirtiness cache for the given package directory. @@ -376,7 +371,7 @@ -> ConfigureOpts -> Bool -- ^ build haddocks -> Installed -- ^ library - -> Set Text -- ^ executables + -> Set StackUnqualCompName -- ^ executables -> RIO env () writePrecompiledCache baseConfigOpts @@ -390,7 +385,7 @@ ec <- view envConfigL let stackRootRelative = makeRelative (view stackRootL ec) exes' <- forM (Set.toList exes) $ \exe -> do - name <- parseRelFile $ T.unpack exe + name <- parseRelFile $ unqualCompToString exe stackRootRelative $ baseConfigOpts.snapInstallRoot </> bindirSuffix </> name let installedLibToPath libName ghcPkgId pcAction = do
src/Stack/Build/ConstructPlan.hs view
@@ -30,7 +30,7 @@ import Stack.Constants ( compilerOptionsCabalFlag ) import Stack.Package ( applyForceCustomBuild, buildableExes, packageUnknownTools - , processPackageDepsToList + , processPackageDepsEither ) import Stack.Prelude hiding ( loadPackage ) import Stack.SourceMap ( getPLIVersion, mkProjectPackage ) @@ -41,16 +41,17 @@ , taskProvides, taskTargetIsMutable, toCachePkgSrc ) import Stack.Types.Build.ConstructPlan - ( AddDepRes (..), CombinedMap, Ctx (..), M, PackageInfo (..) - , ToolWarning(..), UnregisterState (..), W (..) - , adrHasLibrary, adrVersion, toTask + ( AddDepRes (..), CombinedMap, Ctx (..), M + , MissingPresentDeps (..), PackageInfo (..), ToolWarning(..) + , UnregisterState (..), W (..), adrHasLibrary, adrVersion + , isAdrToInstall, toTask ) import Stack.Types.Build.Exception ( BadDependency (..), BuildException (..) , BuildPrettyException (..), ConstructPlanException (..) ) import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), stackYamlL ) + ( BuildConfig (..), HasBuildConfig (..), configFileL ) import Stack.Types.BuildOpts ( BuildOpts (..) ) import Stack.Types.BuildOptsCLI ( BuildOptsCLI (..), BuildSubset (..) ) @@ -58,9 +59,9 @@ import Stack.Types.Compiler ( WhichCompiler (..) ) import Stack.Types.CompilerPaths ( CompilerPaths (..), HasCompiler (..) ) +import Stack.Types.ComponentUtils ( unqualCompFromText ) import Stack.Types.Config ( Config (..), HasConfig (..), stackRootL ) -import Stack.Types.ConfigureOpts - ( BaseConfigOpts (..), ConfigureOpts (..) ) +import Stack.Types.ConfigureOpts ( BaseConfigOpts (..) ) import qualified Stack.Types.ConfigureOpts as ConfigureOpts import Stack.Types.Curator ( Curator (..) ) import Stack.Types.Dependency ( DepValue (..), isDepTypeLibrary ) @@ -97,7 +98,7 @@ -- and the interdependencies among the build 'Task's. In particular: -- -- 1) It determines which packages need to be built, based on the transitive --- deps of the current targets. For local packages, this is indicated by the +-- deps of the current targets. For project packages, this is indicated by the -- 'lpWanted' boolean. For extra packages to build, this comes from the -- @extraToBuild0@ argument of type @Set PackageName@. These are usually -- packages that have been specified on the command line. @@ -187,13 +188,13 @@ else Map.empty } else do - stackYaml <- view stackYamlL + configFile <- view configFileL stackRoot <- view stackRootL isImplicitGlobal <- view $ configL . to (isPCGlobalProject . (.project)) prettyThrowM $ ConstructPlanFailed errs - stackYaml + configFile stackRoot isImplicitGlobal parents @@ -312,7 +313,7 @@ pure $ pPackages <> deps -- | Determine which packages to unregister based on the given tasks and --- already registered local packages. +-- already registered project packages and local extra-deps. mkUnregisterLocal :: Map PackageName Task -- ^ Tasks @@ -432,26 +433,27 @@ -> Bool -- ^ Should Haddock documentation be built? -> M () -addFinal lp package isAllInOne buildHaddocks = do +addFinal lp package allInOne buildHaddocks = do depsRes <- addPackageDeps package res <- case depsRes of Left e -> pure $ Left e - Right (missing, present, _minLoc) -> do + Right (MissingPresentDeps missing present _minLoc) -> do + let pkgConfigOpts = ConfigureOpts.packageConfigureOptsFromPackage package ctx <- ask + let configOpts = TaskConfigOpts + { missing + , envConfig = ctx.ctxEnvConfig + , baseConfigOpts = ctx.baseConfigOpts + , isLocalNonExtraDep = True + , isMutable = Mutable + , pkgConfigOpts + } pure $ Right Task - { configOpts = TaskConfigOpts missing $ \missing' -> - let allDeps = Map.union present missing' - in ConfigureOpts.configureOpts - (view envConfigL ctx) - ctx.baseConfigOpts - allDeps - True -- local - Mutable - package + { configOpts , buildHaddocks , present , taskType = TTLocalMutable lp - , allInOne = isAllInOne + , allInOne , cachePkgSrc = CacheSrcLocal (toFilePath (parent lp.cabalFP)) , buildTypeConfig = packageBuildTypeConfig package } @@ -667,9 +669,7 @@ let isAllInOne = not splitRequired adr <- installPackageGivenDeps isAllInOne lp.buildHaddocks ps tb minstalled deps - let finalAllInOne = case adr of - ADRToInstall _ | splitRequired -> False - _ -> True + let finalAllInOne = not (isAdrToInstall adr && splitRequired) -- FIXME: this redundantly adds the deps (but they'll all just -- get looked up in the map) addFinal lp tb finalAllInOne False @@ -714,9 +714,9 @@ installPackageGivenDeps isAllInOne buildHaddocks ps package minstalled deps --- | Checks if we need to install the given 'Package', given the results --- of 'addPackageDeps'. If dependencies are missing, the package is dirty, or --- it's not installed, then it needs to be installed. +-- | Checks if we need to install the given 'Package', given the results of +-- 'addPackageDeps'. If dependencies are missing, the package is dirty, or it is +-- not installed, then it needs to be installed. installPackageGivenDeps :: Bool -- ^ will the build step also build any tests? @@ -725,42 +725,42 @@ -> PackageSource -> Package -> Maybe Installed - -> ( Set PackageIdentifier - , Map PackageIdentifier GhcPkgId - , IsMutable ) + -> MissingPresentDeps -> M AddDepRes -installPackageGivenDeps isAllInOne buildHaddocks ps package minstalled - (missing, present, minMutable) = do +installPackageGivenDeps allInOne buildHaddocks ps package minstalled + (MissingPresentDeps missing present minMutable) = do let name = package.name + mRightVersionInstalled <- case minstalled of + Just installed -> if Set.null missing + then do + shouldInstall <- + checkDirtiness ps installed package present buildHaddocks + pure $ if shouldInstall then Nothing else Just installed + else do + let packageNameText = T.pack . packageNameString . pkgName + t = T.intercalate ", " $ map packageNameText (Set.toList missing) + tell mempty + { wDirty = + Map.singleton name $ "missing dependencies: " <> addEllipsis t + } + pure Nothing + Nothing -> pure Nothing ctx <- ask - mRightVersionInstalled <- case (minstalled, Set.null missing) of - (Just installed, True) -> do - shouldInstall <- - checkDirtiness ps installed package present buildHaddocks - pure $ if shouldInstall then Nothing else Just installed - (Just _, False) -> do - let t = T.intercalate ", " $ - map (T.pack . packageNameString . pkgName) (Set.toList missing) - tell mempty - { wDirty = - Map.singleton name $ "missing dependencies: " <> addEllipsis t - } - pure Nothing - (Nothing, _) -> pure Nothing let loc = psLocation ps - mutable = installLocationIsMutable loc <> minMutable + isMutable = installLocationIsMutable loc <> minMutable + pkgConfigOpts = ConfigureOpts.packageConfigureOptsFromPackage package + configOpts = TaskConfigOpts + { missing + , envConfig = ctx.ctxEnvConfig + , baseConfigOpts = ctx.baseConfigOpts + , isLocalNonExtraDep = psLocal ps + , isMutable + , pkgConfigOpts + } pure $ case mRightVersionInstalled of Just installed -> ADRFound loc installed Nothing -> ADRToInstall Task - { configOpts = TaskConfigOpts missing $ \missing' -> - let allDeps = Map.union present missing' - in ConfigureOpts.configureOpts - (view envConfigL ctx) - ctx.baseConfigOpts - allDeps - (psLocal ps) - mutable - package + { configOpts , buildHaddocks , present , taskType = @@ -768,8 +768,8 @@ PSFilePath lp -> TTLocalMutable lp PSRemote pkgLoc _version _fromSnapshot _cp -> - TTRemotePackage mutable package pkgLoc - , allInOne = isAllInOne + TTRemotePackage isMutable package pkgLoc + , allInOne , cachePkgSrc = toCachePkgSrc ps , buildTypeConfig = packageBuildTypeConfig package } @@ -798,23 +798,17 @@ -- (3) whether the package itself is mutable or immutable. addPackageDeps :: Package - -> M ( Either - ConstructPlanException - ( Set PackageIdentifier - , Map PackageIdentifier GhcPkgId - , IsMutable - ) - ) + -> M (Either ConstructPlanException MissingPresentDeps) addPackageDeps package = do checkAndWarnForUnknownTools package let pkgId = packageIdentifier package - deps <- processPackageDepsToList package (processDep pkgId) - pure $ case partitionEithers deps of + result <- processPackageDepsEither package (processDep pkgId) + pure $ case result of -- Note that the Monoid for 'IsMutable' means that if any is 'Mutable', -- the result is 'Mutable'. Otherwise the result is 'Immutable'. - ([], pairs) -> Right $ mconcat pairs - (errs, _) -> - Left $ DependencyPlanFailures package (Map.fromList errs) + Right v -> Right v + Left errs -> + Left $ DependencyPlanFailures package errs -- | Given a dependency, yields either information for an error message or a -- triple indicating: (1) if the dependency is to be installed, its package @@ -829,29 +823,32 @@ -> DepValue -- ^ The version range and dependency type of the dependency. -> M ( Either - ( PackageName - , (VersionRange, Maybe (Version, BlobKey), BadDependency) + ( Map + PackageName + (VersionRange, Maybe (Version, BlobKey), BadDependency) ) - (Set PackageIdentifier, Map PackageIdentifier GhcPkgId, IsMutable) + MissingPresentDeps ) processDep pkgId name value = do eRes <- getCachedDepOrAddDep name + let failure mLatestApp err = + Left $ Map.singleton name (range, mLatestApp, err) case eRes of Left e -> do addParent let bd = case e of UnknownPackage name' -> assert (name' == name) NotInBuildPlan DependencyCycleDetected names -> BDDependencyCycleDetected names - -- ultimately we won't show any information on this to the user, + -- Ultimately we won't show any information on this to the user; -- we'll allow the dependency failures alone to display to avoid - -- spamming the user too much + -- spamming the user too much. DependencyPlanFailures _ _ -> Couldn'tResolveItsDependencies version mLatestApplicable <- getLatestApplicableVersionAndRev name range - pure $ Left (name, (range, mLatestApplicable, bd)) + pure $ failure mLatestApplicable bd Right adr | isDepTypeLibrary value.depType && not (adrHasLibrary adr) -> - pure $ Left (name, (range, Nothing, HasNoLibrary)) + pure $ failure Nothing HasNoLibrary Right adr -> do addParent inRange <- adrInRange pkgId name range adr @@ -859,13 +856,7 @@ then pure $ Right $ processAdr adr else do mLatestApplicable <- getLatestApplicableVersionAndRev name range - pure $ Left - ( name - , ( range - , mLatestApplicable - , DependencyMismatch $ adrVersion adr - ) - ) + pure $ failure mLatestApplicable (DependencyMismatch $ adrVersion adr) where range = value.versionRange version = pkgVersion pkgId @@ -905,8 +896,11 @@ adrInRange pkgId name range adr = if adrVersion adr `withinRange` range then pure True else do - allowNewer <- view $ configL . to (.allowNewer) - allowNewerDeps <- view $ configL . to (.allowNewerDeps) + config <- view configL + allowNewerCLI <- view $ envConfigL . to (.buildOptsCLI) . to (.allowNewer) + let allowNewerConfig = config.allowNewer + allowNewer = fromFirst False $ allowNewerCLI <> allowNewerConfig + allowNewerDeps = config.allowNewerDeps if allowNewer then case allowNewerDeps of Nothing -> do @@ -989,17 +983,24 @@ -- the dependency is, or will be when installed, mutable or immutable. processAdr :: AddDepRes - -> (Set PackageIdentifier, Map PackageIdentifier GhcPkgId, IsMutable) + -> MissingPresentDeps processAdr adr = case adr of ADRToInstall task -> - (Set.singleton $ taskProvides task, Map.empty, taskTargetIsMutable task) - ADRFound loc (Executable _) -> - (Set.empty, Map.empty, installLocationIsMutable loc) - ADRFound loc (Library ident installedInfo) -> - ( Set.empty - , installedMapGhcPkgId ident installedInfo - , installLocationIsMutable loc - ) + MissingPresentDeps + { missingPackages = Set.singleton $ taskProvides task + , presentPackages = mempty + , isMutable = taskTargetIsMutable task + } + ADRFound loc installed -> + MissingPresentDeps + { missingPackages = mempty + , presentPackages = presentPackagesV + , isMutable = installLocationIsMutable loc + } + where + presentPackagesV = case installed of + Library ident installedInfo -> installedMapGhcPkgId ident installedInfo + _ -> Map.empty checkDirtiness :: PackageSource @@ -1012,13 +1013,15 @@ checkDirtiness ps installed package present buildHaddocks = do ctx <- ask moldOpts <- runRIO ctx $ tryGetFlagCache installed - let configureOpts = ConfigureOpts.configureOpts + let packageConfigureOpt = + ConfigureOpts.packageConfigureOptsFromPackage package + configureOpts = ConfigureOpts.configureOpts (view envConfigL ctx) ctx.baseConfigOpts present (psLocal ps) (installLocationIsMutable $ psLocation ps) -- should be Local i.e. mutable always - package + packageConfigureOpt components = case ps of PSFilePath lp -> Set.map (encodeUtf8 . renderComponent) lp.components @@ -1101,7 +1104,7 @@ then id else stripGhcOptions) . map T.pack - . (\(ConfigureOpts x y) -> x ++ y) + . ConfigureOpts.renderConfigureOpts . (.configureOpts) where -- options set by Stack @@ -1171,7 +1174,6 @@ fmap catMaybes $ forM unknownTools $ \toolName -> runMaybeT $ notOnPath toolName *> notPackageExe toolName *> warn toolName tell mempty { wWarnings = (map toolWarningText warnings ++) } - pure () where -- From Cabal 2.0, build-tools can specify a pre-built executable that should -- already be on the PATH. @@ -1184,7 +1186,8 @@ -- From Cabal 1.12, build-tools can specify another executable in the same -- package. notPackageExe toolName = - MaybeT $ skipIf $ collectionMember toolName p.executables + MaybeT $ skipIf $ + collectionMember (unqualCompFromText toolName) p.executables warn name = MaybeT . pure . Just $ ToolWarning (ExeName name) p.name skipIf p' = pure $ if p' then Nothing else Just ()
src/Stack/Build/Execute.hs view
@@ -19,6 +19,7 @@ , Concurrency (..), runActions ) import Control.Concurrent.STM ( check ) +import Control.Monad.Extra ( whenJust ) import qualified Data.List as L import Data.List.Split ( chunksOf ) import qualified Data.Map.Merge.Strict as Map @@ -63,6 +64,8 @@ import Stack.Types.BuildOptsMonoid ( ProgressBarFormat (..) ) import Stack.Types.Compiler ( ActualCompiler (..) ) import Stack.Types.CompilerPaths ( HasCompiler (..), getGhcPkgExe ) +import Stack.Types.ComponentUtils + ( StackUnqualCompName, unqualCompToString ) import Stack.Types.Config ( Config (..), HasConfig (..), buildOptsL ) import Stack.Types.ConfigureOpts @@ -161,7 +164,7 @@ <> line xs -> do let executableMsg (name, loc) = fillSep $ - fromString (T.unpack name) + fromString (unqualCompToString name) : "from" : ( case loc of Snap -> "snapshot" :: StyleDoc @@ -209,7 +212,7 @@ -> [LocalPackage] -> [DumpPackage] -- ^ global packages -> [DumpPackage] -- ^ snapshot packages - -> [DumpPackage] -- ^ local packages + -> [DumpPackage] -- ^ project packages and local extra-deps -> InstalledMap -> Map PackageName Target -> Plan @@ -259,7 +262,7 @@ copyExecutables :: HasEnvConfig env - => Map Text InstallLocation + => Map StackUnqualCompName InstallLocation -> RIO env () copyExecutables exes | Map.null exes = pure () copyExecutables exes = do @@ -282,23 +285,24 @@ currExe <- liftIO getExecutablePath -- needed for windows, see below installed <- forMaybeM (Map.toList exes) $ \(name, loc) -> do - let bindir = + let strName = unqualCompToString name + bindir = case loc of Snap -> snapBin Local -> localBin - mfp <- forgivingResolveFile bindir (T.unpack name ++ ext) + mfp <- forgivingResolveFile bindir (strName ++ ext) >>= rejectMissingFile case mfp of Nothing -> do prettyWarnL [ flow "Couldn't find executable" - , style Current (fromString $ T.unpack name) + , style Current (fromString strName) , flow "in directory" , pretty bindir <> "." ] pure Nothing Just file -> do - let destFile = destDir' FP.</> T.unpack name ++ ext + let destFile = destDir' FP.</> strName ++ ext prettyInfoL [ flow "Copying from" , pretty file @@ -310,7 +314,7 @@ Platform _ Windows | FP.equalFilePath destFile currExe -> windowsRenameCopy (toFilePath file) destFile _ -> D.copyFile (toFilePath file) destFile - pure $ Just (name <> T.pack ext) + pure $ Just (strName ++ ext) unless (null installed) $ do prettyInfo $ @@ -320,7 +324,7 @@ ] <> line <> bulletedList - (map (fromString . T.unpack . textDisplay) installed :: [StyleDoc]) + (map fromString installed :: [StyleDoc]) unless compilerSpecific $ warnInstallSearchPathIssues destDir' installed -- | Windows can't write over the current executable. Instead, we rename the @@ -346,11 +350,9 @@ let !testOpts = buildOpts.testOpts when testOpts.coverage deleteHpcReports cv <- view actualCompilerVersionL - case nonEmpty $ Map.toList plan.unregisterLocal of - Nothing -> pure () - Just ids -> do - localDB <- packageDatabaseLocal - unregisterPackages cv localDB ids + whenJust (nonEmpty $ Map.toList plan.unregisterLocal) $ \ids -> do + localDB <- packageDatabaseLocal + unregisterPackages cv localDB ids liftIO $ atomically $ modifyTVar' ee.localDumpPkgs $ \initMap -> foldl' (flip Map.delete) initMap $ Map.keys plan.unregisterLocal
src/Stack/Build/ExecuteEnv.hs view
@@ -14,13 +14,13 @@ , withSingleContext , ExcludeTHLoading (..) , KeepOutputOpen (..) - , ExecutableBuildStatus (..) , OutputType (..) ) where import Control.Concurrent.Companion ( Companion, withCompanion ) import Control.Concurrent.Execute ( ActionContext (..), ActionId (..), Concurrency (..) ) +import Control.Monad.Extra ( whenJust ) import Crypto.Hash ( SHA256 (..), hashWith ) import Data.Attoparsec.Text ( char, choice, digit, parseOnly ) import qualified Data.Attoparsec.Text as P ( string ) @@ -112,12 +112,6 @@ import System.FileLock ( SharedExclusive (..), withFileLock, withTryFileLock ) --- | Has an executable been built or not? -data ExecutableBuildStatus - = ExecutableBuilt - | ExecutableNotBuilt - deriving (Eq, Ord, Show) - data ExecuteEnv = ExecuteEnv { installLock :: !(MVar ()) , buildOpts :: !BuildOpts @@ -261,7 +255,7 @@ -> [LocalPackage] -> [DumpPackage] -- ^ global packages -> [DumpPackage] -- ^ snapshot packages - -> [DumpPackage] -- ^ local packages + -> [DumpPackage] -- ^ project packages and local extra-deps -> Maybe Int -- ^ largest package name, for nicer interleaved output -> (ExecuteEnv -> RIO env a) -> RIO env a @@ -294,11 +288,6 @@ setupO = setupSrcDir </> setupOName setupHsExists <- doesFileExist setupHs unless setupHsExists $ writeBinaryFileAtomic setupHs simpleSetupCode - -- See https://github.com/commercialhaskell/stack/issues/6267. Remove any - -- historical *.hi or *.o files. This can be dropped when Stack drops - -- support for the problematic versions of GHC. - ignoringAbsence (removeFile setupHi) - ignoringAbsence (removeFile setupO) let setupShimStub = "setup-shim-" ++ simpleSetupHash setupShimFileName <- parseRelFile (setupShimStub ++ ".hs") setupShimHiName <- parseRelFile (setupShimStub ++ ".hi") @@ -309,12 +298,14 @@ setupShimHsExists <- doesFileExist setupShimHs unless setupShimHsExists $ writeBinaryFileAtomic setupShimHs setupGhciShimCode + setupExe <- getSetupExe setupHs setupShimHs tempDir -- See https://github.com/commercialhaskell/stack/issues/6267. Remove any -- historical *.hi or *.o files. This can be dropped when Stack drops -- support for the problematic versions of GHC. + ignoringAbsence (removeFile setupHi) + ignoringAbsence (removeFile setupO) ignoringAbsence (removeFile setupShimHi) ignoringAbsence (removeFile setupShimO) - setupExe <- getSetupExe setupHs setupShimHs tempDir cabalPkgVer <- view cabalVersionL globalDB <- view $ compilerPathsL . to (.globalDB) let globalDumpPkgs = toDumpPackagesByGhcPkgId globalPackages @@ -454,13 +445,11 @@ noColors = do CB.takeWhile (/= 27) -- ESC mnext <- CB.head - case mnext of - Nothing -> pure () - Just x -> assert (x == 27) $ do - -- Color sequences always end with an m - CB.dropWhile (/= 109) -- m - CB.drop 1 -- drop the m itself - noColors + whenJust mnext $ \x -> assert (x == 27) $ do + -- Color sequences always end with an m + CB.dropWhile (/= 109) -- m + CB.drop 1 -- drop the m itself + noColors -- | Make a padded prefix for log messages packageNamePrefix :: ExecuteEnv -> PackageName -> String
src/Stack/Build/ExecutePackage.hs view
@@ -32,8 +32,6 @@ import qualified Distribution.Text as C import Distribution.Types.MungedPackageName ( encodeCompatPackageName ) -import Distribution.Types.UnqualComponentName - ( mkUnqualComponentName ) import Distribution.Version ( mkVersion ) import Path ( (</>), addExtension, filename, isProperPrefixOf, parent @@ -61,16 +59,13 @@ , writePackageProjectRoot, writeSetupConfigMod ) import Stack.Build.ExecuteEnv - ( ExcludeTHLoading (..), ExecutableBuildStatus (..) - , ExecuteEnv (..), KeepOutputOpen (..), OutputType (..) - , withSingleContext + ( ExcludeTHLoading (..), ExecuteEnv (..), KeepOutputOpen (..) + , OutputType (..), withSingleContext ) import Stack.Build.Source ( addUnlistedToBuildCache ) import Stack.Config.ConfigureScript ( ensureConfigureScript ) import Stack.Constants - ( bindirSuffix, compilerOptionsCabalFlag, relDirBuild - , testGhcEnvRelFile - ) + ( bindirSuffix, compilerOptionsCabalFlag, testGhcEnvRelFile ) import Stack.Constants.Config ( distDirFromDir, distRelativeDir, hpcDirFromDir , hpcRelativeDir, setupConfigFromDir @@ -93,7 +88,7 @@ import Stack.Types.Build.Exception ( BuildException (..), BuildPrettyException (..) ) import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), projectRootL ) + ( BuildConfig (..), HasBuildConfig (..), configFileRootL ) import Stack.Types.BuildOpts ( BenchmarkOpts (..), BuildOpts (..), HaddockOpts (..) , TestOpts (..) @@ -112,17 +107,22 @@ , cpWhich, getGhcPkgExe ) import qualified Stack.Types.Component as Component +import Stack.Types.ComponentUtils + ( StackUnqualCompName, toCabalName, unqualCompToString + , unqualCompToText + ) import Stack.Types.Config ( Config (..), HasConfig (..) ) import Stack.Types.ConfigureOpts ( BaseConfigOpts (..), ConfigureOpts (..) ) +import qualified Stack.Types.ConfigureOpts as ConfigureOpts import Stack.Types.Curator ( Curator (..) ) import Stack.Types.DumpPackage ( DumpPackage (..) ) import Stack.Types.EnvConfig - ( EnvConfig (..), HasEnvConfig (..), actualCompilerVersionL + ( HasEnvConfig (..), actualCompilerVersionL , appropriateGhcColorFlag ) import Stack.Types.EnvSettings ( EnvSettings (..) ) -import Stack.Types.GhcPkgId ( GhcPkgId, unGhcPkgId ) +import Stack.Types.GhcPkgId ( GhcPkgId, ghcPkgIdToText ) import Stack.Types.GlobalOpts ( GlobalOpts (..) ) import Stack.Types.Installed ( InstallLocation (..), Installed (..), InstalledMap @@ -134,12 +134,11 @@ , renderComponent ) import Stack.Types.Package - ( LocalPackage (..), Package (..), installedMapGhcPkgId + ( LocalPackage (..), Package (..), installedPackageToGhcPkgId , runMemoizedWith, simpleInstalledLib , toCabalMungedPackageName ) import Stack.Types.PackageFile ( PackageWarning (..) ) -import Stack.Types.Platform ( HasPlatform (..) ) import Stack.Types.Runner ( HasRunner, globalOptsL ) import System.IO.Error ( isDoesNotExistError ) import System.PosixCompat.Files @@ -178,16 +177,25 @@ -- an initialBuildSteps target. | ee.buildOptsCLI.initialBuildSteps && taskIsTarget task , Just (_, installed) <- Map.lookup (pkgName ident) installedMap - -> pure $ installedToGhcPkgId ident installed - Just installed -> pure $ installedToGhcPkgId ident installed + -> pure $ installedPackageToGhcPkgId ident installed + Just installed -> pure $ installedPackageToGhcPkgId ident installed _ -> throwM $ PackageIdMissingBug ident - installedToGhcPkgId ident (Library ident' libInfo) = - assert (ident == ident') (installedMapGhcPkgId ident libInfo) - installedToGhcPkgId _ (Executable _) = mempty - TaskConfigOpts missing mkOpts = task.configOpts - missingMapList <- traverse getMissing $ toList missing - let missing' = Map.unions missingMapList - configureOpts' = mkOpts missing' + let cOpts = task.configOpts + missingMapList <- traverse getMissing $ toList cOpts.missing + let pcOpts = cOpts.pkgConfigOpts + missing' = Map.unions missingMapList + -- Historically the leftermost was missing' for union preference in case of + -- collision for the return here. But unifying things with configureOpts + -- where it was the opposite resulted in this. It doesn't seem to make any + -- difference anyway. + allDepsMap = Map.union missing' task.present + configureOpts' = ConfigureOpts.configureOpts + cOpts.envConfig + cOpts.baseConfigOpts + allDepsMap + cOpts.isLocalNonExtraDep + cOpts.isMutable + pcOpts configureOpts = configureOpts' { nonPathRelated = configureOpts'.nonPathRelated ++ map T.unpack extra } deps = Set.fromList $ Map.elems missing' ++ Map.elems task.present @@ -203,7 +211,6 @@ , pkgSrc = task.cachePkgSrc , pathEnvVar = ee.pathEnvVar } - allDepsMap = Map.union missing' task.present pure (allDepsMap, cache) -- | Ensure that the configuration for the package matches what is given @@ -226,7 +233,7 @@ (guard . isDoesNotExistError) (getFileStatus (toFilePath setupConfigfp)) newSetupConfigMod <- getNewSetupConfigMod - newProjectRoot <- S8.pack . toFilePath <$> view projectRootL + newConfigFileRoot <- S8.pack . toFilePath <$> view configFileRootL -- See https://github.com/commercialhaskell/stack/issues/3554. This can be -- dropped when Stack drops support for GHC < 8.4. taskAnyMissingHackEnabled <- @@ -266,7 +273,7 @@ /= Just (ignoreComponents newConfigCache) || mOldCabalMod /= Just newCabalMod || mOldSetupConfigMod /= newSetupConfigMod - || mOldProjectRoot /= Just newProjectRoot + || mOldProjectRoot /= Just newConfigFileRoot when task.buildTypeConfig $ -- When build-type is Configure, we need to have a configure script in the @@ -288,15 +295,14 @@ exes <- forM programNames $ \(name, file) -> do mpath <- findExecutable file pure $ case mpath of - Left _ -> [] - Right x -> pure $ concat ["--with-", name, "=", x] + Left _ -> [] + Right x -> pure $ concat ["--with-", name, "=", x] + let allOpts = + concat exes + <> ConfigureOpts.renderConfigureOpts newConfigCache.configureOpts -- Configure cabal with arguments determined by - -- Stack.Types.Build.ureOpts - cabal KeepTHLoading $ "configure" : concat - [ concat exes - , newConfigCache.configureOpts.pathRelated - , newConfigCache.configureOpts.nonPathRelated - ] + -- Stack.Types.Build.configureOpts + cabal KeepTHLoading $ "configure" : allOpts -- Only write the cache for local packages. Remote packages are built in a -- temporary directory so the cache would never be used anyway. case task.taskType of @@ -308,7 +314,7 @@ -- our config mod file is newer than the file above, but this seems -- reasonable too. getNewSetupConfigMod >>= writeSetupConfigMod pkgDir - writePackageProjectRoot pkgDir newProjectRoot + writePackageProjectRoot pkgDir newConfigFileRoot pure needConfig -- | Make a padded prefix for log messages @@ -363,10 +369,6 @@ installedMap isFinalBuild = do - cabalVersion <- view $ envConfigL . to (.compilerPaths.cabalVersion) - -- The old version of Cabal (the library) copy did not allow the components - -- to be copied to be specified. - let isOldCabalCopy = cabalVersion < mkVersion [2, 0] (allDepsMap, cache) <- getConfigCache ee task installedMap enableTests enableBenchmarks let bcoSnapInstallRoot = ee.baseConfigOpts.snapInstallRoot @@ -376,75 +378,58 @@ Just precompiled -> copyPreCompiled ee task pkgId precompiled Nothing -> do curator <- view $ buildConfigL . to (.curator) - realConfigAndBuild isOldCabalCopy cache curator allDepsMap - case minstalled of - Nothing -> pure () - Just installed -> do - writeFlagCache installed cache - liftIO $ atomically $ - modifyTVar ee.ghcPkgIds $ Map.insert pkgId installed + realConfigAndBuild + ac + ee + task + installedMap + (enableTests, enableBenchmarks) + (isFinalBuild, buildingFinals) + cache + curator + allDepsMap + whenJust minstalled $ \installed -> do + writeFlagCache installed cache + liftIO $ atomically $ modifyTVar ee.ghcPkgIds $ Map.insert pkgId installed where pkgId = taskProvides task - PackageIdentifier pname _ = pkgId - doHaddock curator package = - task.buildHaddocks - && not isFinalBuild - -- Works around haddock failing on bytestring-builder since it has no - -- modules when bytestring is new enough. - && mainLibraryHasExposedModules package - -- Special help for the curator tool to avoid haddocks that are known - -- to fail - && maybe True (Set.notMember pname . (.skipHaddock)) curator - buildingFinals = isFinalBuild || task.allInOne enableTests = buildingFinals && any isCTest (taskComponents task) enableBenchmarks = buildingFinals && any isCBench (taskComponents task) - annSuffix isOldCabalCopy executableBuildStatuses = - if result == "" then "" else " (" <> result <> ")" - where - result = T.intercalate " + " $ concat - [ ["lib" | task.allInOne && hasLib] - , ["sub-lib" | task.allInOne && hasSubLib] - , ["exe" | task.allInOne && hasExe] - , ["test" | enableTests] - , ["bench" | enableBenchmarks] - ] - (hasLib, hasSubLib, hasExe) = case task.taskType of - TTLocalMutable lp -> - let package = lp.package - hasLibrary = hasBuildableMainLibrary package - hasSubLibraries = not $ null package.subLibraries - hasExecutables = not . Set.null $ - exesToBuild isOldCabalCopy executableBuildStatuses lp - in (hasLibrary, hasSubLibraries, hasExecutables) - -- This isn't true, but we don't want to have this info for upstream deps. - _ -> (False, False, False) - - realConfigAndBuild isOldCabalCopy cache mcurator allDepsMap = - withSingleContext ac ee task.taskType allDepsMap Nothing $ +realConfigAndBuild :: + forall env a. HasEnvConfig env + => ActionContext + -> ExecuteEnv + -> Task + -> Map PackageName (a, Installed) + -> (Bool, Bool) + -- ^ (enableTests, enableBenchmarks) + -> (Bool, Bool) + -- ^ (isFinalBuild, buildingFinals) + -> ConfigCache + -> Maybe Curator + -> Map PackageIdentifier GhcPkgId + -> RIO env (Maybe Installed) +realConfigAndBuild + ac + ee + task + installedMap + (enableTests, enableBenchmarks) + (isFinalBuild, buildingFinals) + cache + mcurator0 + allDepsMap + = withSingleContext ac ee task.taskType allDepsMap Nothing $ \package cabalFP pkgDir cabal0 announce _outputType -> do let cabal = cabal0 CloseOnException - executableBuildStatuses <- getExecutableBuildStatuses package pkgDir - when ( not (cabalIsSatisfied isOldCabalCopy executableBuildStatuses) - && taskIsTarget task - ) $ - prettyInfoL - [ flow "Building all executables for" - , style Current (fromPackageName package.name) - , flow "once. After a successful build of all of them, only \ - \specified executables will be rebuilt." - ] _neededConfig <- ensureConfig cache pkgDir ee.buildOpts - ( announce - ( "configure" - <> display (annSuffix isOldCabalCopy executableBuildStatuses) - ) - ) + (announce ("configure" <> display annSuffix)) cabal cabalFP task @@ -464,36 +449,58 @@ -- https://github.com/commercialhaskell/stack/issues/2787 (True, _) | null ac.downstream -> pure Nothing (_, True) | null ac.downstream || installedMapHasThisPkg -> do - initialBuildSteps isOldCabalCopy executableBuildStatuses cabal announce + initialBuildSteps cabal announce pure Nothing _ -> fulfillCuratorBuildExpectations pname - mcurator + mcurator0 enableTests enableBenchmarks Nothing - (Just <$> - realBuild isOldCabalCopy cache package pkgDir cabal0 announce executableBuildStatuses) + (Just <$> realBuild package pkgDir cabal0 announce) + where + pkgId = taskProvides task + PackageIdentifier pname _ = pkgId + doHaddock curator package = + task.buildHaddocks + && not isFinalBuild + -- Works around haddock failing on bytestring-builder since it has no + -- modules when bytestring is new enough. + && mainLibraryHasExposedModules package + -- Special help for the curator tool to avoid haddocks that are known + -- to fail + && maybe True (Set.notMember pname . (.skipHaddock)) curator - initialBuildSteps isOldCabalCopy executableBuildStatuses cabal announce = do - announce - ( "initial-build-steps" - <> display (annSuffix isOldCabalCopy executableBuildStatuses) - ) + annSuffix = if result == "" then "" else " (" <> result <> ")" + where + result = T.intercalate " + " $ concat + [ ["lib" | task.allInOne && hasLib] + , ["sub-lib" | task.allInOne && hasSubLib] + , ["exe" | task.allInOne && hasExe] + , ["test" | enableTests] + , ["bench" | enableBenchmarks] + ] + (hasLib, hasSubLib, hasExe) = case task.taskType of + TTLocalMutable lp -> + let package = lp.package + hasLibrary = hasBuildableMainLibrary package + hasSubLibraries = not $ null package.subLibraries + hasExecutables = not . Set.null $ exesToBuild lp + in (hasLibrary, hasSubLibraries, hasExecutables) + -- This isn't true, but we don't want to have this info for upstream deps. + _ -> (False, False, False) + initialBuildSteps cabal announce = do + announce ("initial-build-steps" <> display annSuffix) cabal KeepTHLoading ["repl", "stack-initial-build-steps"] realBuild :: - Bool - -- ^ Is Cabal copy limited to all libraries and executables? - -> ConfigCache - -> Package + Package -> Path Abs Dir -> (KeepOutputOpen -> ExcludeTHLoading -> [String] -> RIO env ()) -> (Utf8Builder -> RIO env ()) -- ^ A plain 'announce' function - -> Map Text ExecutableBuildStatus -> RIO env Installed - realBuild isOldCabalCopy cache package pkgDir cabal0 announce executableBuildStatuses = do + realBuild package pkgDir cabal0 announce = do let cabal = cabal0 CloseOnException wc <- view $ actualCompilerVersionL . whichCompilerL @@ -508,7 +515,6 @@ TTRemotePackage{} -> pure () -- FIXME: only output these if they're in the build plan. - let postBuildCheck _succeeded = do mlocalWarnings <- case task.taskType of TTLocalMutable lp -> do @@ -549,7 +555,7 @@ actualCompiler <- view actualCompilerVersionL () <- announce ( "build" - <> display (annSuffix isOldCabalCopy executableBuildStatuses) + <> display annSuffix <> " with " <> display actualCompiler ) @@ -562,13 +568,11 @@ case (task.taskType, task.allInOne, isFinalBuild) of (_, True, True) -> throwM AllInOneBuildBug (TTLocalMutable lp, False, False) -> - let componentOpts = - primaryComponentOptions isOldCabalCopy executableBuildStatuses lp + let componentOpts = primaryComponentOptions lp in pure (componentOpts, componentOpts) (TTLocalMutable lp, False, True) -> pure (finalComponentOptions lp, []) (TTLocalMutable lp, True, False) -> - let componentOpts = - primaryComponentOptions isOldCabalCopy executableBuildStatuses lp + let componentOpts = primaryComponentOptions lp in pure (componentOpts <> finalComponentOptions lp, componentOpts) (TTRemotePackage{}, _, _) -> pure ([], []) cabal stripTHLoading ("build" : buildOpts <> extraOpts) @@ -607,6 +611,9 @@ , [ "--haddock-option=--hyperlinked-source" | ee.buildOpts.haddockHyperlinkSource ] + , [ "--executables" | ee.buildOpts.haddockExecutables ] + , [ "--tests" | ee.buildOpts.haddockTests ] + , [ "--benchmarks" | ee.buildOpts.haddockBenchmarks ] , [ "--internal" | ee.buildOpts.haddockInternal ] , quickjump ] @@ -627,8 +634,7 @@ && (hasLibrary || hasSubLibraries || hasExecutables) when shouldCopy $ withMVar ee.installLock $ \() -> do announce "copy/register" - let copyArgs = "copy" : if isOldCabalCopy then [] else copyOpts - eres <- try $ cabal KeepTHLoading copyArgs + eres <- try $ cabal KeepTHLoading $ "copy" : copyOpts case eres of Left err@CabalExitedUnsuccessfully{} -> throwM $ CabalCopyFailed @@ -701,32 +707,20 @@ -- generating Haddocks. -- fetchAndMarkInstalledPackage :: - (HasTerm env, HasEnvConfig env) + (HasEnvConfig env, HasTerm env) => ExecuteEnv -> InstallLocation -> Package -> PackageIdentifier -> RIO env Installed fetchAndMarkInstalledPackage ee taskInstallLocation package pkgId = do - let baseConfigOpts = ee.baseConfigOpts - (installedPkgDb, installedDumpPkgsTVar) = - case taskInstallLocation of - Snap -> - ( baseConfigOpts.snapDB - , ee.snapshotDumpPkgs ) - Local -> - ( baseConfigOpts.localDB - , ee.localDumpPkgs ) + let ghcPkgIdLoader = fetchGhcPkgIdForLib ee taskInstallLocation package.name -- Only pure the sub-libraries to cache them if we also cache the main -- library (that is, if it exists) if hasBuildableMainLibrary package then do - let getAndStoreGhcPkgId = - loadInstalledPkg [installedPkgDb] installedDumpPkgsTVar - foldSubLibToMap subLib mapInMonad = do - let mungedName = toCabalMungedPackageName package.name subLib.name - maybeGhcpkgId <- - getAndStoreGhcPkgId (encodeCompatPackageName mungedName) + let foldSubLibToMap subLib mapInMonad = do + maybeGhcpkgId <- ghcPkgIdLoader (Just subLib.name) mapInMonad <&> case maybeGhcpkgId of Just v -> Map.insert subLib.name v _ -> id @@ -734,7 +728,7 @@ package.subLibraries foldSubLibToMap mempty - mGhcPkgId <- getAndStoreGhcPkgId package.name + mGhcPkgId <- ghcPkgIdLoader Nothing case mGhcPkgId of Nothing -> throwM $ Couldn'tFindPkgId package.name Just ghcPkgId -> pure $ simpleInstalledLib pkgId ghcPkgId subLibsPkgIds @@ -743,6 +737,30 @@ -- with writeFlagCache? pure $ Executable pkgId +fetchGhcPkgIdForLib :: + (HasTerm env, HasEnvConfig env) + => ExecuteEnv + -> InstallLocation + -> PackageName + -> Maybe Component.StackUnqualCompName + -> RIO env (Maybe GhcPkgId) +fetchGhcPkgIdForLib ee installLocation pkgName libName = do + let baseConfigOpts = ee.baseConfigOpts + (installedPkgDb, installedDumpPkgsTVar) = + case installLocation of + Snap -> + ( baseConfigOpts.snapDB + , ee.snapshotDumpPkgs ) + Local -> + ( baseConfigOpts.localDB + , ee.localDumpPkgs ) + let commonLoader = loadInstalledPkg [installedPkgDb] installedDumpPkgsTVar + case libName of + Nothing -> commonLoader pkgName + Just v -> do + let mungedName = encodeCompatPackageName $ toCabalMungedPackageName pkgName v + commonLoader mungedName + -- | Copy ddump-* files, if we are building finals and a non-empty ddump-dir -- has been specified. copyDdumpFilesIfNeeded :: HasEnvConfig env => Bool -> Maybe Text -> RIO env () @@ -771,53 +789,8 @@ src' <- parseRelFile src copyFile src' (destBaseDir </> filename src')) --- | Get the build status of all the package executables. Do so by --- testing whether their expected output file exists, e.g. --- --- .stack-work/dist/x86_64-osx/Cabal-1.22.4.0/build/alpha/alpha --- .stack-work/dist/x86_64-osx/Cabal-1.22.4.0/build/alpha/alpha.exe --- .stack-work/dist/x86_64-osx/Cabal-1.22.4.0/build/alpha/alpha.jsexe/ (NOTE: a dir) -getExecutableBuildStatuses :: - HasEnvConfig env - => Package - -> Path Abs Dir - -> RIO env (Map Text ExecutableBuildStatus) -getExecutableBuildStatuses package pkgDir = do - distDir <- distDirFromDir pkgDir - platform <- view platformL - fmap - Map.fromList - (mapM (checkExeStatus platform distDir) (Set.toList (buildableExes package))) - --- | Check whether the given executable is defined in the given dist directory. -checkExeStatus :: - HasLogFunc env - => Platform - -> Path b Dir - -> Text - -> RIO env (Text, ExecutableBuildStatus) -checkExeStatus platform distDir name = do - exename <- parseRelDir (T.unpack name) - exists <- checkPath (distDir </> relDirBuild </> exename) - pure - ( name - , if exists - then ExecutableBuilt - else ExecutableNotBuilt) - where - checkPath base = - case platform of - Platform _ Windows -> do - fileandext <- parseRelFile (file ++ ".exe") - doesFileExist (base </> fileandext) - _ -> do - fileandext <- parseRelFile file - doesFileExist (base </> fileandext) - where - file = T.unpack name - getPrecompiled :: - (HasEnvConfig env) + HasEnvConfig env => ConfigCache -> TaskType -> Path Abs Dir @@ -853,8 +826,13 @@ _ -> pure Nothing copyPreCompiled :: - (HasLogFunc env, HasCompiler env, HasTerm env, HasProcessContext env, HasEnvConfig env) => - ExecuteEnv + ( HasLogFunc env + , HasCompiler env + , HasTerm env + , HasProcessContext env + , HasEnvConfig env + ) + => ExecuteEnv -> Task -> PackageIdentifier -> PrecompiledCache b0 @@ -871,9 +849,9 @@ subLibNames = Set.toList $ buildableSubLibs $ case task.taskType of TTLocalMutable lp -> lp.package TTRemotePackage _ p _ -> p - toMungedPackageId :: Text -> MungedPackageId + toMungedPackageId :: StackUnqualCompName -> MungedPackageId toMungedPackageId subLib = - let subLibName = LSubLibName $ mkUnqualComponentName $ T.unpack subLib + let subLibName = LSubLibName $ toCabalName subLib in MungedPackageId (MungedPackageName pname subLibName) pversion toPackageId :: MungedPackageId -> PackageIdentifier toPackageId (MungedPackageId n v) = @@ -892,11 +870,9 @@ let pkgDb = ee.baseConfigOpts.snapDB ghcPkgExe <- getGhcPkgExe -- First unregister, silently, everything that needs to be unregistered. - case nonEmpty allToUnregister of - Nothing -> pure () - Just allToUnregister' -> catchAny - (unregisterGhcPkgIds False ghcPkgExe pkgDb allToUnregister') - (const (pure ())) + whenJust (nonEmpty allToUnregister) $ \allToUnregister' -> catchAny + (unregisterGhcPkgIds False ghcPkgExe pkgDb allToUnregister') + (const (pure ())) -- Now, register the cached conf files. forM_ allToRegister $ \libpath -> ghcPkg ghcPkgExe [pkgDb] ["register", "--force", toFilePath libpath] @@ -925,7 +901,7 @@ bindir = ee.baseConfigOpts.snapInstallRoot </> bindirSuffix loadInstalledPkg :: - ( HasCompiler env, HasProcessContext env, HasTerm env ) + (HasCompiler env, HasProcessContext env, HasTerm env) => [Path Abs Dir] -> TVar (Map GhcPkgId DumpPackage) -> PackageName @@ -940,7 +916,8 @@ pure $ Just dp.ghcPkgId _ -> throwM $ MultipleResultsBug name dps -fulfillHaddockExpectations :: (MonadUnliftIO m, HasTerm env, MonadReader env m) +fulfillHaddockExpectations :: + (MonadUnliftIO m, HasTerm env, MonadReader env m) => PackageName -> Maybe Curator -> (KeepOutputOpen -> m ()) @@ -983,7 +960,7 @@ -- coverage reports if coverage is enabled. singleTest :: HasEnvConfig env => TestOpts - -> [Text] + -> [StackUnqualCompName] -> ActionContext -> ExecuteEnv -> Task @@ -1038,7 +1015,7 @@ ] errs <- fmap Map.unions $ forM suitesToRun $ \(testName, suiteInterface) -> do - let stestName = T.unpack testName + let stestName = unqualCompToString testName (testName', isTestTypeLib) <- case suiteInterface of C.TestSuiteLibV09{} -> pure (stestName ++ "Stub", True) @@ -1102,7 +1079,7 @@ <> foldMap ( \ghcId -> "package-id " - <> display (unGhcPkgId ghcId) + <> display (ghcPkgIdToText ghcId) <> "\n" ) (pkgGhcIdList ++ thGhcId:Map.elems allDepsMap) @@ -1135,7 +1112,7 @@ <> T.intercalate " " (map showProcessArgDebug args) announce $ "test (suite: " - <> display testName + <> display (unqualCompToText testName) <> display argsDisplay <> ")" @@ -1178,7 +1155,7 @@ $ BL.fromStrict $ encodeUtf8 $ fromString $ show ( logPath - , mkUnqualComponentName (T.unpack testName) + , toCabalName testName ) else do isTerminal <- view $ globalOptsL . to (.terminal) @@ -1211,7 +1188,7 @@ let announceResult result = announce $ "Test suite " - <> display testName + <> display (unqualCompToText testName) <> " " <> result case mec of @@ -1235,15 +1212,15 @@ (package.buildType == C.Simple) exeName (packageNameString package.name) - (T.unpack testName) + (unqualCompToString testName) pure emptyResult when needHpc $ do let testsToRun' = map f testsToRun f tName = case (.interface) <$> mComponent of - Just C.TestSuiteLibV09{} -> tName <> "Stub" - _ -> tName + Just C.TestSuiteLibV09{} -> unqualCompToText tName <> "Stub" + _ -> unqualCompToText tName where mComponent = collectionLookup tName package.testSuites generateHpcReport pkgDir package testsToRun' @@ -1270,7 +1247,7 @@ -- | Implements running a package's benchmarks. singleBench :: HasEnvConfig env => BenchmarkOpts - -> [Text] + -> [StackUnqualCompName] -> ActionContext -> ExecuteEnv -> Task @@ -1280,7 +1257,7 @@ (allDepsMap, _cache) <- getConfigCache ee task installedMap False True withSingleContext ac ee task.taskType allDepsMap (Just "bench") $ \_package _cabalfp _pkgDir cabal announce _outputType -> do - let args = map T.unpack benchesToRun <> maybe [] + let args = map unqualCompToString benchesToRun <> maybe [] ((:[]) . ("--benchmark-options=" <>)) beopts.additionalArgs @@ -1298,8 +1275,11 @@ -- Do not pass `-hpcdir` as GHC option if the coverage is not enabled. -- This helps running stack-compiled programs with dynamic interpreters like -- `hint`. Cfr: https://github.com/commercialhaskell/stack/issues/997 -extraBuildOptions :: (HasEnvConfig env, HasRunner env) - => WhichCompiler -> BuildOpts -> RIO env [String] +extraBuildOptions :: + (HasEnvConfig env, HasRunner env) + => WhichCompiler + -> BuildOpts + -> RIO env [String] extraBuildOptions wc bopts = do colorOpt <- appropriateGhcColorFlag let optsFlag = compilerOptionsCabalFlag wc @@ -1312,13 +1292,8 @@ pure [optsFlag, baseOpts] -- Library, sub-library, foreign library and executable build components. -primaryComponentOptions :: - Bool - -- ^ Is Cabal copy limited to all libraries and executables? - -> Map Text ExecutableBuildStatus - -> LocalPackage - -> [String] -primaryComponentOptions isOldCabalCopy executableBuildStatuses lp = +primaryComponentOptions :: LocalPackage -> [String] +primaryComponentOptions lp = -- TODO: get this information from target parsing instead, which will allow -- users to turn off library building if desired ( if hasBuildableMainLibrary package @@ -1332,47 +1307,20 @@ ++ map (T.unpack . T.append "lib:") (getBuildableListText package.subLibraries) - ++ map - (T.unpack . T.append "exe:") - (Set.toList $ exesToBuild isOldCabalCopy executableBuildStatuses lp) + ++ Set.toList + ( Set.mapMonotonic + (\s -> "exe:" ++ unqualCompToString s) + (exesToBuild lp) + ) where package = lp.package --- | History of this function: --- --- * Normally it would do either all executables or if the user specified --- requested components, just build them. Afterwards, due to this Cabal bug --- <https://github.com/haskell/cabal/issues/2780>, we had to make Stack build --- all executables every time. --- --- * In <https://github.com/commercialhaskell/stack/issues/3229> this was --- flagged up as very undesirable behavior on a large project, hence the --- behavior below that we build all executables once (modulo success), and --- thereafter pay attention to user-wanted components. --- --- * The Cabal bug was fixed, in that the copy command of later Cabal versions --- allowed components to be specified. Consequently, Cabal may be satisified, --- even if all of a package's executables have not yet been built. -exesToBuild :: - Bool - -- ^ Is Cabal copy limited to all libraries and executables? - -> Map Text ExecutableBuildStatus - -> LocalPackage - -> Set Text -exesToBuild isOldCabalCopy executableBuildStatuses lp = - if cabalIsSatisfied isOldCabalCopy executableBuildStatuses && lp.wanted - then exeComponents lp.components - else buildableExes lp.package - --- | Do the current executables satisfy Cabal's requirements? -cabalIsSatisfied :: - Bool - -- ^ Is Cabal copy limited to all libraries and executables? - -> Map k ExecutableBuildStatus - -> Bool -cabalIsSatisfied False _ = True -cabalIsSatisfied True executableBuildStatuses = - all (== ExecutableBuilt) $ Map.elems executableBuildStatuses +-- | Either build all executables or, if the user specifies requested +-- components, just build them. +exesToBuild :: LocalPackage -> Set StackUnqualCompName +exesToBuild lp = if lp.wanted + then exeComponents lp.components + else buildableExes lp.package -- Test-suite and benchmark build components. finalComponentOptions :: LocalPackage -> [String]
src/Stack/Build/Haddock.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE OverloadedStrings #-} @@ -20,22 +21,22 @@ import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Data.Text as T -import Data.Time ( UTCTime ) import Distribution.Text ( display ) import Path - ( (</>), addExtension, fromAbsDir, fromAbsFile, fromRelDir - , parent, parseRelDir, parseRelFile + ( (</>), addExtension, dirname, fileExtension, filename + , fromAbsDir, fromAbsFile, fromRelDir, parent, parseRelDir + , parseRelFile ) import Path.Extra ( parseCollapsedAbsFile, toFilePathNoTrailingSep , tryGetModificationTime ) import Path.IO - ( copyDirRecur', doesFileExist, ensureDir, ignoringAbsence - , removeDirRecur + ( copyDirRecur, copyDirRecur', doesDirExist, doesFileExist + , ensureDir, ignoringAbsence, listDir, removeDirRecur ) import qualified RIO.ByteString.Lazy as BL -import RIO.List ( intercalate ) +import RIO.List ( intercalate, intersperse ) import RIO.Process ( HasProcessContext, withWorkingDir ) import Stack.Constants ( docDirSuffix, htmlDirSuffix, relDirAll, relFileIndexHtml ) @@ -46,14 +47,16 @@ ( CompilerPaths (..), HasCompiler (..) ) import Stack.Types.ConfigureOpts ( BaseConfigOpts (..) ) import Stack.Types.BuildOpts ( BuildOpts (..), HaddockOpts (..) ) -import Stack.Types.BuildOptsCLI ( BuildOptsCLI (..) ) +import Stack.Types.BuildOptsCLI ( BuildOptsCLI (..), BuildSubset (BSOnlyDependencies, BSOnlySnapshot) ) import Stack.Types.DumpPackage ( DumpPackage (..) ) -import Stack.Types.EnvConfig ( HasEnvConfig (..) ) +import Stack.Types.EnvConfig ( EnvConfig (..), HasEnvConfig (..) ) import Stack.Types.GhcPkgId ( GhcPkgId ) +import Stack.Types.InterfaceOpt ( InterfaceOpt (..) ) import Stack.Types.Package ( InstallLocation (..), LocalPackage (..), Package (..) ) import qualified System.FilePath as FP import Web.Browser ( openBrowser ) +import RIO.FilePath (dropTrailingPathSeparator) openHaddocksInBrowser :: HasTerm env @@ -97,8 +100,7 @@ getDocIndex _ -> getDocIndex prettyInfo $ "Opening" <+> pretty docFile <+> "in the browser." - _ <- liftIO $ openBrowser (toFilePath docFile) - pure () + void $ liftIO $ openBrowser (toFilePath docFile) -- | Determine whether we should haddock for a package. shouldHaddockPackage :: @@ -117,7 +119,7 @@ shouldHaddockDeps :: BuildOpts -> Bool shouldHaddockDeps bopts = fromMaybe bopts.buildHaddocks bopts.haddockDeps --- | Generate Haddock index and contents for local packages. +-- | Generate Haddock index and contents for project packages. generateLocalHaddockIndex :: (HasCompiler env, HasProcessContext env, HasTerm env) => BaseConfigOpts @@ -136,13 +138,13 @@ ) locals generateHaddockIndex - "local packages" + "project packages" bco dumpPackages "." (localDocDir bco) --- | Generate Haddock index and contents for local packages and their +-- | Generate Haddock index and contents for project packages and their -- dependencies. generateDepsHaddockIndex :: (HasCompiler env, HasProcessContext env, HasTerm env) @@ -161,7 +163,7 @@ ) locals depDocDir = localDepsDocDir bco generateHaddockIndex - "local packages and dependencies" + "project packages and dependencies" bco deps ".." @@ -223,7 +225,9 @@ case eindexModTime of Left _ -> True Right indexModTime -> - or [mt > indexModTime | (_, mt, _, _) <- interfaceOpts] + or [ mt > indexModTime + | mt <- map (.srcInterfaceFileModTime) interfaceOpts + ] prettyDescr = style Current (fromString $ T.unpack descr) if needUpdate then do @@ -244,7 +248,7 @@ [bco.snapDB, bco.localDB] ++ bco.buildOpts.haddockOpts.additionalArgs ++ ["--gen-contents", "--gen-index"] - ++ [x | (xs, _, _, _) <- interfaceOpts, x <- xs] + ++ [x | xs <- map (.readInterfaceArgs) interfaceOpts, x <- xs] ) else prettyInfo $ @@ -258,56 +262,113 @@ where toInterfaceOpt :: DumpPackage - -> IO (Maybe ([String], UTCTime, Path Abs File, Path Abs File)) - toInterfaceOpt DumpPackage {haddockInterfaces, packageIdent, haddockHtml} = - case haddockInterfaces of + -> IO (Maybe InterfaceOpt) + toInterfaceOpt dp = + case dp.haddockInterfaces of [] -> pure Nothing srcInterfaceFP:_ -> do - srcInterfaceAbsFile <- parseCollapsedAbsFile srcInterfaceFP - let (PackageIdentifier name _) = packageIdent + srcInterfaceFile <- parseCollapsedAbsFile srcInterfaceFP + let (PackageIdentifier name _) = dp.packageIdent + srcInterfaceDir = parent srcInterfaceFile + compInterfaceDirsAndFiles <- do + -- It is possible that the *.haddock file specified by the + -- haddock-interfaces key for an installed package may not exist. For + -- example, with GHC 9.6.6 on Windows, there is no + -- + -- ${pkgroot}/../doc/html/libraries/rts-1.0.2\rts.haddock + (srcInterfaceSubDirs, _) <- doesDirExist srcInterfaceDir >>= \case + True -> listDir srcInterfaceDir + False -> pure ([], []) + -- This assumes that Cabal (the library) `haddock --executables` for + -- component my-component of package my-package puts one *.haddock + -- file and associated files in directory: + -- + -- my-package/my-component + -- + -- Not all directories in directory my-package relate to components. + -- For example, my-package/src relates to the files for the + -- colourised code of the main library of package my-package. + let isCompInterfaceDir dir = do + (_, files) <- listDir dir + pure $ (dir, ) <$> F.find isInterface files + where + isInterface file = fileExtension file == Just ".haddock" + mapMaybeM isCompInterfaceDir srcInterfaceSubDirs + -- Lift a copy of the component's Haddock directory up to the same level + -- as the main library's Haddock directory. For compontent my-component + -- of package my-package we name the directory my-package_my-component. + let liftcompInterfaceDir dir file = do + let parentDir = parent dir + parentName = dirname parentDir + compName = dirname dir + uniqueName <- do + let parentName' = + dropTrailingPathSeparator $ toFilePath parentName + compName' = + dropTrailingPathSeparator $ toFilePath compName + parseRelDir $ parentName' <> "_" <> compName' + let destCompDir = parent parentDir </> uniqueName + destCompFile = destCompDir </> filename file + ignoringAbsence (removeDirRecur destCompDir) + ensureDir destCompDir + onException + (copyDirRecur dir destCompDir) + (ignoringAbsence (removeDirRecur destCompDir)) + pure (destCompFile, uniqueName) destInterfaceRelFP = docRelFP FP.</> - packageIdentifierString packageIdent FP.</> + packageIdentifierString dp.packageIdent FP.</> (packageNameString name FP.<.> "haddock") docPathRelFP = - fmap ((docRelFP FP.</>) . FP.takeFileName) haddockHtml - interfaces = intercalate "," $ mcons docPathRelFP [srcInterfaceFP] - - destInterfaceAbsFile <- + fmap ((docRelFP FP.</>) . FP.takeFileName) dp.haddockHtml + mkInterface :: Maybe FilePath -> FilePath -> String + mkInterface mDocPath file = + intercalate "," $ mcons mDocPath [file] + compInterface :: (Path Abs Dir, Path Abs File) -> IO String + compInterface (dir, file) = do + (file', uniqueName) <- liftcompInterfaceDir dir file + let compDir = dropTrailingPathSeparator $ toFilePath uniqueName + docDir = docRelFP FP.</> compDir + pure $ mkInterface (Just docDir) (toFilePath file') + interfaces = mkInterface docPathRelFP srcInterfaceFP + compInterfaces <- forM compInterfaceDirsAndFiles compInterface + let readInterfaceArgs = + "-i" : intersperse "-i" (interfaces : compInterfaces) + destInterfaceFile <- parseCollapsedAbsFile (toFilePath destDir FP.</> destInterfaceRelFP) - esrcInterfaceModTime <- tryGetModificationTime srcInterfaceAbsFile + eSrcInterfaceFileModTime <- tryGetModificationTime srcInterfaceFile pure $ - case esrcInterfaceModTime of + case eSrcInterfaceFileModTime of Left _ -> Nothing - Right srcInterfaceModTime -> - Just - ( [ "-i", interfaces ] - , srcInterfaceModTime - , srcInterfaceAbsFile - , destInterfaceAbsFile - ) - copyPkgDocs :: (a, UTCTime, Path Abs File, Path Abs File) -> IO () - copyPkgDocs (_, srcInterfaceModTime, srcInterfaceAbsFile, destInterfaceAbsFile) = do + Right srcInterfaceFileModTime -> + Just InterfaceOpt + { readInterfaceArgs + , srcInterfaceFileModTime + , srcInterfaceFile + , destInterfaceFile + } + copyPkgDocs :: InterfaceOpt -> IO () + copyPkgDocs opts = do -- Copy dependencies' haddocks to documentation directory. This way, -- relative @../$pkg-$ver@ links work and it's easy to upload docs to a web -- server or otherwise view them in a non-local-filesystem context. We copy -- instead of symlink for two reasons: (1) symlinks aren't reliably supported -- on Windows, and (2) the filesystem containing dependencies' docs may not be -- available where viewing the docs (e.g. if building in a Docker container). - edestInterfaceModTime <- tryGetModificationTime destInterfaceAbsFile + edestInterfaceModTime <- tryGetModificationTime opts.destInterfaceFile case edestInterfaceModTime of Left _ -> doCopy Right destInterfaceModTime - | destInterfaceModTime < srcInterfaceModTime -> doCopy + | destInterfaceModTime < opts.srcInterfaceFileModTime -> doCopy | otherwise -> pure () where doCopy = do ignoringAbsence (removeDirRecur destHtmlAbsDir) ensureDir destHtmlAbsDir onException - (copyDirRecur' (parent srcInterfaceAbsFile) destHtmlAbsDir) + (copyDirRecur' (parent opts.srcInterfaceFile) destHtmlAbsDir) (ignoringAbsence (removeDirRecur destHtmlAbsDir)) - destHtmlAbsDir = parent destInterfaceAbsFile + destHtmlAbsDir = parent opts.destInterfaceFile -- | Find first DumpPackage matching the GhcPkgId lookupDumpPackage :: GhcPkgId @@ -320,11 +381,11 @@ haddockIndexFile :: Path Abs Dir -> Path Abs File haddockIndexFile destDir = destDir </> relFileIndexHtml --- | Path of local packages documentation directory. +-- | Path of project packages documentation directory. localDocDir :: BaseConfigOpts -> Path Abs Dir localDocDir bco = bco.localInstallRoot </> docDirSuffix --- | Path of documentation directory for the dependencies of local packages +-- | Path of documentation directory for the dependencies of project packages localDepsDocDir :: BaseConfigOpts -> Path Abs Dir localDepsDocDir bco = localDocDir bco </> relDirAll @@ -336,14 +397,17 @@ (HasEnvConfig env, HasTerm env) => [LocalPackage] -> RIO env () -generateLocalHaddockForHackageArchives = - mapM_ - ( \lp -> - let pkg = lp.package - pkgId = PackageIdentifier pkg.name pkg.version - pkgDir = parent lp.cabalFP - in generateLocalHaddockForHackageArchive pkgDir pkgId - ) +generateLocalHaddockForHackageArchives lps = do + buildSubset <- view $ envConfigL . to (.buildOptsCLI.buildSubset) + let localsExcluded = + buildSubset == BSOnlyDependencies || buildSubset == BSOnlySnapshot + unless localsExcluded $ + forM_ lps $ \lp -> + let pkg = lp.package + pkgId = PackageIdentifier pkg.name pkg.version + pkgDir = parent lp.cabalFP + in when lp.wanted $ + generateLocalHaddockForHackageArchive pkgDir pkgId -- | Generate an archive file containing local Haddock documentation for -- Hackage, in a form accepted by Hackage. @@ -367,15 +431,22 @@ ) tarGzFile = distDir </> tarGzFileName docDir = distDir </> docDirSuffix </> htmlDirSuffix - createTarGzFile tarGzFile docDir nameRelDir - prettyInfo $ - fillSep - [ flow "Archive of Haddock documentation for Hackage for" - , style Current (fromString pkgIdName) - , flow "created at:" - ] - <> line - <> pretty tarGzFile + tarGzFileCreated <- createTarGzFile tarGzFile docDir nameRelDir + if tarGzFileCreated + then + prettyInfo $ + fillSep + [ flow "Archive of Haddock documentation for Hackage for" + , style Current (fromString pkgIdName) + , flow "created at:" + ] + <> line + <> pretty tarGzFile + else + prettyWarnL + [ flow "No Haddock documentation for Hackage available for" + , style Error (fromString pkgIdName) <> "." + ] createTarGzFile :: Path Abs File @@ -384,10 +455,19 @@ -- ^ Base directory -> Path Rel Dir -- ^ Directory to archive, relative to base directory - -> RIO env () + -> RIO env Bool createTarGzFile tar base dir = do - entries <- liftIO $ Tar.pack base' [dir'] - BL.writeFile tar' $ GZip.compress $ Tar.write entries + dirExists <- doesDirExist $ base </> dir + if dirExists + then do + entries <- liftIO $ Tar.pack base' [dir'] + if null entries + then pure False + else do + ensureDir $ parent tar + BL.writeFile tar' $ GZip.compress $ Tar.write entries + pure True + else pure False where base' = fromAbsDir base dir' = fromRelDir dir
src/Stack/Build/Installed.hs view
@@ -158,7 +158,7 @@ UserPkgDb loc fp -> ", from " <> displayShow (loc, fp) <> "," <> " due to" <> case reason of - UnknownPkg -> " it being unknown to the resolver / extra-deps." + UnknownPkg -> " it being unknown to the snapshot or extra-deps." WrongLocation db' loc -> " wrong location: " <> displayShow (db', loc) WrongVersion actual wanted ->
src/Stack/Build/Source.hs view
@@ -10,7 +10,6 @@ , loadCommonPackage , loadLocalPackage , loadSourceMap - , getLocalFlags , addUnlistedToBuildCache , hashSourceMapData ) where @@ -32,12 +31,12 @@ import Stack.PackageFile ( getPackageFile ) import Stack.Prelude import Stack.SourceMap - ( DumpedGlobalPackage, checkFlagsUsedThrowing - , getCompilerInfo, immutableLocSha, mkProjectPackage - , pruneGlobals + ( DumpedGlobalPackage, getCompilerInfo, immutableLocSha + , mkProjectPackage, pruneGlobals ) import Stack.Types.ApplyGhcOptions ( ApplyGhcOptions (..) ) import Stack.Types.ApplyProgOptions ( ApplyProgOptions (..) ) +import Stack.Types.Build.Exception ( BuildPrettyException (..) ) import Stack.Types.BuildConfig ( BuildConfig (..), HasBuildConfig (..) ) import Stack.Types.BuildOpts ( BuildOpts (..), TestOpts (..) ) @@ -69,7 +68,7 @@ , SMActual (..), SMTargets (..), SourceMap (..) , SourceMapHash (..), Target (..), ppGPD, ppRoot ) -import Stack.Types.UnusedFlags ( FlagSource (..) ) +import Stack.Types.UnusedFlags ( FlagSource (..), UnusedFlags (..) ) import System.FilePath ( takeFileName ) import System.IO.Error ( isDoesNotExistError ) @@ -93,51 +92,25 @@ -- | Given the parsed targets and build command line options constructs a source -- map -loadSourceMap :: HasBuildConfig env - => SMTargets - -> BuildOptsCLI - -> SMActual DumpedGlobalPackage - -> RIO env SourceMap +loadSourceMap :: + forall env. HasBuildConfig env + => SMTargets + -> BuildOptsCLI + -> SMActual DumpedGlobalPackage + -> RIO env SourceMap loadSourceMap targets boptsCli sma = do - bconfig <- view buildConfigL + logDebug "Applying and checking flags" + let errsPackages = mapMaybe checkPackage packagesWithCliFlags + eProject <- mapM applyOptsFlagsPP (M.toList sma.project) + eDeps <- mapM applyOptsFlagsDep (M.toList targetsAndSmaDeps) + let (errsProject, project') = partitionEithers eProject + (errsDeps, deps') = partitionEithers eDeps + errs = errsPackages <> errsProject <> errsDeps + unless (null errs) $ prettyThrowM $ InvalidFlagSpecification errs let compiler = sma.compiler - project = M.map applyOptsFlagsPP sma.project - bopts = bconfig.config.build - applyOptsFlagsPP p@ProjectPackage{ projectCommon = c } = p - { projectCommon = applyOptsFlags (M.member c.name targets.targets) True c } - deps0 = targets.deps <> sma.deps - deps = M.map applyOptsFlagsDep deps0 - applyOptsFlagsDep d@DepPackage{ depCommon = c } = d - { depCommon = applyOptsFlags (M.member c.name targets.deps) False c } - applyOptsFlags isTarget isProjectPackage common = - let name = common.name - flags = getLocalFlags boptsCli name - ghcOptions = - generalGhcOptions bconfig boptsCli isTarget isProjectPackage - cabalConfigOpts = - generalCabalConfigOpts bconfig boptsCli common.name isTarget isProjectPackage - in common - { flags = - if M.null flags - then common.flags - else flags - , ghcOptions = - ghcOptions ++ common.ghcOptions - , cabalConfigOpts = - cabalConfigOpts ++ common.cabalConfigOpts - , buildHaddocks = - if isTarget - then bopts.buildHaddocks - else shouldHaddockDeps bopts - } - packageCliFlags = Map.fromList $ - mapMaybe maybeProjectFlags $ - Map.toList boptsCli.flags - maybeProjectFlags (ACFByName name, fs) = Just (name, fs) - maybeProjectFlags _ = Nothing + project = M.fromList project' + deps = M.fromList deps' globalPkgs = pruneGlobals sma.globals (Map.keysSet deps) - logDebug "Checking flags" - checkFlagsUsedThrowing packageCliFlags FSCommandLine project deps logDebug "SourceMap constructed" pure SourceMap { targets @@ -146,6 +119,90 @@ , deps , globalPkgs } + where + cliFlags = boptsCli.flags + targetsAndSmaDeps = targets.deps <> sma.deps + packagesWithCliFlags = mapMaybe maybeProjectWithCliFlags $ Map.toList cliFlags + where + maybeProjectWithCliFlags (ACFByName name, _) = Just name + maybeProjectWithCliFlags _ = Nothing + checkPackage :: PackageName -> Maybe UnusedFlags + checkPackage name = + let maybeCommon = + fmap (.projectCommon) (Map.lookup name sma.project) + <|> fmap (.depCommon) (Map.lookup name targetsAndSmaDeps) + in maybe + (Just $ UFNoPackage FSCommandLine name) + (const Nothing) + maybeCommon + applyOptsFlagsPP :: + (a, ProjectPackage) + -> RIO env (Either UnusedFlags (a, ProjectPackage)) + applyOptsFlagsPP (name, p@ProjectPackage{ projectCommon = common }) = do + let isTarget = M.member common.name targets.targets + eCommon <- applyOptsFlags isTarget True common + pure $ (\common' -> (name, p { projectCommon = common' })) <$> eCommon + applyOptsFlagsDep :: + (a, DepPackage) + -> RIO env (Either UnusedFlags (a, DepPackage)) + applyOptsFlagsDep (name, d@DepPackage{ depCommon = common }) = do + let isTarget = M.member common.name targets.deps + eCommon <- applyOptsFlags isTarget False common + pure $ (\common' -> (name, d { depCommon = common' })) <$> eCommon + applyOptsFlags :: + Bool + -> Bool + -> CommonPackage + -> RIO env (Either UnusedFlags CommonPackage) + applyOptsFlags isTarget isProjectPackage common = do + let name = common.name + cliFlagsByName = Map.findWithDefault Map.empty (ACFByName name) cliFlags + cliFlagsAll = + Map.findWithDefault Map.empty ACFAllProjectPackages cliFlags + noOptsToApply = Map.null cliFlagsByName && Map.null cliFlagsAll + (flags, unusedByName, pkgFlags) <- if noOptsToApply + then + pure (Map.empty, Set.empty, Set.empty) + else do + gpd <- + -- This action is expensive. We want to avoid it if we can. + liftIO common.gpd + let pkgFlags = Set.fromList $ map C.flagName $ C.genPackageFlags gpd + unusedByName = Map.keysSet $ Map.withoutKeys cliFlagsByName pkgFlags + cliFlagsAllRelevant = + Map.filterWithKey (\k _ -> k `Set.member` pkgFlags) cliFlagsAll + flags = cliFlagsByName <> cliFlagsAllRelevant + pure (flags, unusedByName, pkgFlags) + if Set.null unusedByName + -- All flags are defined, nothing to do + then do + bconfig <- view buildConfigL + let bopts = bconfig.config.build + ghcOptions = + generalGhcOptions bconfig boptsCli isTarget isProjectPackage + cabalConfigOpts = generalCabalConfigOpts + bconfig + boptsCli + name + isTarget + isProjectPackage + pure $ Right common + { flags = + if M.null flags + then common.flags + else flags + , ghcOptions = + ghcOptions ++ common.ghcOptions + , cabalConfigOpts = + cabalConfigOpts ++ common.cabalConfigOpts + , buildHaddocks = + if isTarget + then bopts.buildHaddocks + else shouldHaddockDeps bopts + } + -- Error about the undefined flags + else + pure $ Left $ UFFlagsNotDefined FSCommandLine name pkgFlags unusedByName -- | Get a 'SourceMapHash' for a given 'SourceMap' -- @@ -177,7 +234,7 @@ immDeps <- forM (Map.elems sm.deps) depPackageHashableContent bc <- view buildConfigL let -- extra bytestring specifying GHC options supposed to be applied to GHC - -- boot packages so we'll have different hashes when bare resolver + -- boot packages so we'll have different hashes when bare snapshot -- 'ghc-X.Y.Z' is used, no extra-deps and e.g. user wants builds with -- profiling or without bootGhcOpts = map display (generalGhcOptions bc boptsCli False False) @@ -206,18 +263,6 @@ <> getUtf8Builder (mconcat flags) <> getUtf8Builder (mconcat ghcOptions) <> getUtf8Builder (mconcat cabalConfigOpts) - --- | All flags for a local package. -getLocalFlags :: - BuildOptsCLI - -> PackageName - -> Map FlagName Bool -getLocalFlags boptsCli name = Map.unions - [ Map.findWithDefault Map.empty (ACFByName name) cliFlags - , Map.findWithDefault Map.empty ACFAllProjectPackages cliFlags - ] - where - cliFlags = boptsCli.flags -- | Get the options to pass to @./Setup.hs configure@ generalCabalConfigOpts ::
src/Stack/Build/Target.hs view
@@ -12,7 +12,7 @@ -- -- There are two relevant data sources for performing this parsing: the project -- configuration, and command line arguments. Project configurations includes --- the resolver (defining a LoadedSnapshot of global and snapshot packages), +-- the snapshot (defining a LoadedSnapshot of global and snapshot packages), -- local dependencies, and project packages. It also defines local flag -- overrides. -- @@ -80,6 +80,7 @@ import Stack.Types.BuildConfig ( BuildConfig (..), HasBuildConfig (..) ) import Stack.Types.BuildOptsCLI ( BuildOptsCLI (..) ) +import Stack.Types.ComponentUtils ( unqualCompFromText ) import Stack.Types.Config ( Config (..) ) import Stack.Types.NamedComponent ( NamedComponent (..), renderComponent ) @@ -171,8 +172,8 @@ [] -> pure $ Left $ fillSep [ style Dir (fromString $ T.unpack t) - , flow "is not a local package directory and it is not a \ - \parent directory of any local package directory." + , flow "is not a local directory for a package and it is not a \ + \parent directory of any such directory." ] names -> pure $ Right $ map ((ri, ) . RTPackage) names where @@ -226,9 +227,9 @@ parseCompType t' = case t' of - "exe" -> Just CExe - "test" -> Just CTest - "bench" -> Just CBench + "exe" -> Just (CExe . unqualCompFromText) + "test" -> Just (CTest . unqualCompFromText) + "bench" -> Just (CBench . unqualCompFromText) _ -> Nothing -------------------------------------------------------------------------------- @@ -263,11 +264,14 @@ -- 'ComponentName' isCompNamed :: ComponentName -> NamedComponent -> Bool isCompNamed _ CLib = False - isCompNamed t1 (CSubLib t2) = t1 == t2 - isCompNamed t1 (CExe t2) = t1 == t2 - isCompNamed t1 (CFlib t2) = t1 == t2 - isCompNamed t1 (CTest t2) = t1 == t2 - isCompNamed t1 (CBench t2) = t1 == t2 + isCompNamed t1 t2 = case t2 of + (CSubLib t2') -> t1' == t2' + (CExe t2') -> t1' == t2' + (CFlib t2') -> t1' == t2' + (CTest t2') -> t1' == t2' + (CBench t2') -> t1' == t2' + where + t1' = unqualCompFromText t1 go (RTComponent cname) = do -- Associated list from component name to package that defines it. We use an @@ -316,7 +320,7 @@ case Map.lookup name locals of Nothing -> pure $ Left $ fillSep - [ flow "Unknown local package:" + [ flow "Unknown project package:" , style Target (fromPackageName name) <> "." ] Just pp -> do @@ -393,12 +397,13 @@ go (RTPackageIdentifier ident@(PackageIdentifier name version)) | Map.member name locals = pure $ Left $ fillSep - [ style Target (fromPackageName name) - , flow "target has a specific version number, but it is a local \ - \package. To avoid confusion, we will not install the \ - \specified version or build the local one. To build the \ - \local package, specify the target without an explicit \ - \version." + [ style Target (fromPackageId ident) + , flow "is a specific package version, but" + , style Target (fromPackageName name) + , flow "is the name of a project package. To avoid confusion, Stack \ + \will not try to build the specified version or the project \ + \package. To build the project package, specify only" + , style Current (fromPackageName name) <> "." ] | otherwise = case Map.lookup name allLocs of @@ -412,15 +417,13 @@ ) -> if version == versionLoc then pure $ deferToConstructPlan name - else hackageLatestRevision name version + else hackageLatestRevision name version versionLoc -- The package was coming from something besides the index, so refuse -- to do the override Just loc' -> pure $ Left $ fillSep - [ flow "Package with identifier was targeted on the command \ - \line:" - , style Target (fromPackageId ident) <> "," - , flow "but it was specified from a non-index location:" + [ style Target (fromPackageId ident) + , flow "was specified from a non-index location, namely:" , flow $ T.unpack $ textDisplay loc' <> "." , flow "Recommendation: add the correctly desired version to \ \extra-deps." @@ -429,7 +432,14 @@ Nothing -> do mrev <- getLatestHackageRevision YesRequireHackageIndex name version pure $ case mrev of - Nothing -> deferToConstructPlan name + Nothing -> Left $ + fillSep + [ flow "Stack did not know the location of a package named" + , style Target (fromPackageName name) + , "and could not find" + , style Target (fromPackageId ident) + , flow "in the package index." + ] Just (_rev, cfKey, treeKey) -> Right ResolveResult { name , rawInput @@ -453,10 +463,20 @@ , packageType = PTDependency } - hackageLatestRevision name version = do + hackageLatestRevision name version versionLoc = do mrev <- getLatestHackageRevision YesRequireHackageIndex name version pure $ case mrev of - Nothing -> deferToConstructPlan name + Nothing -> Left $ + fillSep + [ flow "Stack knows the location of" + , style Current (fromPackageId pkgId') + , flow "but did not know the location of" + , style Target (fromPackageId pkgId) <>"," + , flow "and did not find it in the package index." + ] + where + pkgId = PackageIdentifier name version + pkgId' = PackageIdentifier name versionLoc Just (_rev, cfKey, treeKey) -> Right ResolveResult { name , rawInput @@ -572,8 +592,8 @@ ] | null textTargets' && Map.null locals -> prettyThrowIO $ TargetParseException - [ flow "The project contains no local packages (packages not \ - \marked with 'extra-dep')." + [ flow "The project contains no project packages (packages other \ + \than extra-deps)." ] | otherwise -> prettyThrowIO $ TargetParseException [ flow "The specified targets matched no packages." ]
src/Stack/BuildOpts.hs view
@@ -31,6 +31,9 @@ , haddockOpts = defaultHaddockOpts , openHaddocks = defaultFirstFalse buildMonoid.openHaddocks , haddockDeps = Nothing + , haddockExecutables = defaultFirstFalse buildMonoid.haddockExecutables + , haddockTests = defaultFirstFalse buildMonoid.haddockTests + , haddockBenchmarks = defaultFirstFalse buildMonoid.haddockBenchmarks , haddockInternal = defaultFirstFalse buildMonoid.haddockInternal , haddockHyperlinkSource = defaultFirstTrue buildMonoid.haddockHyperlinkSource , haddockForHackage = defaultFirstFalse buildMonoid.haddockForHackage
src/Stack/BuildPlan.hs view
@@ -65,7 +65,7 @@ (Map PackageName (Maybe Version, Set PackageName)) -- truly unknown (Map PackageName (Set PackageIdentifier)) -- shadowed | SnapshotNotFound SnapName - | NeitherCompilerOrResolverSpecified T.Text + | NeitherCompilerOrSnapshotSpecified T.Text | DuplicatePackagesBug deriving (Show, Typeable) @@ -73,7 +73,7 @@ displayException (SnapshotNotFound snapName) = unlines [ "Error: [S-2045]" , "SnapshotNotFound " ++ snapName' - , "Non existing resolver: " ++ snapName' ++ "." + , "Non existing snapshot: " ++ snapName' ++ "." , "For a complete list of available snapshots see https://www.stackage.org/snapshots" ] where @@ -123,7 +123,7 @@ shadowed' | Map.null shadowed = [] | otherwise = concat - [ ["The following packages are shadowed by local packages:"] + [ ["The following packages are shadowed by project packages:"] , map go (Map.toList shadowed) , ["Recommended action: modify the extra-deps field of " ++ toFilePath stackYaml ++ @@ -146,11 +146,11 @@ $ Set.toList $ Set.unions $ Map.elems shadowed - displayException (NeitherCompilerOrResolverSpecified url) = concat + displayException (NeitherCompilerOrSnapshotSpecified url) = concat [ "Error: [S-8559]\n" , "Failed to load custom snapshot at " , T.unpack url - , ", because no 'compiler' or 'resolver' is specified." + , ", because no 'compiler' or 'snapshot' is specified." ] displayException DuplicatePackagesBug = bugReport "[S-5743]" "Duplicate packages are not expected here."
src/Stack/CLI.hs view
@@ -223,7 +223,7 @@ "Sets a key in YAML configuration file to value." (withConfig NoReexec . cfgCmdSet) configCmdSetParser - addCommand' + addCommandWithLocalInstallRootFooter ConfigCmd.cfgCmdEnvName "Print environment variables for use in a shell." (withConfig YesReexec . withDefaultEnvConfig . cfgCmdEnv) @@ -263,7 +263,7 @@ evalCmd (evalOptsParser "CODE") - exec = addCommand' + exec = addCommandWithLocalInstallRootFooter "exec" "Execute a command. If the command is absent, the first of any arguments \ \is taken as the command." @@ -373,7 +373,8 @@ init = addCommand' "init" "Create Stack project configuration from Cabal or Hpack package \ - \specifications." + \specifications. If a snapshot is specified at the command line, the \ + \command will try to use it." initCmd initOptsParser @@ -385,27 +386,29 @@ list = addCommand' "list" - "List package id's in snapshot (experimental)." + "List package versions included in the package index, or in a specified \ + \snapshot (directly or indirectly)." listCmd (many $ strArgument $ metavar "PACKAGE") ls = addCommand' "ls" - "List command. (Supports snapshots, dependencies, Stack's styles and \ - \installed tools.)" + "List command. (Supports snapshots, global packages, dependencies, Stack's \ + \styles and installed tools.)" lsCmd lsOptsParser new = addCommand' "new" "Create a new project from a template. Run 'stack templates' to see \ - \available templates. Will also initialise if there is no stack.yaml \ - \file. Note: you can also specify a local file or a remote URL as a \ - \template; or force an initialisation." + \available templates. A local file or a remote URL can be specified as a \ + \template. Will initialise if there is no stack.yaml file. Initialisation \ + \may be forced. If a snapshot is specified at the command line, \ + \initialisation will try to use it." newCmd newOptsParser - path = addCommand' + path = addCommandWithLocalInstallRootFooter "path" "Print out handy path information." Stack.Path.path @@ -454,7 +457,7 @@ "Run a Stack script." globalFooter scriptCmd - (\so gom -> gom { resolverRoot = First $ Just $ takeDirectory so.file }) + (\so gom -> gom { snapshotRoot = First $ Just $ takeDirectory so.file }) (globalOpts OtherCmdGlobalOpts) scriptOptsParser @@ -559,6 +562,22 @@ constr (\_ gom -> gom) (globalOpts OtherCmdGlobalOpts) + + -- addCommand with custom footer about options affecting the local install + --root and hiding global options + addCommandWithLocalInstallRootFooter :: + String + -> String + -> (a -> RIO Runner ()) + -> Parser a + -> AddCommand + addCommandWithLocalInstallRootFooter cmd title constr = + addCommand'' + cmd + title + constr + "This command also accepts 'stack build' flags and options that affect \ + \the location of the local project installation root directory." addSubCommands' :: String
src/Stack/Clean.hs view
@@ -18,7 +18,7 @@ import Stack.Prelude import Stack.Runners ( ShouldReexec (..), withConfig ) import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), getProjectWorkDir ) + ( BuildConfig (..), HasBuildConfig (..), getWorkDir ) import Stack.Types.Config ( Config ) import Stack.Types.Runner ( Runner ) import Stack.Types.SourceMap ( SMWanted (..), ppRoot ) @@ -49,8 +49,8 @@ data CleanOpts = CleanShallow [PackageName] -- ^ Delete the "dist directories" as defined in - -- 'Stack.Constants.Config.distRelativeDir' for the given local packages. If - -- no packages are given, all project packages should be cleaned. + -- 'Stack.Constants.Config.distRelativeDir' for the given project packages. + -- If no project packages are given, all project packages should be cleaned. | CleanFull -- ^ Delete all work directories in the project. @@ -94,5 +94,5 @@ xs -> throwM (NonLocalPackages xs) CleanFull -> do pkgWorkDirs <- mapM (workDirFromDir . ppRoot) $ Map.elems packages - projectWorkDir <- getProjectWorkDir + projectWorkDir <- getWorkDir pure (projectWorkDir : pkgWorkDirs)
src/Stack/Component.hs view
@@ -22,7 +22,6 @@ , stackBenchmarkFromCabal , stackTestFromCabal , foldOnNameAndBuildInfo - , stackUnqualToQual , componentDependencyMap , fromCabalName ) where @@ -47,13 +46,6 @@ ) import Stack.Types.ComponentUtils ( fromCabalName ) import Stack.Types.Dependency ( cabalExeToStackDep, cabalToStackDep ) -import Stack.Types.NamedComponent ( NamedComponent ) - -stackUnqualToQual :: - (Text -> NamedComponent) - -> StackUnqualCompName - -> NamedComponent -stackUnqualToQual c (StackUnqualCompName n) = c n foldOnNameAndBuildInfo :: ( HasField "buildInfo" a StackBuildInfo
src/Stack/ComponentFile.hs view
@@ -33,7 +33,6 @@ import Distribution.Text ( display ) import Distribution.Utils.Path ( PackageDir, SourceDir, SymbolicPath, getSymbolicPath ) -import Distribution.Version ( mkVersion ) import GHC.Records ( HasField ) import qualified HiFileParser as Iface import Path @@ -56,6 +55,8 @@ , StackExecutable (..), StackLibrary (..) , StackTestSuite (..), StackUnqualCompName (..) ) +import Stack.Types.ComponentUtils + ( emptyCompName, unqualCompToString ) import Stack.Types.Config ( Config (..), HasConfig (..), prettyStackDevL ) import Stack.Types.NamedComponent ( NamedComponent (..) ) @@ -78,7 +79,7 @@ StackBenchmark -> RIO GetPackageFileContext (NamedComponent, ComponentFile) stackBenchmarkFiles bench = - resolveComponentFiles (CBench bench.name.unqualCompToText) build names + resolveComponentFiles (CBench bench.name) build names where names = bnames <> exposed exposed = @@ -93,7 +94,7 @@ StackTestSuite -> RIO GetPackageFileContext (NamedComponent, ComponentFile) stackTestSuiteFiles test = - resolveComponentFiles (CTest test.name.unqualCompToText) build names + resolveComponentFiles (CTest test.name) build names where names = bnames <> exposed exposed = @@ -109,7 +110,7 @@ StackExecutable -> RIO GetPackageFileContext (NamedComponent, ComponentFile) stackExecutableFiles exe = - resolveComponentFiles (CExe exe.name.unqualCompToText) build names + resolveComponentFiles (CExe exe.name) build names where build = exe.buildInfo names = @@ -123,9 +124,9 @@ stackLibraryFiles lib = resolveComponentFiles componentName build names where - componentRawName = lib.name.unqualCompToText + componentRawName = lib.name componentName - | componentRawName == mempty = CLib + | componentRawName == emptyCompName = CLib | otherwise = CSubLib componentRawName build = lib.buildInfo names = bnames ++ exposed @@ -154,10 +155,9 @@ pure (component, ComponentFile modules (files <> cfiles) warnings) where autogenDirs = do - cabalVer <- asks (.cabalVer) distDir <- asks (.distDir) - let compDir = componentAutogenDir cabalVer component distDir - pkgDir = maybeToList $ packageAutogenDir cabalVer distDir + let compDir = componentAutogenDir component distDir + pkgDir = [packageAutogenDir distDir] filterM doesDirExist $ compDir : pkgDir -- | Try to resolve the list of base names in the given directory by looking for @@ -343,7 +343,7 @@ CBench name -> makeTmp name where makeTmp name = - buildDir distDir </> componentNameToDir (name <> "/" <> name <> "-tmp") + buildDir distDir </> componentNameToDirNormOrTmp True name -- | Try to resolve the list of base names in the given directory by -- looking for unique instances of base names applied with the given @@ -532,15 +532,13 @@ f p x = forgivingResolveDir p x >>= rejectMissingDir -- | Make the global autogen dir if Cabal version is new enough. -packageAutogenDir :: Version -> Path Abs Dir -> Maybe (Path Abs Dir) -packageAutogenDir cabalVer distDir - | cabalVer < mkVersion [2, 0] = Nothing - | otherwise = Just $ buildDir distDir </> relDirGlobalAutogen +packageAutogenDir :: Path Abs Dir -> Path Abs Dir +packageAutogenDir distDir = buildDir distDir </> relDirGlobalAutogen -- | Make the autogen dir. -componentAutogenDir :: Version -> NamedComponent -> Path Abs Dir -> Path Abs Dir -componentAutogenDir cabalVer component distDir = - componentBuildDir cabalVer component distDir </> relDirAutogen +componentAutogenDir :: NamedComponent -> Path Abs Dir -> Path Abs Dir +componentAutogenDir component distDir = + componentBuildDir component distDir </> relDirAutogen -- | Make the build dir. Note that Cabal >= 2.0 uses the -- 'componentBuildDir' above for some things. @@ -549,23 +547,25 @@ -- NOTE: don't export this, only use it for valid paths based on -- component names. -componentNameToDir :: Text -> Path Rel Dir -componentNameToDir name = - fromMaybe (throw $ ComponentNotParsedBug sName) (parseRelDir sName) - where sName = T.unpack name +componentNameToDir :: StackUnqualCompName -> Path Rel Dir +componentNameToDir = componentNameToDirNormOrTmp False +componentNameToDirNormOrTmp :: Bool -> StackUnqualCompName -> Path Rel Dir +componentNameToDirNormOrTmp isTemp name = + fromMaybe (throw $ ComponentNotParsedBug sName) (parseRelDir fullName) + where + fullName = if isTemp then sName <> "/" <> sName <> "-tmp" else sName + sName = unqualCompToString name + -- | See 'Distribution.Simple.LocalBuildInfo.componentBuildDir' -componentBuildDir :: Version -> NamedComponent -> Path Abs Dir -> Path Abs Dir -componentBuildDir cabalVer component distDir - | cabalVer < mkVersion [2, 0] = buildDir distDir - | otherwise = - case component of - CLib -> buildDir distDir - CSubLib name -> buildDir distDir </> componentNameToDir name - CFlib name -> buildDir distDir </> componentNameToDir name - CExe name -> buildDir distDir </> componentNameToDir name - CTest name -> buildDir distDir </> componentNameToDir name - CBench name -> buildDir distDir </> componentNameToDir name +componentBuildDir :: NamedComponent -> Path Abs Dir -> Path Abs Dir +componentBuildDir component distDir = case component of + CLib -> buildDir distDir + CSubLib name -> buildDir distDir </> componentNameToDir name + CFlib name -> buildDir distDir </> componentNameToDir name + CExe name -> buildDir distDir </> componentNameToDir name + CTest name -> buildDir distDir </> componentNameToDir name + CBench name -> buildDir distDir </> componentNameToDir name -- Internal helper to define resolveFileOrWarn and resolveDirOrWarn resolveOrWarn ::
src/Stack/Config.hs view
@@ -6,23 +6,24 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-} --- | The general Stack configuration that starts everything off. This should --- be smart to fallback if there is no stack.yaml, instead relying on --- whatever files are available. +-- | The general Stack configuration that starts everything off. This should be +-- smart to fallback if there is no stack.yaml, instead relying on whatever +-- files are available. -- --- If there is no stack.yaml, and there is a cabal.config, we --- read in those constraints, and if there's a cabal.sandbox.config, --- we read any constraints from there and also find the package --- database from there, etc. And if there's nothing, we should --- probably default to behaving like cabal, possibly with spitting out --- a warning that "you should run `stk init` to make things better". +-- If there is no stack.yaml, and there is a cabal.config, we read in those +-- constraints, and if there's a cabal.sandbox.config, we read any constraints +-- from there and also find the package database from there, etc. And if there's +-- nothing, we should probably default to behaving like cabal, possibly with +-- spitting out a warning that "you should run `stk init` to make things +-- better". module Stack.Config ( loadConfig , loadConfigYaml , packagesParser , getImplicitGlobalProjectDir , getSnapshots - , makeConcreteResolver + , makeConcreteSnapshot + , getRawSnapshot , checkOwnership , getInContainer , getInNixShell @@ -41,21 +42,26 @@ import qualified Data.ByteString as S import Data.ByteString.Builder ( byteString ) import Data.Coerce ( coerce ) +import qualified Data.Either.Extra as EE import qualified Data.IntMap as IntMap import qualified Data.Map as Map import qualified Data.Map.Merge.Strict as MS import qualified Data.Monoid import Data.Monoid.Map ( MonoidMap (..) ) +import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Yaml as Yaml +import qualified Distribution.PackageDescription as PD import Distribution.System ( Arch (..), OS (..), Platform (..), buildPlatform ) import qualified Distribution.Text ( simpleParse ) import Distribution.Version ( simplifyVersionRange ) +import qualified Hpack import GHC.Conc ( getNumProcessors ) import Network.HTTP.StackClient ( httpJSON, parseUrlThrow, getResponseBody ) import Options.Applicative ( Parser, help, long, metavar, strOption ) +import Pantry ( loadSnapshot ) import Path ( PathException (..), (</>), parent, parseAbsDir , parseAbsFile, parseRelDir, stripProperPrefix @@ -63,10 +69,10 @@ import Path.Extra ( toFilePathNoTrailingSep ) import Path.Find ( findInParents ) import Path.IO - ( XdgDirectory (..), canonicalizePath, doesDirExist - , doesFileExist, ensureDir, forgivingAbsence - , getAppUserDataDir, getCurrentDir, getXdgDir, resolveDir - , resolveDir', resolveFile' + ( XdgDirectory (..), canonicalizePath, doesFileExist + , ensureDir, forgivingAbsence, getAppUserDataDir + , getCurrentDir, getXdgDir, resolveDir, resolveDir' + , resolveFile, resolveFile' ) import RIO.List ( unzip ) import RIO.Process @@ -80,10 +86,8 @@ import Stack.Config.Docker ( dockerOptsFromMonoid ) import Stack.Config.Nix ( nixOptsFromMonoid ) import Stack.Constants - ( defaultGlobalConfigPath, defaultGlobalConfigPathDeprecated - , defaultUserConfigPath, defaultUserConfigPathDeprecated - , implicitGlobalProjectDir - , implicitGlobalProjectDirDeprecated, inContainerEnvVar + ( defaultGlobalConfigPath, defaultUserConfigPath + , implicitGlobalProjectDir, inContainerEnvVar , inNixShellEnvVar, osIsWindows, pantryRootEnvVar , platformVariantEnvVar, relDirBin, relDirStackWork , relFileReadmeTxt, relFileStorage, relDirPantry @@ -94,17 +98,15 @@ import qualified Stack.Constants as Constants import Stack.Lock ( lockCachedWanted ) import Stack.Prelude -import Stack.SourceMap - ( additionalDepPackage, checkFlagsUsedThrowing - , mkProjectPackage - ) +import Stack.SourceMap ( additionalDepPackage, mkProjectPackage ) import Stack.Storage.Project ( initProjectStorage ) import Stack.Storage.User ( initUserStorage ) import Stack.Storage.Util ( handleMigrationException ) import Stack.Types.AllowNewerDeps ( AllowNewerDeps (..) ) import Stack.Types.ApplyGhcOptions ( ApplyGhcOptions (..) ) import Stack.Types.ApplyProgOptions ( ApplyProgOptions (..) ) -import Stack.Types.Build.Exception ( BuildException (..) ) +import Stack.Types.Build.Exception + ( BuildException (..), BuildPrettyException (..) ) import Stack.Types.BuildConfig ( BuildConfig (..) ) import Stack.Types.BuildOpts ( BuildOpts (..) ) import Stack.Types.ColorWhen ( ColorWhen (..) ) @@ -115,13 +117,16 @@ ) import Stack.Types.Config.Exception ( ConfigException (..), ConfigPrettyException (..) - , ParseAbsolutePathException (..), packageIndicesWarning ) + , ParseAbsolutePathException (..) + ) import Stack.Types.ConfigMonoid ( ConfigMonoid (..), parseConfigMonoid ) import Stack.Types.Casa ( CasaOptsMonoid (..) ) import Stack.Types.Docker ( DockerOpts (..), DockerOptsMonoid (..) ) import Stack.Types.DumpLogs ( DumpLogs (..) ) import Stack.Types.GlobalOpts ( GlobalOpts (..) ) +import Stack.Types.MsysEnvironment + ( MsysEnvironment (..), msysEnvArch ) import Stack.Types.Nix ( NixOpts (..) ) import Stack.Types.Platform ( PlatformVariant (..), platformOnlyRelDir ) @@ -131,15 +136,15 @@ ( ProjectAndConfigMonoid (..), parseProjectAndConfigMonoid ) import Stack.Types.ProjectConfig ( ProjectConfig (..) ) import Stack.Types.PvpBounds ( PvpBounds (..), PvpBoundsType (..) ) -import Stack.Types.Resolver ( AbstractResolver (..), Snapshots (..) ) import Stack.Types.Runner ( HasRunner (..), Runner (..), globalOptsL, terminalL ) +import Stack.Types.Snapshot ( AbstractSnapshot (..), Snapshots (..) ) import Stack.Types.SourceMap ( CommonPackage (..), DepPackage (..), ProjectPackage (..) , SMWanted (..) ) import Stack.Types.StackYamlLoc ( StackYamlLoc (..) ) -import Stack.Types.UnusedFlags ( FlagSource (..) ) +import Stack.Types.UnusedFlags ( FlagSource (..), UnusedFlags (..) ) import Stack.Types.Version ( IntersectingVersionRange (..), VersionCheck (..) , stackVersion, withinRange @@ -150,57 +155,9 @@ import System.PosixCompat.Files ( fileOwner, getFileStatus ) import System.Posix.User ( getEffectiveUserID ) --- | If deprecated path exists, use it and print a warning. Otherwise, return --- the new path. -tryDeprecatedPath :: - HasTerm env - => Maybe T.Text - -- ^ Description of file for warning (if Nothing, no deprecation warning is - -- displayed) - -> (Path Abs a -> RIO env Bool) - -- ^ Test for existence - -> Path Abs a - -- ^ New path - -> Path Abs a - -- ^ Deprecated path - -> RIO env (Path Abs a, Bool) - -- ^ (Path to use, whether it already exists) -tryDeprecatedPath mWarningDesc exists new old = do - newExists <- exists new - if newExists - then pure (new, True) - else do - oldExists <- exists old - if oldExists - then do - case mWarningDesc of - Nothing -> pure () - Just desc -> - prettyWarnL - [ flow "Location of" - , flow (T.unpack desc) - , "at" - , style Dir (fromString $ toFilePath old) - , flow "is deprecated; rename it to" - , style Dir (fromString $ toFilePath new) - , "instead." - ] - pure (old, True) - else pure (new, False) - --- | Get the location of the implicit global project directory. If the directory --- already exists at the deprecated location, its location is returned. --- Otherwise, the new location is returned. -getImplicitGlobalProjectDir ::HasTerm env => Config -> RIO env (Path Abs Dir) -getImplicitGlobalProjectDir config = - --TEST no warning printed - fst <$> tryDeprecatedPath - Nothing - doesDirExist - (implicitGlobalProjectDir stackRoot) - (implicitGlobalProjectDirDeprecated stackRoot) - where - stackRoot = view stackRootL config +-- | Get the location of the implicit global project directory. +getImplicitGlobalProjectDir :: HasConfig env => RIO env (Path Abs Dir) +getImplicitGlobalProjectDir = view $ stackRootL . to implicitGlobalProjectDir -- | Download the 'Snapshots' value from stackage.org. getSnapshots :: HasConfig env => RIO env Snapshots @@ -212,44 +169,51 @@ logDebug "Done downloading and parsing snapshot versions file" pure $ getResponseBody result --- | Turn an 'AbstractResolver' into a 'Resolver'. -makeConcreteResolver :: +-- | Turn an 'AbstractSnapshot' into a 'RawSnapshotLocation'. +makeConcreteSnapshot :: HasConfig env - => AbstractResolver + => AbstractSnapshot -> RIO env RawSnapshotLocation -makeConcreteResolver (ARResolver r) = pure r -makeConcreteResolver ar = do - r <- - case ar of - ARGlobal -> do - config <- view configL - implicitGlobalDir <- getImplicitGlobalProjectDir config - let fp = implicitGlobalDir </> stackDotYaml +makeConcreteSnapshot (ASSnapshot s) = pure s +makeConcreteSnapshot as = do + s <- + case as of + ASGlobal -> do + fp <- getImplicitGlobalProjectDir <&> (</> stackDotYaml) iopc <- loadConfigYaml (parseProjectAndConfigMonoid (parent fp)) fp ProjectAndConfigMonoid project _ <- liftIO iopc - pure project.resolver - ARLatestNightly -> + pure project.snapshot + ASLatestNightly -> RSLSynonym . Nightly . (.nightly) <$> getSnapshots - ARLatestLTSMajor x -> do + ASLatestLTSMajor x -> do snapshots <- getSnapshots case IntMap.lookup x snapshots.lts of Nothing -> throwIO $ NoLTSWithMajorVersion x Just y -> pure $ RSLSynonym $ LTS x y - ARLatestLTS -> do + ASLatestLTS -> do snapshots <- getSnapshots if IntMap.null snapshots.lts then throwIO NoLTSFound else let (x, y) = IntMap.findMax snapshots.lts in pure $ RSLSynonym $ LTS x y prettyInfoL - [ flow "Selected resolver:" - , style Current (fromString $ T.unpack $ textDisplay r) <> "." + [ flow "Selected snapshot:" + , style Current (fromString $ T.unpack $ textDisplay s) <> "." ] - pure r + pure s --- | Get the latest snapshot resolver available. -getLatestResolver :: HasConfig env => RIO env RawSnapshotLocation -getLatestResolver = do +-- | Get the raw snapshot from the global options. +getRawSnapshot :: HasConfig env => RIO env (Maybe RawSnapshot) +getRawSnapshot = do + mASnapshot <- view $ globalOptsL . to (.snapshot) + forM mASnapshot $ \aSnapshot -> do + concrete <- makeConcreteSnapshot aSnapshot + loc <- completeSnapshotLocation concrete + loadSnapshot loc + +-- | Get the latest snapshot available. +getLatestSnapshot :: HasConfig env => RIO env RawSnapshotLocation +getLatestSnapshot = do snapshots <- getSnapshots let mlts = uncurry LTS <$> listToMaybe (reverse (IntMap.toList snapshots.lts)) @@ -259,16 +223,17 @@ configFromConfigMonoid :: (HasRunner env, HasTerm env) => Path Abs Dir -- ^ Stack root, e.g. ~/.stack - -> Path Abs File -- ^ user config file path, e.g. ~/.stack/config.yaml - -> Maybe AbstractResolver + -> Path Abs File + -- ^ User-specific global configuration file. + -> Maybe AbstractSnapshot -> ProjectConfig (Project, Path Abs File) -> ConfigMonoid -> (Config -> RIO env a) -> RIO env a configFromConfigMonoid stackRoot - userConfigPath - resolver + userGlobalConfigFile + snapshot project configMonoid inner @@ -322,6 +287,10 @@ installGHC = fromFirstTrue configMonoid.installGHC skipGHCCheck = fromFirstFalse configMonoid.skipGHCCheck skipMsys = fromFirstFalse configMonoid.skipMsys + defMsysEnvironment = case platform of + Platform I386 Windows -> Just MINGW32 + Platform X86_64 Windows -> Just MINGW64 + _ -> Nothing extraIncludeDirs = configMonoid.extraIncludeDirs extraLibDirs = configMonoid.extraLibDirs customPreprocessorExts = configMonoid.customPreprocessorExts @@ -336,11 +305,20 @@ requireStackVersion = simplifyVersionRange configMonoid.requireStackVersion.intersectingVersionRange compilerCheck = fromFirst MatchMinor configMonoid.compilerCheck + msysEnvironment <- case defMsysEnvironment of + -- Ignore the configuration setting if there is no default for the + -- platform. + Nothing -> pure Nothing + Just defMsysEnv -> do + let msysEnv = fromFirst defMsysEnv configMonoid.msysEnvironment + if msysEnvArch msysEnv == arch + then pure $ Just msysEnv + else prettyThrowM $ BadMsysEnvironment msysEnv arch platformVariant <- liftIO $ maybe PlatformVariantNone PlatformVariant <$> lookupEnv platformVariantEnvVar let build = buildOptsFromMonoid configMonoid.buildOpts docker <- - dockerOptsFromMonoid (fmap fst mproject) resolver configMonoid.dockerOpts + dockerOptsFromMonoid (fmap fst mproject) snapshot configMonoid.dockerOpts nix <- nixOptsFromMonoid configMonoid.nixOpts os systemGHC <- case (getFirst configMonoid.systemGHC, nix.enable) of @@ -403,6 +381,23 @@ -- resolveDirMaybe. `catchAny` const (throwIO (NoSuchDirectory userPath)) + fileWatchHook <- + case getFirst configMonoid.fileWatchHook of + Nothing -> pure Nothing + Just userPath -> + ( case mproject of + -- Not in a project + Nothing -> Just <$> resolveFile' userPath + -- Resolves to the project dir and appends the user path if it is + -- relative + Just (_, configYaml) -> + Just <$> resolveFile (parent configYaml) userPath + ) + -- TODO: Either catch specific exceptions or add a + -- parseRelAsAbsFileMaybe utility and use it along with + -- resolveFileMaybe. + `catchAny` + const (throwIO (NoSuchFile userPath)) jobs <- case getFirst configMonoid.jobs of Nothing -> liftIO getNumProcessors @@ -425,16 +420,19 @@ fromFirst AGOLocals configMonoid.applyGhcOptions applyProgOptions = fromFirst APOLocals configMonoid.applyProgOptions - allowNewer = fromFirst False configMonoid.allowNewer + allowNewer = configMonoid.allowNewer allowNewerDeps = coerce configMonoid.allowNewerDeps - defaultTemplate = getFirst configMonoid.defaultTemplate + defaultInitSnapshot <- do + root <- getCurrentDir + let resolve = (First <$>) . traverse (resolvePaths (Just root)) . getFirst + resolve configMonoid.defaultInitSnapshot + let defaultTemplate = getFirst configMonoid.defaultTemplate dumpLogs = fromFirst DumpWarningLogs configMonoid.dumpLogs - saveHackageCreds = - fromFirst True configMonoid.saveHackageCreds + saveHackageCreds = configMonoid.saveHackageCreds hackageBaseUrl = fromFirst Constants.hackageBaseUrl configMonoid.hackageBaseUrl hideSourcePaths = fromFirstTrue configMonoid.hideSourcePaths - recommendUpgrade = fromFirstTrue configMonoid.recommendUpgrade + recommendStackUpgrade = fromFirstTrue configMonoid.recommendStackUpgrade notifyIfNixOnPath = fromFirstTrue configMonoid.notifyIfNixOnPath notifyIfGhcUntested = fromFirstTrue configMonoid.notifyIfGhcUntested notifyIfCabalUntested = fromFirstTrue configMonoid.notifyIfCabalUntested @@ -461,16 +459,7 @@ & stylesUpdateL .~ stylesUpdate' & useColorL .~ useColor'' go = configRunner'.globalOpts - pic <- - case getFirst configMonoid.packageIndex of - Nothing -> - case getFirst configMonoid.packageIndices of - Nothing -> pure defaultPackageIndexConfig - Just [pic] -> do - prettyWarn packageIndicesWarning - pure pic - Just x -> prettyThrowIO $ MultiplePackageIndices x - Just pic -> pure pic + pic = fromFirst defaultPackageIndexConfig configMonoid.packageIndex mpantryRoot <- liftIO $ lookupEnv pantryRootEnvVar pantryRoot <- case mpantryRoot of @@ -498,9 +487,18 @@ <> "/" <> display day <> ".yaml" mkRSLUrl builder = RSLUrl (utf8BuilderToText builder) Nothing addr' = display $ T.dropWhileEnd (=='/') addr + globalHintsLoc <- case getFirst configMonoid.globalHintsLocation of + Nothing -> pure defaultGlobalHintsLocation + Just unresolverGlobalHintsLoc -> do + resolvedGlobalHintsLocation <- + resolvePaths (Just stackRoot) unresolverGlobalHintsLoc + pure $ const resolvedGlobalHintsLocation let stackDeveloperMode = fromFirst stackDeveloperModeDefault configMonoid.stackDeveloperMode + hpackForce = if fromFirstFalse configMonoid.hpackForce + then Hpack.Force + else Hpack.NoForce casa = if fromFirstTrue configMonoid.casaOpts.enable then @@ -527,14 +525,16 @@ pantryRoot pic (maybe HpackBundled HpackCommand $ getFirst configMonoid.overrideHpack) + hpackForce clConnectionCount casa snapLoc + globalHintsLoc (\pantryConfig -> initUserStorage (stackRoot </> relFileStorage) ( \userStorage -> inner Config { workDir - , userConfigPath + , userGlobalConfigFile , build , docker , nix @@ -552,9 +552,11 @@ , installGHC , skipGHCCheck , skipMsys + , msysEnvironment , compilerCheck , compilerRepository , localBin + , fileWatchHook , requireStackVersion , jobs , overrideGccPath @@ -576,6 +578,7 @@ , applyProgOptions , allowNewer , allowNewerDeps + , defaultInitSnapshot , defaultTemplate , allowDifferentUser , dumpLogs @@ -586,10 +589,10 @@ , runner , pantryConfig , stackRoot - , resolver + , snapshot , userStorage , hideSourcePaths - , recommendUpgrade + , recommendStackUpgrade , notifyIfNixOnPath , notifyIfGhcUntested , notifyIfCabalUntested @@ -667,7 +670,7 @@ loadConfig inner = do mstackYaml <- view $ globalOptsL . to (.stackYaml) mproject <- loadProjectConfig mstackYaml - mresolver <- view $ globalOptsL . to (.resolver) + mASnapshot <- view $ globalOptsL . to (.snapshot) configArgs <- view $ globalOptsL . to (.configMonoid) (configRoot, stackRoot, userOwnsStackRoot) <- determineStackRootAndOwnership configArgs @@ -692,7 +695,7 @@ configFromConfigMonoid stackRoot userConfigPath - mresolver + mASnapshot mproject' (mconcat $ configArgs : addConfigMonoid extraConfigs) @@ -724,30 +727,33 @@ withBuildConfig inner = do config <- ask - -- If provided, turn the AbstractResolver from the command line into a - -- Resolver that can be used below. + -- If provided, turn the AbstractSnapshot from the command line into a + -- snapshot that can be used below. - -- The configResolver and mcompiler are provided on the command line. In order - -- to properly deal with an AbstractResolver, we need a base directory (to + -- The snapshot and mcompiler are provided on the command line. In order + -- to properly deal with an AbstractSnapshot, we need a base directory (to -- deal with custom snapshot relative paths). We consider the current working - -- directory to be the correct base. Let's calculate the mresolver first. - mresolver <- forM config.resolver $ \aresolver -> do - logDebug ("Using resolver: " <> display aresolver <> " specified on command line") - makeConcreteResolver aresolver + -- directory to be the correct base. Let's calculate the mSnapshot first. + mSnapshot <- forM config.snapshot $ \aSnapshot -> do + logDebug $ + "Using snapshot: " + <> display aSnapshot + <> " specified on command line" + makeConcreteSnapshot aSnapshot - (project', stackYaml) <- case config.project of + (project', configFile) <- case config.project of PCProject (project, fp) -> do forM_ project.userMsg prettyWarnS - pure (project, fp) + pure (project, Right fp) PCNoProject extraDeps -> do p <- - case mresolver of - Nothing -> throwIO NoResolverWhenUsingNoProject - Just _ -> getEmptyProject mresolver extraDeps - pure (p, config.userConfigPath) + case mSnapshot of + Nothing -> throwIO NoSnapshotWhenUsingNoProject + Just _ -> getEmptyProject mSnapshot extraDeps + pure (p, Left config.userGlobalConfigFile) PCGlobalProject -> do logDebug "Run from outside a project, using implicit global project config" - destDir <- getImplicitGlobalProjectDir config + destDir <- getImplicitGlobalProjectDir let dest :: Path Abs File dest = destDir </> stackDotYaml dest' :: FilePath @@ -759,31 +765,31 @@ iopc <- loadConfigYaml (parseProjectAndConfigMonoid destDir) dest ProjectAndConfigMonoid project _ <- liftIO iopc when (view terminalL config) $ - case config.resolver of + case config.snapshot of Nothing -> logDebug $ - "Using resolver: " - <> display project.resolver + "Using snapshot: " + <> display project.snapshot <> " from implicit global project's config file: " <> fromString dest' Just _ -> pure () - pure (project, dest) + pure (project, Right dest) else do prettyInfoL [ flow "Writing the configuration file for the implicit \ \global project to:" , pretty dest <> "." , flow "Note: You can change the snapshot via the" - , style Shell "resolver" + , style Shell "snapshot" , flow "field there." ] - p <- getEmptyProject mresolver [] + p <- getEmptyProject mSnapshot [] liftIO $ do writeBinaryFileAtomic dest $ byteString $ S.concat - [ "# This is the implicit global project's config file, which is only used when\n" - , "# 'stack' is run outside of a real project. Settings here do _not_ act as\n" + [ "# This is the implicit global project's configuration file, which is only used\n" + , "# when 'stack' is run outside of a real project. Settings here do _not_ act as\n" , "# defaults for all projects. To change Stack's default settings, edit\n" - , "# '", encodeUtf8 (T.pack $ toFilePath config.userConfigPath), "' instead.\n" + , "# '", encodeUtf8 (T.pack $ toFilePath config.userGlobalConfigFile), "' instead.\n" , "#\n" , "# For more information about Stack's configuration, see\n" , "# http://docs.haskellstack.org/en/stable/yaml_configuration/\n" @@ -793,29 +799,31 @@ "This is the implicit global project, which is " <> "used only when 'stack' is run\noutside of a " <> "real project.\n" - pure (p, dest) + pure (p, Right dest) mcompiler <- view $ globalOptsL . to (.compiler) let project :: Project project = project' { Project.compiler = mcompiler <|> project'.compiler - , Project.resolver = fromMaybe project'.resolver mresolver + , Project.snapshot = fromMaybe project'.snapshot mSnapshot } + -- We are indifferent as to whether the configuration file is a + -- user-specific global or a project-level one. + eitherConfigFile = EE.fromEither configFile extraPackageDBs <- mapM resolveDir' project.extraPackageDBs - smWanted <- lockCachedWanted stackYaml project.resolver $ - fillProjectWanted stackYaml config project + smWanted <- lockCachedWanted eitherConfigFile project.snapshot $ + fillProjectWanted eitherConfigFile config project - -- Unfortunately redoes getProjectWorkDir, since we don't have a BuildConfig - -- yet + -- Unfortunately redoes getWorkDir, since we don't have a BuildConfig yet workDir <- view workDirL - let projectStorageFile = parent stackYaml </> workDir </> relFileStorage + let projectStorageFile = parent eitherConfigFile </> workDir </> relFileStorage initProjectStorage projectStorageFile $ \projectStorage -> do let bc = BuildConfig { config , smWanted , extraPackageDBs - , stackYaml + , configFile , curator = project.curator , projectStorage } @@ -825,17 +833,17 @@ Maybe RawSnapshotLocation -> [PackageIdentifierRevision] -> RIO Config Project - getEmptyProject mresolver extraDeps = do - r <- case mresolver of - Just resolver -> do + getEmptyProject mSnapshot extraDeps = do + snapshot <- case mSnapshot of + Just snapshot -> do prettyInfoL [ flow "Using the snapshot" - , style Current (fromString $ T.unpack $ textDisplay resolver) + , style Current (fromString $ T.unpack $ textDisplay snapshot) , flow "specified on the command line." ] - pure resolver + pure snapshot Nothing -> do - r'' <- getLatestResolver + r'' <- getLatestSnapshot prettyInfoL [ flow "Using the latest snapshot" , style Current (fromString $ T.unpack $ textDisplay r'') <> "." @@ -846,7 +854,7 @@ , packages = [] , extraDeps = map (RPLImmutable . flip RPLIHackage Nothing) extraDeps , flagsByPkg = mempty - , resolver = r + , snapshot , compiler = Nothing , extraPackageDBs = [] , curator = Nothing @@ -855,18 +863,20 @@ fillProjectWanted :: (HasLogFunc env, HasPantryConfig env, HasProcessContext env) - => Path Abs t + => Path Abs File + -- ^ Location of the configuration file, which may be either a + -- user-specific global or a project-level one. -> Config -> Project -> Map RawPackageLocationImmutable PackageLocationImmutable -> WantedCompiler -> Map PackageName (Bool -> RIO env DepPackage) -> RIO env (SMWanted, [CompletedPLI]) -fillProjectWanted stackYamlFP config project locCache snapCompiler snapPackages = do +fillProjectWanted configFile config project locCache snapCompiler snapPackages = do let bopts = config.build packages0 <- for project.packages $ \fp@(RelFilePath t) -> do - abs' <- resolveDir (parent stackYamlFP) (T.unpack t) + abs' <- resolveDir (parent configFile) (T.unpack t) let resolved = ResolvedPath fp abs' pp <- mkProjectPackage YesPrintWarnings resolved bopts.buildHaddocks pure (pp.projectCommon.name, pp) @@ -923,7 +933,7 @@ deps2 = mergeApply deps1 pFlags $ \_ d flags -> d { depCommon = d.depCommon { flags = flags } } - checkFlagsUsedThrowing pFlags FSStackYaml packages1 deps1 + checkFlagsUsedThrowing pFlags packages1 deps1 let pkgGhcOptions = config.ghcOptionsByName deps = mergeApply deps2 pkgGhcOptions $ \_ d options -> @@ -941,11 +951,44 @@ { compiler = fromMaybe snapCompiler project.compiler , project = packages , deps = deps - , snapshotLocation = project.resolver + , snapshotLocation = project.snapshot } pure (wanted, catMaybes mcompleted) +-- | Check if a package is a project package or a dependency and, if it is, +-- if all the specified flags are defined in the package's Cabal file. +checkFlagsUsedThrowing :: + forall m. (MonadIO m, MonadThrow m) + => Map PackageName (Map FlagName Bool) + -> Map PackageName ProjectPackage + -> Map PackageName DepPackage + -> m () +checkFlagsUsedThrowing packageFlags projectPackages deps = do + unusedFlags <- forMaybeM (Map.toList packageFlags) getUnusedPackageFlags + unless (null unusedFlags) $ + prettyThrowM $ InvalidFlagSpecification unusedFlags + where + getUnusedPackageFlags :: + (PackageName, Map FlagName Bool) + -> m (Maybe UnusedFlags) + getUnusedPackageFlags (name, userFlags) = case maybeCommon of + -- Package is not available as project or dependency + Nothing -> pure $ Just $ UFNoPackage FSStackYaml name + -- Package exists, let's check if the flags are defined + Just common -> do + gpd <- liftIO common.gpd + let pname = pkgName $ PD.package $ PD.packageDescription gpd + pkgFlags = Set.fromList $ map PD.flagName $ PD.genPackageFlags gpd + unused = Map.keysSet $ Map.withoutKeys userFlags pkgFlags + pure $ if Set.null unused + -- All flags are defined, nothing to do + then Nothing + -- Error about the undefined flags + else Just $ UFFlagsNotDefined FSStackYaml pname pkgFlags unused + where + maybeCommon = fmap (.projectCommon) (Map.lookup name projectPackages) + <|> fmap (.depCommon) (Map.lookup name deps) -- | Check if there are any duplicate package names and, if so, throw an -- exception. @@ -958,7 +1001,6 @@ hasMultiples (_, _:_:_) = True hasMultiples _ = False - -- | Get the Stack root, e.g. @~/.stack@, and determine whether the user owns it. -- -- On Windows, the second value is always 'True'. @@ -1060,19 +1102,17 @@ getExtraConfigs :: HasTerm env => Path Abs File -- ^ use config path -> RIO env [Path Abs File] -getExtraConfigs userConfigPath = do - defaultStackGlobalConfigPath <- getDefaultGlobalConfigPath - liftIO $ do - env <- getEnvironment - mstackConfig <- - maybe (pure Nothing) (fmap Just . parseAbsFile) - $ lookup "STACK_CONFIG" env - mstackGlobalConfig <- - maybe (pure Nothing) (fmap Just . parseAbsFile) - $ lookup "STACK_GLOBAL_CONFIG" env - filterM doesFileExist - $ fromMaybe userConfigPath mstackConfig - : maybe [] pure (mstackGlobalConfig <|> defaultStackGlobalConfigPath) +getExtraConfigs userConfigPath = liftIO $ do + env <- getEnvironment + mstackConfig <- + maybe (pure Nothing) (fmap Just . parseAbsFile) + $ lookup "STACK_CONFIG" env + mstackGlobalConfig <- + maybe (pure Nothing) (fmap Just . parseAbsFile) + $ lookup "STACK_GLOBAL_CONFIG" env + filterM doesFileExist + $ fromMaybe userConfigPath mstackConfig + : maybe [] pure (mstackGlobalConfig <|> defaultGlobalConfigPath) -- | Load and parse YAML from the given config file. Throws -- 'ParseConfigFileException' when there's a decoding error. @@ -1160,41 +1200,18 @@ ProjectAndConfigMonoid project config <- liftIO iopc pure (project, fp, config) --- | Get the location of the default Stack configuration file. If a file already --- exists at the deprecated location, its location is returned. Otherwise, the --- new location is returned. -getDefaultGlobalConfigPath :: - HasTerm env - => RIO env (Maybe (Path Abs File)) -getDefaultGlobalConfigPath = - case (defaultGlobalConfigPath, defaultGlobalConfigPathDeprecated) of - (Just new, Just old) -> - Just . fst <$> - tryDeprecatedPath - (Just "non-project global configuration file") - doesFileExist - new - old - (Just new,Nothing) -> pure (Just new) - _ -> pure Nothing - --- | Get the location of the default user configuration file. If a file already --- exists at the deprecated location, its location is returned. Otherwise, the --- new location is returned. +-- | Get the location of the default user global configuration file. getDefaultUserConfigPath :: HasTerm env => Path Abs Dir -> RIO env (Path Abs File) -getDefaultUserConfigPath stackRoot = do - (path, exists) <- tryDeprecatedPath - (Just "non-project configuration file") - doesFileExist - (defaultUserConfigPath stackRoot) - (defaultUserConfigPathDeprecated stackRoot) - unless exists $ do - ensureDir (parent path) - liftIO $ writeBinaryFileAtomic path defaultConfigYaml - pure path +getDefaultUserConfigPath configRoot = do + let userConfigPath = defaultUserConfigPath configRoot + userConfigExists <- doesFileExist userConfigPath + unless userConfigExists $ do + ensureDir (parent userConfigPath) + liftIO $ writeBinaryFileAtomic userConfigPath defaultConfigYaml + pure userConfigPath packagesParser :: Parser [String] packagesParser = many (strOption
src/Stack/Config/Build.hs view
@@ -54,6 +54,15 @@ , haddockDeps = if isHaddockFromHackage then Nothing else getFirst buildMonoid.haddockDeps + , haddockExecutables = + not isHaddockFromHackage + && fromFirstFalse buildMonoid.haddockExecutables + , haddockTests = + not isHaddockFromHackage + && fromFirstFalse buildMonoid.haddockTests + , haddockBenchmarks = + not isHaddockFromHackage + && fromFirstFalse buildMonoid.haddockBenchmarks , haddockInternal = not isHaddockFromHackage && fromFirstFalse buildMonoid.haddockInternal
src/Stack/Config/Docker.hs view
@@ -19,28 +19,28 @@ ( DockerOpts (..), DockerMonoidRepoOrImage (..) , DockerOptsMonoid (..), dockerImageArgName ) -import Stack.Types.Resolver ( AbstractResolver (..) ) +import Stack.Types.Snapshot ( AbstractSnapshot (..) ) import Stack.Types.Version ( IntersectingVersionRange (..) ) -- | Type representing exceptions thrown by functions exported by the -- "Stack.Config.Docker" module. data ConfigDockerException - = ResolverNotSupportedException !(Maybe Project) !(Maybe AbstractResolver) - -- ^ Only LTS resolvers are supported for default image tag. + = SnapshotNotSupportedException !(Maybe Project) !(Maybe AbstractSnapshot) + -- ^ Only LTS snapshots are supported for default image tag. deriving (Show, Typeable) instance Exception ConfigDockerException where - displayException (ResolverNotSupportedException mproject maresolver) = + displayException (SnapshotNotSupportedException mproject mASnapshot) = concat [ "Error: [S-8575]\n" - , "Resolver not supported for Docker images:\n " - , case (mproject, maresolver) of - (Nothing, Nothing) -> "no resolver specified" - (_, Just aresolver) -> - T.unpack $ utf8BuilderToText $ display aresolver + , "Snapshot resolver not supported for Docker images:\n " + , case (mproject, mASnapshot) of + (Nothing, Nothing) -> "no snapshot specified" + (_, Just aSnapshot) -> + T.unpack $ utf8BuilderToText $ display aSnapshot (Just project, Nothing) -> - T.unpack $ utf8BuilderToText $ display project.resolver - , "\nUse an LTS resolver, or set the '" + T.unpack $ utf8BuilderToText $ display project.snapshot + , "\nUse an LTS snapshot, or set the '" , T.unpack dockerImageArgName , "' explicitly, in your configuration file."] @@ -49,15 +49,15 @@ MonadThrow m => String -- ^ base -> Maybe Project - -> Maybe AbstractResolver + -> Maybe AbstractSnapshot -> m String -addDefaultTag base mproject maresolver = do - let exc = throwM $ ResolverNotSupportedException mproject maresolver - lts <- case maresolver of - Just (ARResolver (RSLSynonym lts@(LTS _ _))) -> pure lts - Just _aresolver -> exc +addDefaultTag base mproject mASnapshot = do + let exc = throwM $ SnapshotNotSupportedException mproject mASnapshot + lts <- case mASnapshot of + Just (ASSnapshot (RSLSynonym lts@(LTS _ _))) -> pure lts + Just _aSnapshot -> exc Nothing -> - case (.resolver) <$> mproject of + case (.snapshot) <$> mproject of Just (RSLSynonym lts@(LTS _ _)) -> pure lts _ -> exc pure $ base ++ ":" ++ show lts @@ -66,17 +66,17 @@ dockerOptsFromMonoid :: MonadThrow m => Maybe Project - -> Maybe AbstractResolver + -> Maybe AbstractSnapshot -> DockerOptsMonoid -> m DockerOpts -dockerOptsFromMonoid mproject maresolver dockerMonoid = do +dockerOptsFromMonoid mproject mASnapshot dockerMonoid = do let image = case getFirst dockerMonoid.repoOrImage of - Nothing -> addDefaultTag "fpco/stack-build" mproject maresolver + Nothing -> addDefaultTag "fpco/stack-build" mproject mASnapshot Just (DockerMonoidImage image') -> pure image' Just (DockerMonoidRepo repo) -> case find (`elem` (":@" :: String)) repo of - Nothing -> addDefaultTag repo mproject maresolver + Nothing -> addDefaultTag repo mproject mASnapshot -- Repo already specified a tag or digest, so don't append default Just _ -> pure repo let enable =
src/Stack/ConfigCmd.hs view
@@ -19,8 +19,8 @@ import qualified Data.Aeson.Key as Key import qualified Data.Aeson.KeyMap as KeyMap import Data.Attoparsec.Text as P - ( Parser, parseOnly, skip, skipWhile, string, takeText - , takeWhile + ( Parser, parseOnly, skip, string, takeText, takeWhile + , takeWhile1 ) import qualified Data.Map.Merge.Strict as Map import qualified Data.Text as T @@ -35,21 +35,24 @@ import qualified RIO.NonEmpty as NE import RIO.Process ( envVarsL ) import Stack.Config - ( makeConcreteResolver, getProjectConfig + ( makeConcreteSnapshot, getProjectConfig , getImplicitGlobalProjectDir ) import Stack.Constants ( stackDotYaml ) import Stack.Prelude import Stack.Types.Config ( Config (..), HasConfig (..) ) import Stack.Types.ConfigMonoid - ( configMonoidInstallGHCName, configMonoidSystemGHCName ) + ( configMonoidInstallGHCName + , configMonoidRecommendStackUpgradeName + , configMonoidSystemGHCName + ) import Stack.Types.EnvConfig ( EnvConfig ) import Stack.Types.EnvSettings ( EnvSettings (..) ) import Stack.Types.GHCVariant ( HasGHCVariant ) import Stack.Types.GlobalOpts ( GlobalOpts (..) ) import Stack.Types.ProjectConfig ( ProjectConfig (..) ) -import Stack.Types.Resolver ( AbstractResolver, readAbstractResolver ) import Stack.Types.Runner ( globalOptsL ) +import Stack.Types.Snapshot ( AbstractSnapshot, readAbstractSnapshot ) import System.Environment ( getEnvironment ) -- | Type repesenting exceptions thrown by functions exported by the @@ -64,10 +67,11 @@ ++ "'config' command used when no project configuration available." data ConfigCmdSet - = ConfigCmdSetSnapshot !(Unresolved AbstractResolver) - | ConfigCmdSetResolver !(Unresolved AbstractResolver) + = ConfigCmdSetSnapshot !(Unresolved AbstractSnapshot) + | ConfigCmdSetResolver !(Unresolved AbstractSnapshot) | ConfigCmdSetSystemGhc !CommandScope !Bool | ConfigCmdSetInstallGhc !CommandScope !Bool + | ConfigCmdSetRecommendStackUpgrade !CommandScope !Bool | ConfigCmdSetDownloadPrefix !CommandScope !Text data CommandScope @@ -82,6 +86,7 @@ configCmdSetScope (ConfigCmdSetResolver _) = CommandScopeProject configCmdSetScope (ConfigCmdSetSystemGhc scope _) = scope configCmdSetScope (ConfigCmdSetInstallGhc scope _) = scope +configCmdSetScope (ConfigCmdSetRecommendStackUpgrade scope _) = scope configCmdSetScope (ConfigCmdSetDownloadPrefix scope _) = scope cfgCmdSet :: @@ -96,11 +101,10 @@ mstackYaml <- getProjectConfig mstackYamlOption case mstackYaml of PCProject stackYaml -> pure stackYaml - PCGlobalProject -> - fmap (</> stackDotYaml) (getImplicitGlobalProjectDir conf) + PCGlobalProject -> getImplicitGlobalProjectDir <&> (</> stackDotYaml) PCNoProject _extraDeps -> throwIO NoProjectConfigAvailable -- maybe modify the ~/.stack/config.yaml file instead? - CommandScopeGlobal -> pure conf.userConfigPath + CommandScopeGlobal -> pure conf.userGlobalConfigFile rawConfig <- liftIO (readFileUtf8 (toFilePath configFilePath)) config <- either throwM pure (Yaml.decodeEither' $ encodeUtf8 rawConfig) newValue <- cfgCmdSetValue (parent configFilePath) cmd @@ -109,14 +113,16 @@ newValue' = T.stripEnd $ decodeUtf8With lenientDecode $ Yaml.encode newValue -- Text file = toFilePath configFilePath -- String - newYamlLines <- case inConfig config cmdKeys of - Nothing -> do + hits = catMaybes $ NE.toList $ NE.map (inConfig config) cmdKeys + primaryCmdKey = NE.last $ NE.head cmdKeys + newYamlLines <- case hits of + [] -> do prettyInfoL [ pretty configFilePath , flow "has been extended." ] - pure $ writeLines yamlLines "" cmdKeys newValue' - Just oldValue -> if oldValue == newValue + pure $ writeLines yamlLines "" (NE.head cmdKeys) newValue' + [(cmdKey, oldValue)] -> if oldValue == newValue && cmdKey == primaryCmdKey then do prettyInfoL [ pretty configFilePath @@ -124,7 +130,27 @@ \unchanged." ] pure yamlLines - else switchLine configFilePath (NE.last cmdKeys) newValue' [] yamlLines + else do + when (cmdKey /= primaryCmdKey) $ + prettyWarn $ + fillSep + [ pretty configFilePath + , flow "contained a synonym for" + , style Target (fromString $ T.unpack primaryCmdKey) + , parens (style Current (fromString $ T.unpack cmdKey)) + , flow "which has been replaced." + ] + <> line + switchLine configFilePath cmdKey primaryCmdKey newValue' [] yamlLines + _ -> do + -- In practice, this warning should not be encountered because with + -- snapshot and resolver present, Stack will not parse the YAML file. + prettyWarnL + [ pretty configFilePath + , flow "contains more than one possible existing configuration and, \ + \consequently, remains unchanged." + ] + pure yamlLines liftIO $ writeFileUtf8 file (T.unlines newYamlLines) where -- This assumes that if the key does not exist, the lines that can be @@ -145,27 +171,32 @@ inConfig v cmdKeys = case v of Yaml.Object obj -> - case KeyMap.lookup (Key.fromText (NE.head cmdKeys)) obj of - Nothing -> Nothing - Just v' -> case nonEmpty $ NE.tail cmdKeys of - Nothing -> Just v' - Just ks -> inConfig v' ks + let cmdKey = NE.head cmdKeys + in case KeyMap.lookup (Key.fromText cmdKey) obj of + Nothing -> Nothing + Just v' -> case nonEmpty $ NE.tail cmdKeys of + Nothing -> Just (cmdKey, v') + Just ks -> inConfig v' ks _ -> Nothing - switchLine file cmdKey _ searched [] = do + switchLine file cmdKey _ _ searched [] = do prettyWarnL [ style Current (fromString $ T.unpack cmdKey) - , flow "not found in YAML file" + , flow "was not found in YAML file" , pretty file - , flow "as a single line. Multi-line key:value formats are not \ - \supported." + , flow "in the form" + , style Shell "key: value" + , flow "on a single line. Multi-line formats for existing keys are not \ + \supported by the" + , style Shell "config set" + , flow "commands. The file's contents have not been changed." ] pure $ reverse searched - switchLine file cmdKey newValue searched (oldLine:rest) = + switchLine file cmdKey cmdKey' newValue searched (oldLine:rest) = case parseOnly (parseLine cmdKey) oldLine of - Left _ -> switchLine file cmdKey newValue (oldLine:searched) rest + Left _ -> switchLine file cmdKey cmdKey' newValue (oldLine:searched) rest Right (kt, spaces1, spaces2, spaces3, comment) -> do - let newLine = spaces1 <> renderKey cmdKey kt <> spaces2 <> + let newLine = spaces1 <> renderKey cmdKey' kt <> spaces2 <> ":" <> spaces3 <> newValue <> comment prettyInfoL [ pretty file @@ -179,8 +210,12 @@ kt <- parseKey key spaces2 <- P.takeWhile (== ' ') skip (== ':') - spaces3 <- P.takeWhile (== ' ') - skipWhile (/= ' ') + spaces3 <- P.takeWhile1 (== ' ') + -- This assumes that the existing value contains no space characters, which + -- is tolerable for current purposes. + void $ takeWhile1 (/= ' ') + -- This assumes that anything that follows the existing value is a comment, + -- which is tolerable for current purposes. comment <- takeText pure (kt, spaces1, spaces2, spaces3, comment) @@ -232,26 +267,31 @@ snapshotValue root newSnapshot cfgCmdSetValue _ (ConfigCmdSetSystemGhc _ bool') = pure $ Yaml.Bool bool' cfgCmdSetValue _ (ConfigCmdSetInstallGhc _ bool') = pure $ Yaml.Bool bool' +cfgCmdSetValue _ (ConfigCmdSetRecommendStackUpgrade _ bool') = + pure $ Yaml.Bool bool' cfgCmdSetValue _ (ConfigCmdSetDownloadPrefix _ url) = pure $ Yaml.String url snapshotValue :: HasConfig env => Path Abs Dir -- ^ root directory of project - -> Unresolved AbstractResolver -> RIO env Yaml.Value + -> Unresolved AbstractSnapshot + -> RIO env Yaml.Value snapshotValue root snapshot = do snapshot' <- resolvePaths (Just root) snapshot - concreteSnapshot <- makeConcreteResolver snapshot' + concreteSnapshot <- makeConcreteSnapshot snapshot' -- Check that the snapshot actually exists void $ loadSnapshot =<< completeSnapshotLocation concreteSnapshot pure (Yaml.toJSON concreteSnapshot) -cfgCmdSetKeys :: ConfigCmdSet -> NonEmpty Text -cfgCmdSetKeys (ConfigCmdSetSnapshot _) = ["snapshot"] -cfgCmdSetKeys (ConfigCmdSetResolver _) = ["resolver"] -cfgCmdSetKeys (ConfigCmdSetSystemGhc _ _) = [configMonoidSystemGHCName] -cfgCmdSetKeys (ConfigCmdSetInstallGhc _ _) = [configMonoidInstallGHCName] +cfgCmdSetKeys :: ConfigCmdSet -> NonEmpty (NonEmpty Text) +cfgCmdSetKeys (ConfigCmdSetSnapshot _) = [["snapshot"], ["resolver"]] +cfgCmdSetKeys (ConfigCmdSetResolver _) = [["resolver"], ["snapshot"]] +cfgCmdSetKeys (ConfigCmdSetSystemGhc _ _) = [[configMonoidSystemGHCName]] +cfgCmdSetKeys (ConfigCmdSetInstallGhc _ _) = [[configMonoidInstallGHCName]] +cfgCmdSetKeys (ConfigCmdSetRecommendStackUpgrade _ _) = + [[configMonoidRecommendStackUpgradeName]] cfgCmdSetKeys (ConfigCmdSetDownloadPrefix _ _) = - ["package-index", "download-prefix"] + [["package-index", "download-prefix"]] cfgCmdName :: String cfgCmdName = "config" @@ -270,7 +310,7 @@ ( OA.info ( ConfigCmdSetSnapshot <$> OA.argument - readAbstractResolver + readAbstractSnapshot ( OA.metavar "SNAPSHOT" <> OA.help "E.g. \"nightly\" or \"lts-22.8\"" )) ( OA.progDesc @@ -279,34 +319,43 @@ ( OA.info ( ConfigCmdSetResolver <$> OA.argument - readAbstractResolver + readAbstractSnapshot ( OA.metavar "SNAPSHOT" <> OA.help "E.g. \"nightly\" or \"lts-22.8\"" )) ( OA.progDesc - "Change the resolver key of the current project." )) + "Change the snapshot of the current project, using the \ + \resolver key." )) , OA.command (T.unpack configMonoidSystemGHCName) ( OA.info ( ConfigCmdSetSystemGhc - <$> scopeFlag + <$> globalScopeFlag <*> boolArgument ) ( OA.progDesc - "Configure whether Stack should use a system GHC \ - \installation or not." )) + "Configure whether or not Stack should use a system GHC \ + \installation." )) , OA.command (T.unpack configMonoidInstallGHCName) ( OA.info ( ConfigCmdSetInstallGhc - <$> scopeFlag + <$> globalScopeFlag <*> boolArgument ) ( OA.progDesc - "Configure whether Stack should automatically install \ + "Configure whether or not Stack should automatically install \ \GHC when necessary." )) + , OA.command (T.unpack configMonoidRecommendStackUpgradeName) + ( OA.info + ( ConfigCmdSetRecommendStackUpgrade + <$> projectScopeFlag + <*> boolArgument ) + ( OA.progDesc + "Configure whether or not Stack should notify the user if it \ + \identifes a new version of Stack is available." )) , OA.command "package-index" ( OA.info ( OA.hsubparser $ OA.command "download-prefix" ( OA.info ( ConfigCmdSetDownloadPrefix - <$> scopeFlag + <$> globalScopeFlag <*> urlArgument ) ( OA.progDesc "Configure download prefix for Stack's package \ @@ -315,8 +364,8 @@ "Configure Stack's package index" )) ] -scopeFlag :: OA.Parser CommandScope -scopeFlag = OA.flag +globalScopeFlag :: OA.Parser CommandScope +globalScopeFlag = OA.flag CommandScopeProject CommandScopeGlobal ( OA.long "global" @@ -325,6 +374,16 @@ \instead of the project-level configuration file ('stack.yaml')." ) +projectScopeFlag :: OA.Parser CommandScope +projectScopeFlag = OA.flag + CommandScopeGlobal + CommandScopeProject + ( OA.long "project" + <> OA.help + "Modify the project-level configuration file ('stack.yaml') instead of \ + \the user-specific global configuration file ('config.yaml')." + ) + readBool :: OA.ReadM Bool readBool = do s <- OA.readerAsk @@ -353,7 +412,7 @@ configCmdEnvParser :: OA.Parser EnvSettings configCmdEnvParser = EnvSettings - <$> boolFlags True "locals" "include local package information" mempty + <$> boolFlags True "locals" "include information about local packages" mempty <*> boolFlags True "ghc-package-path" "set GHC_PACKAGE_PATH environment variable" mempty <*> boolFlags True "stack-exe" "set STACK_EXE environment variable" mempty
src/Stack/Constants.hs view
@@ -25,11 +25,8 @@ , stackProgNameUpper , wiredInPackages , cabalPackageName - , implicitGlobalProjectDirDeprecated , implicitGlobalProjectDir - , defaultUserConfigPathDeprecated , defaultUserConfigPath - , defaultGlobalConfigPathDeprecated , defaultGlobalConfigPath , platformVariantEnvVar , compilerOptionsCabalFlag @@ -89,6 +86,10 @@ , relDirMingw , relDirMingw32 , relDirMingw64 + , relDirClang32 + , relDirClang64 + , relDirClangArm64 + , relDirUcrt64 , relDirLocal , relDirUsr , relDirInclude @@ -250,28 +251,22 @@ Nothing -> impureThrow WiredInPackagesNotParsedBug where mparsed = mapM parsePackageName - [ "ghc-prim" + [ "rts" + -- Said to be not a \'real\' package + , "ghc-prim" -- A magic package + , "ghc-bignum" + -- A magic package , "integer-gmp" -- No longer magic > 1.0.3.0 (GHC >= 9.0) and deprecated in favour of - -- ghc-bignum. With GHC 9.6.5 at least, there seems to be no problem in + -- ghc-bignum. With GHC 9.6.6 at least, there seems to be no problem in -- using it. , "integer-simple" -- A magic package , "base" -- A magic package - , "rts" - -- Said to be not a \'real\' package , "template-haskell" -- A magic package - , "dph-seq" - -- Deprecated in favour of dph-prim-seq, which does not appear to be - -- magic. With GHC 9.6.5 at least, there seems to be no problem in using - -- it. - , "dph-par" - -- Deprecated in favour of dph-prim-par, which does not appear to be - -- magic. With GHC 9.6.5 at least, there seems to be no problem in using - -- it. , "ghc" -- A magic package , "interactive" @@ -279,9 +274,7 @@ -- if they were defined in modules all sharing a common package -- interactive. See 'Note [The interactive package]' at -- https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Runtime/Context.hs - -- With GHC 9.6.5 at least, there seems to be no problem in using it. - , "ghc-bignum" - -- A magic package + -- With GHC 9.6.6 at least, there seems to be no problem in using it. ] -- | Just to avoid repetition and magic strings. @@ -289,38 +282,19 @@ cabalPackageName = mkPackageName "Cabal" --- | Deprecated implicit global project directory used when outside of a project. -implicitGlobalProjectDirDeprecated :: Path Abs Dir -- ^ Stack root. - -> Path Abs Dir -implicitGlobalProjectDirDeprecated p = - p </> - $(mkRelDir "global") - -- | Implicit global project directory used when outside of a project. -- Normally, @getImplicitGlobalProjectDir@ should be used instead. -implicitGlobalProjectDir :: Path Abs Dir -- ^ Stack root. - -> Path Abs Dir -implicitGlobalProjectDir p = - p </> - $(mkRelDir "global-project") - --- | Deprecated default global config path. -defaultUserConfigPathDeprecated :: Path Abs Dir -> Path Abs File -defaultUserConfigPathDeprecated = (</> $(mkRelFile "stack.yaml")) +implicitGlobalProjectDir :: + Path Abs Dir -- ^ Stack root. + -> Path Abs Dir +implicitGlobalProjectDir p = p </> $(mkRelDir "global-project") --- | Default global config path. --- Normally, @getDefaultUserConfigPath@ should be used instead. +-- | Default user global configuration path. Normally, +-- @getDefaultUserConfigPath@ should be used instead. defaultUserConfigPath :: Path Abs Dir -> Path Abs File defaultUserConfigPath = (</> $(mkRelFile "config.yaml")) --- | Deprecated default global config path. --- Note that this will be @Nothing@ on Windows, which is by design. -defaultGlobalConfigPathDeprecated :: Maybe (Path Abs File) -defaultGlobalConfigPathDeprecated = parseAbsFile "/etc/stack/config" - --- | Default global config path. --- Normally, @getDefaultGlobalConfigPath@ should be used instead. --- Note that this will be @Nothing@ on Windows, which is by design. +-- | Default global config path. On Windows, by design, this will be @Nothing@. defaultGlobalConfigPath :: Maybe (Path Abs File) defaultGlobalConfigPath = parseAbsFile "/etc/stack/config.yaml" @@ -517,6 +491,18 @@ relDirMingw64 :: Path Rel Dir relDirMingw64 = $(mkRelDir "mingw64") +relDirClang32 :: Path Rel Dir +relDirClang32 = $(mkRelDir "clang32") + +relDirClang64 :: Path Rel Dir +relDirClang64 = $(mkRelDir "clang64") + +relDirClangArm64 :: Path Rel Dir +relDirClangArm64 = $(mkRelDir "clangarm64") + +relDirUcrt64 :: Path Rel Dir +relDirUcrt64 = $(mkRelDir "ucrt64") + relDirLocal :: Path Rel Dir relDirLocal = $(mkRelDir "local") @@ -693,7 +679,8 @@ -- | The footer to the help for Stack's subcommands globalFooter :: String globalFooter = - "Command 'stack --help' for global options that apply to all subcommands." + "Command 'stack --help' (or '-h') for global options that apply to all " + <> "subcommands." -- | The type for GitHub REST API HTTP \'Basic\' authentication. gitHubBasicAuthType :: ByteString
src/Stack/Constants/Config.hs view
@@ -26,7 +26,7 @@ import Path ( (</>), mkRelDir, mkRelFile, parseRelDir ) import Stack.Constants ( relDirDist, relDirGhci, relDirHpc ) import Stack.Prelude -import Stack.Types.BuildConfig ( HasBuildConfig, projectRootL ) +import Stack.Types.BuildConfig ( HasBuildConfig, configFileRootL ) import Stack.Types.Compiler ( compilerVersionString ) import Stack.Types.CompilerPaths ( compilerVersionL ) import Stack.Types.Config ( Config, HasConfig, stackRootL, workDirL ) @@ -37,15 +37,15 @@ objectInterfaceDirL :: HasBuildConfig env => Getting r env (Path Abs Dir) objectInterfaceDirL = to $ \env -> -- FIXME is this idiomatic lens code? let workDir = view workDirL env - root = view projectRootL env - in root </> workDir </> $(mkRelDir "odir/") + configFileRoot = view configFileRootL env + in configFileRoot </> workDir </> $(mkRelDir "odir/") -- | GHCi files directory. ghciDirL :: HasBuildConfig env => Getting r env (Path Abs Dir) ghciDirL = to $ \env -> -- FIXME is this idiomatic lens code? let workDir = view workDirL env - root = view projectRootL env - in root </> workDir </> relDirGhci + configFileRoot = view configFileRootL env + in configFileRoot </> workDir </> relDirGhci -- | The directory containing the files used for dirtiness check of source -- files.
src/Stack/Coverage.hs view
@@ -18,14 +18,18 @@ ) where import qualified Data.ByteString.Lazy.Char8 as L8 +import Data.Conduit ( await ) import qualified Data.List as L import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Text.Lazy as LT +import Distribution.Types.MungedPackageId ( computeCompatPackageId ) +import Distribution.Types.UnqualComponentName + ( mkUnqualComponentName ) import Distribution.Version ( mkVersion ) import Path - ( (</>), dirname, filename, parent, parseAbsFile, parseRelDir + ( (</>), dirname, parent, parseAbsFile, parseRelDir , parseRelFile, stripProperPrefix ) import Path.Extra ( toFilePathNoTrailingSep ) @@ -35,7 +39,8 @@ , resolveDir', resolveFile' ) import RIO.ByteString.Lazy ( putStrLn ) -import RIO.Process ( ProcessException, proc, readProcess_ ) +import RIO.Process + ( ExitCodeException, ProcessException, proc, readProcess_ ) import Stack.Build.Target ( NeedTargets (..) ) import Stack.Constants ( relDirAll, relDirCombined, relDirCustom @@ -44,12 +49,15 @@ ) import Stack.Constants.Config ( distDirFromDir, hpcRelativeDir ) import Stack.Package ( hasBuildableMainLibrary ) +import Stack.PackageDump ( ghcPkgField ) import Stack.Prelude import Stack.Runners ( ShouldReexec (..), withConfig, withEnvConfig ) import Stack.Types.BuildConfig ( BuildConfig (..), HasBuildConfig (..) ) import Stack.Types.Compiler ( getGhcVersion ) +import Stack.Types.CompilerPaths ( getGhcPkgExe ) import Stack.Types.CompCollection ( getBuildableSetText ) +import Stack.Types.ComponentUtils ( unqualCompToString ) import Stack.Types.BuildOptsCLI ( BuildOptsCLI (..), defaultBuildOptsCLI ) import Stack.Types.EnvConfig @@ -94,7 +102,7 @@ "[S-9975]" <> line <> fillSep - [ flow "Expected a local package, but" + [ flow "Expected a project package, but" , style Target . fromPackageName $ name , flow "is either an extra-dep or in the snapshot." ] @@ -385,11 +393,13 @@ \case CTest testName -> (pkgPath </>) <$> parseRelFile - ( T.unpack testName + ( testName' ++ "/" - ++ T.unpack testName + ++ testName' ++ ".tix" ) + where + testName' = unqualCompToString testName _ -> prettyThrowIO $ NonTestSuiteTarget name TargetAll PTProject -> do pkgPath <- hpcPkgPath name @@ -609,61 +619,35 @@ => Path Abs Dir -> PackageIdentifier -> Set.Set Text -> Text -> RIO env (Either Text [Text]) findPackageFieldForBuiltPackage pkgDir pkgId subLibs field = do + let subLibNames = + Set.map (LSubLibName . mkUnqualComponentName . T.unpack) subLibs + libraryNames = Set.insert LMainLibName subLibNames + mungedPackageIds = Set.map (computeCompatPackageId pkgId) libraryNames distDir <- distDirFromDir pkgDir + ghcPkgExe <- getGhcPkgExe let inplaceDir = distDir </> relDirPackageConfInplace pkgIdStr = packageIdentifierString pkgId notFoundErr = pure $ Left $ "Failed to find package key for " <> T.pack pkgIdStr - extractField path = do - contents <- readFileUtf8 (toFilePath path) - case asum (map (T.stripPrefix (field <> ": ")) (T.lines contents)) of + extractField mungedPkgId = do + mContents <- catch + (ghcPkgField ghcPkgExe inplaceDir mungedPkgId (T.unpack field) await) + -- A .conf file may not exist in the package database for a library or + -- sub-library, if that component has not been built yet. + (\(_ :: ExitCodeException) -> pure Nothing) + case mContents of Just result -> pure $ Right $ T.strip result Nothing -> notFoundErr logDebug $ "Scanning " <> fromString (toFilePath inplaceDir) - <> " for files matching " + <> " for munged packages matching " <> fromString pkgIdStr - (_, files) <- handleIO (const $ pure ([], [])) $ listDir inplaceDir - logDebug $ displayShow files - -- From all the files obtained from the scanning process above, we need to - -- identify which are .conf files and then ensure that there is at most one - -- .conf file for each library and sub-library (some might be missing if that - -- component has not been built yet). We should error if there are more than - -- one .conf file for a component or if there are no .conf files at all in the - -- searched location. - let toFilename = T.pack . toFilePath . filename - -- strip known prefix and suffix from the found files to determine only - -- the .conf files - stripKnown = - T.stripSuffix ".conf" <=< T.stripPrefix (T.pack (pkgIdStr ++ "-")) - stripped = - mapMaybe (\file -> fmap (,file) . stripKnown . toFilename $ file) files - -- which component could have generated each of these conf files - stripHash n = - let z = T.dropWhile (/= '-') n - in if T.null z then "" else T.tail z - matchedComponents = map (\(n, f) -> (stripHash n, [f])) stripped - byComponents = - Map.restrictKeys (Map.fromListWith (++) matchedComponents) $ Set.insert "" subLibs - logDebug $ displayShow byComponents - if Map.null $ Map.filter (\fs -> length fs > 1) byComponents - then case concat $ Map.elems byComponents of - [] -> notFoundErr - -- for each of these files, we need to extract the requested field - paths -> do - (errors, keys) <- partitionEithers <$> traverse extractField paths - case errors of - (a:_) -> pure $ Left a -- the first error only, since they're repeated anyway - [] -> pure $ Right keys - else - pure - $ Left - $ "Multiple files matching " - <> T.pack (pkgIdStr ++ "-*.conf") - <> " found in " - <> T.pack (toFilePath inplaceDir) - <> ". Maybe try 'stack clean' on this package?" + (errors, keys) <- + partitionEithers <$> traverse extractField (Set.toList mungedPackageIds) + case errors of + (a:_) -> pure $ Left a -- the first error only, since they're repeated anyway + [] -> pure $ Right keys displayReportPath :: HasTerm env
src/Stack/Docker.hs view
@@ -18,6 +18,7 @@ , runContainerAndExit ) where +import Control.Monad.Extra ( whenJust ) import qualified Crypto.Hash as Hash ( Digest, MD5, hash ) import Data.Aeson ( eitherDecode ) import Data.Aeson.Types ( FromJSON (..), (.!=) ) @@ -499,10 +500,9 @@ estackUserEntry0 <- liftIO $ tryJust (guard . isDoesNotExistError) $ User.getUserEntryForName stackUserName -- Switch UID/GID if needed, and update user's home directory - case de.user of - Nothing -> pure () - Just (DockerUser 0 _ _ _) -> pure () - Just du -> withProcessContext envOverride $ + whenJust de.user $ \du -> case du of + DockerUser 0 _ _ _ -> pure () + _ -> withProcessContext envOverride $ updateOrCreateStackUser estackUserEntry0 homeDir du case estackUserEntry0 of Left _ -> pure () @@ -566,8 +566,7 @@ User.setGroupID du.gid handleSetGroups du.groups User.setUserID du.uid - _ <- Files.setFileCreationMask du.umask - pure () + void $ Files.setFileCreationMask du.umask stackUserName = "stack" :: String -- | Remove the contents of a directory, without removing the directory itself.
src/Stack/Dot.hs view
@@ -27,11 +27,11 @@ printGraph dotOpts localNames prunedGraph -- | Print a graphviz graph of the edges in the Map and highlight the given --- local packages +-- project packages printGraph :: (Applicative m, MonadIO m) => DotOpts - -> Set PackageName -- ^ all locals + -> Set PackageName -- ^ All project packages. -> Map PackageName (Set PackageName, DotPayload) -> m () printGraph dotOpts locals graph = do @@ -44,7 +44,8 @@ filteredLocals = Set.filter (\local' -> local' `Set.notMember` dotOpts.prune) locals --- | Print the local nodes with a different style depending on options +-- | Print the project packages nodes with a different style, depending on +-- options printLocalNodes :: (F.Foldable t, MonadIO m) => DotOpts
src/Stack/Exec.hs view
@@ -31,6 +31,8 @@ ( BuildOptsCLI (..), defaultBuildOptsCLI ) import Stack.Types.CompilerPaths ( CompilerPaths (..), HasCompiler (..), getGhcPkgExe ) +import Stack.Types.ComponentUtils + ( unqualCompFromString, unqualCompToText ) import Stack.Types.Config ( Config (..), HasConfig (..) ) import Stack.Types.EnvConfig ( EnvConfig ) import Stack.Types.EnvSettings ( EnvSettings (..) ) @@ -181,17 +183,19 @@ packages <- view $ buildConfigL . to (.smWanted.project) pkgComponents <- for (Map.elems packages) ppComponents let executables = concatMap (filter isCExe . Set.toList) pkgComponents - let (exe, args') = case args of + (exe, args') = case args of [] -> (firstExe, args) - x:xs -> case L.find (\y -> y == CExe (T.pack x)) executables of - Nothing -> (firstExe, args) - argExe -> (argExe, xs) + x:xs -> let matchesExecutable y = y == CExe (unqualCompFromString x) + in case L.find matchesExecutable executables of + Nothing -> (firstExe, args) + argExe -> (argExe, xs) where firstExe = listToMaybe executables case exe of Just (CExe exe') -> do - withNewLocalBuildTargets [T.cons ':' exe'] $ build Nothing - pure (T.unpack exe', args') + let textExeName = unqualCompToText exe' + withNewLocalBuildTargets [T.cons ':' textExeName] $ build Nothing + pure (T.unpack textExeName, args') _ -> prettyThrowIO ExecutableToRunNotFound getGhcCmd pkgs args = do
src/Stack/FileWatch.hs view
@@ -1,5 +1,6 @@-{-# LANGUAGE NoImplicitPrelude #-} -{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedRecordDot #-} +{-# LANGUAGE OverloadedStrings #-} module Stack.FileWatch ( WatchMode (WatchModePoll) @@ -11,10 +12,19 @@ import qualified Data.Map.Merge.Strict as Map import qualified Data.Map.Strict as Map import qualified Data.Set as Set +import qualified Data.Text as T import GHC.IO.Exception ( IOErrorType (InvalidArgument), IOException (..) ) -import Path ( parent ) +import Path ( fileExtension, parent ) +import Path.IO ( doesFileExist, executable, getPermissions ) +import RIO.Process + ( EnvVars, HasProcessContext (..), proc, runProcess + , withModifyEnvVars + ) +import System.Permissions ( osIsWindows ) import Stack.Prelude +import Stack.Types.Config ( Config (..), HasConfig (..) ) +import Stack.Types.Runner ( HasRunner (..), Runner (..) ) import System.FSNotify ( WatchConfig, WatchMode (..), confWatchMode, defaultConfig , eventPath, watchDir, withManagerConf @@ -22,14 +32,14 @@ import System.IO ( getLine ) fileWatch :: - HasTerm env - => ((Set (Path Abs File) -> IO ()) -> RIO env ()) + (HasConfig env, HasTerm env) + => ((Set (Path Abs File) -> IO ()) -> RIO Runner ()) -> RIO env () fileWatch = fileWatchConf defaultConfig fileWatchPoll :: - HasTerm env - => ((Set (Path Abs File) -> IO ()) -> RIO env ()) + (HasConfig env, HasTerm env) + => ((Set (Path Abs File) -> IO ()) -> RIO Runner ()) -> RIO env () fileWatchPoll = fileWatchConf $ defaultConfig { confWatchMode = WatchModePoll 1000000 } @@ -39,11 +49,13 @@ -- The action provided takes a callback that is used to set the files to be -- watched. When any of those files are changed, we rerun the action again. fileWatchConf :: - HasTerm env + (HasConfig env, HasTerm env) => WatchConfig - -> ((Set (Path Abs File) -> IO ()) -> RIO env ()) + -> ((Set (Path Abs File) -> IO ()) -> RIO Runner ()) -> RIO env () -fileWatchConf cfg inner = +fileWatchConf cfg inner = do + runner <- view runnerL + mHook <- view $ configL . to (.fileWatchHook) withRunInIO $ \run -> withManagerConf cfg $ \manager -> do allFiles <- newTVarIO Set.empty dirtyVar <- newTVarIO True @@ -134,7 +146,7 @@ dirty <- readTVar dirtyVar check dirty - eres <- tryAny $ inner setWatched + eres <- tryAny $ runRIO runner (inner setWatched) -- Clear dirtiness flag after the build to avoid an infinite loop caused -- by the build itself triggering dirtiness. This could be viewed as a @@ -143,19 +155,63 @@ -- https://github.com/commercialhaskell/stack/issues/822 atomically $ writeTVar dirtyVar False - case eres of - Left e -> - case fromException e of - Just ExitSuccess -> - prettyInfo $ style Good $ fromString $ displayException e - _ -> case fromException e :: Maybe PrettyException of - Just pe -> prettyError $ pretty pe - _ -> prettyInfo $ style Error $ fromString $ displayException e - _ -> prettyInfo $ - style Good (flow "Success! Waiting for next file change.") + let defaultAction = case eres of + Left e -> + case fromException e of + Just ExitSuccess -> + prettyInfo $ style Good $ fromString $ displayException e + _ -> case fromException e :: Maybe PrettyException of + Just pe -> prettyError $ pretty pe + _ -> prettyInfo $ style Error $ fromString $ displayException e + _ -> prettyInfo $ + style Good (flow "Success! Waiting for next file change.") + case mHook of + Nothing -> defaultAction + Just hook -> do + hookIsExecutable <- handleIO (\_ -> pure False) $ if osIsWindows + then + -- can't really detect executable on windows, only file extension + doesFileExist hook + else executable <$> getPermissions hook + if hookIsExecutable + then runFileWatchHook eres hook + else do + prettyWarn $ + flow "File watch hook not executable. Falling back on default." + defaultAction + prettyInfoL [ "Type" , style Shell "help" , flow "for the available commands. Press enter to force a rebuild." ] + +runFileWatchHook :: + (HasProcessContext env, HasTerm env) + => Either SomeException () + -> Path Abs File + -> RIO env () +runFileWatchHook buildResult hook = + withModifyEnvVars insertBuildResultInEnv $ do + let (cmd, args) = if osIsWindows && isShFile + then ("sh", [toFilePath hook]) + else (toFilePath hook, []) + menv <- view processContextL + exit <- withProcessContext menv $ proc cmd args runProcess + case exit of + ExitSuccess -> pure () + ExitFailure i -> do + prettyWarnL + [ flow "File watch hook exited with code:" + , style Error (fromString $ show i) <> "." + ] + pure () + where + insertBuildResultInEnv :: EnvVars -> EnvVars + insertBuildResultInEnv = Map.insert "HOOK_FW_RESULT" $ case buildResult of + Left e -> T.pack $ displayException e + Right _ -> "" + isShFile = case fileExtension hook of + Just ".sh" -> True + _ -> False
src/Stack/Ghci.hs view
@@ -14,12 +14,14 @@ , ghci ) where +import Control.Monad.Extra ( whenJust ) import Control.Monad.State.Strict ( State, execState, get, modify ) import Data.ByteString.Builder ( byteString ) import qualified Data.ByteString.Char8 as S8 import qualified Data.ByteString.Lazy as LBS import qualified Data.List as L import Data.List.Extra ( (!?) ) +import qualified Data.Map as Map import qualified Data.Map.Strict as M import qualified Data.Set as S import qualified Data.Text as T @@ -32,8 +34,7 @@ import RIO.Process ( exec, withWorkingDir ) import Stack.Build ( buildLocalTargets ) import Stack.Build.Installed ( getInstalled, toInstallMap ) -import Stack.Build.Source - ( getLocalFlags, localDependencies, projectLocalPackages ) +import Stack.Build.Source ( localDependencies, projectLocalPackages ) import Stack.Build.Target ( NeedTargets (..), parseTargets ) import Stack.Constants ( relDirGhciScript, relDirStackProgName, relFileCabalMacrosH @@ -45,7 +46,8 @@ , scriptToLazyByteString ) import Stack.Package - ( buildableExes, buildableForeignLibs, getPackageOpts + ( buildableExes, buildableForeignLibs, buildableSubLibs + , buildableTestSuites, buildableBenchmarks, getPackageOpts , hasBuildableMainLibrary, listOfPackageDeps , packageFromPackageDescription, readDotBuildinfo , resolvePackageDescription, topSortPackageComponent @@ -56,16 +58,16 @@ import Stack.Types.Build.Exception ( BuildPrettyException (..), pprintTargetParseErrors ) import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), stackYamlL ) + ( BuildConfig (..), HasBuildConfig (..), configFileL ) import Stack.Types.BuildOpts ( BuildOpts (..) ) import qualified Stack.Types.BuildOpts as BenchmarkOpts ( BenchmarkOpts (..) ) import qualified Stack.Types.BuildOpts as TestOpts ( TestOpts (..) ) import Stack.Types.BuildOptsCLI - ( ApplyCLIFlag, BuildOptsCLI (..), defaultBuildOptsCLI ) -import Stack.Types.CompCollection ( getBuildableListText ) + ( ApplyCLIFlag (..), BuildOptsCLI (..), defaultBuildOptsCLI ) import Stack.Types.CompilerPaths ( CompilerPaths (..), HasCompiler (..) ) import Stack.Types.Config ( Config (..), HasConfig (..), buildOptsL ) +import Stack.Types.Config.Exception ( ConfigPrettyException (..) ) import Stack.Types.EnvConfig ( EnvConfig (..), HasEnvConfig (..), actualCompilerVersionL , shaPathForBytes @@ -157,7 +159,6 @@ , additionalPackages :: ![String] , mainIs :: !(Maybe Text) , loadLocalDeps :: !Bool - , skipIntermediate :: !Bool , hidePackages :: !(Maybe Bool) , noBuild :: !Bool , onlyMain :: !Bool @@ -218,9 +219,8 @@ } local (set buildOptsL boptsLocal) (ghci ghciOpts) --- | Launch a GHCi session for the given local package targets with the --- given options and configure it with the load paths and extensions --- of those targets. +-- | Launch a GHCi session for the given project package targets with the given +-- options and configure it with the load paths and extensions of those targets. ghci :: HasEnvConfig env => GhciOpts -> RIO env () ghci opts = do let buildOptsCLI = defaultBuildOptsCLI @@ -247,9 +247,7 @@ (inputTargets, mfileTargets) <- case etargets of Right packageTargets -> pure (packageTargets, Nothing) Left rawFileTargets -> do - case mainIsTargets of - Nothing -> pure () - Just _ -> throwM Can'tSpecifyFilesAndMainIs + whenJust mainIsTargets $ \_ -> throwM Can'tSpecifyFilesAndMainIs -- Figure out targets based on filepath targets (targetMap, fileInfo, extraFiles) <- findFileTargets locals rawFileTargets pure (targetMap, Just (fileInfo, extraFiles)) @@ -281,7 +279,7 @@ case targets of TargetAll _ -> [T.pack (packageNameString pn)] TargetComps comps -> [renderPkgComponent (pn, c) | c <- toList comps] - -- Build required dependencies and setup local packages. + -- Build required dependencies and setup project packages. buildDepsAndInitialSteps opts $ concatMap (\(pn, (_, t)) -> pkgTargets pn t) localTargets targetWarnings localTargets nonLocalTargets mfileTargets @@ -431,8 +429,7 @@ -- Figure out let extraLoadDeps = getExtraLoadDeps ghciOpts.loadLocalDeps localMap directlyWanted - if (ghciOpts.skipIntermediate && not ghciOpts.loadLocalDeps) - || null extraLoadDeps + if null extraLoadDeps then pure directlyWanted else do let extraList' = @@ -454,12 +451,6 @@ \your targets:" : extraList ) - <> line - <> fillSep - [ "(Use" - , style Shell "--skip-intermediate-deps" - , flow "to omit these.)" - ] pure (directlyWanted ++ extraLoadDeps) getAllNonLocalTargets :: @@ -473,11 +464,11 @@ buildDepsAndInitialSteps :: HasEnvConfig env => GhciOpts -> [Text] -> RIO env () buildDepsAndInitialSteps ghciOpts localTargets = do let targets = localTargets ++ map T.pack ghciOpts.additionalPackages - -- If necessary, do the build, for local packagee targets, only do + -- If necessary, do the build, for project packagee targets, only do -- 'initialBuildSteps'. - case nonEmpty targets of - -- only new local targets could appear here - Just nonEmptyTargets | not ghciOpts.noBuild -> do + whenJust (nonEmpty targets) $ \nonEmptyTargets -> + unless ghciOpts.noBuild $ do + -- only new project package targets could appear here eres <- buildLocalTargets nonEmptyTargets case eres of Right () -> pure () @@ -486,8 +477,6 @@ Just (PrettyException prettyErr) -> prettyError $ pretty prettyErr Nothing -> prettyError $ fromString (displayException err) prettyWarn "Build failed, but trying to launch GHCi anyway" - _ -> - pure () checkAdditionalPackages :: MonadThrow m => [String] -> m [PackageName] checkAdditionalPackages pkgs = forM pkgs $ \name -> do @@ -861,8 +850,7 @@ config = PackageConfig { enableTests = True , enableBenchmarks = True - , flags = - getLocalFlags buildOptsCLI name `M.union` sourceMapFlags + , flags = getCliFlags <> sourceMapFlags , ghcOptions = sourceMapGhcOptions , cabalConfigOpts = sourceMapCabalConfigOpts , compilerVersion = compilerVersion @@ -893,6 +881,14 @@ , cabalFP , target } + where + cliFlags = buildOptsCLI.flags + -- | All CLI Cabal flags for a package. + getCliFlags :: Map FlagName Bool + getCliFlags = Map.unions + [ Map.findWithDefault Map.empty (ACFByName name) cliFlags + , Map.findWithDefault Map.empty ACFAllProjectPackages cliFlags + ] getGhciPkgInfos :: HasEnvConfig env @@ -955,21 +951,27 @@ -- (differently). wantedPackageComponents :: BuildOpts -> Target -> Package -> Set NamedComponent wantedPackageComponents _ (TargetComps cs) _ = cs -wantedPackageComponents bopts (TargetAll PTProject) pkg = S.fromList $ +wantedPackageComponents bopts (TargetAll PTProject) pkg = ( if hasBuildableMainLibrary pkg - then CLib : map CSubLib buildableForeignLibs' - else [] + then S.insert CLib (S.mapMonotonic CSubLib buildableForeignLibs') + else S.empty ) - <> map CExe buildableExes' - <> map CSubLib buildableSubLibs - <> (if bopts.tests then map CTest buildableTestSuites else []) - <> (if bopts.benchmarks then map CBench buildableBenchmarks else []) + <> S.mapMonotonic CExe buildableExes' + <> S.mapMonotonic CSubLib buildableSubLibs' + <> ( if bopts.tests + then S.mapMonotonic CTest buildableTestSuites' + else S.empty + ) + <> ( if bopts.benchmarks + then S.mapMonotonic CBench buildableBenchmarks' + else S.empty + ) where - buildableForeignLibs' = S.toList $ buildableForeignLibs pkg - buildableSubLibs = getBuildableListText pkg.subLibraries - buildableExes' = S.toList $ buildableExes pkg - buildableTestSuites = getBuildableListText pkg.testSuites - buildableBenchmarks = getBuildableListText pkg.benchmarks + buildableForeignLibs' = buildableForeignLibs pkg + buildableSubLibs' = buildableSubLibs pkg + buildableExes' = buildableExes pkg + buildableTestSuites' = buildableTestSuites pkg + buildableBenchmarks' = buildableBenchmarks pkg wantedPackageComponents _ _ _ = S.empty checkForIssues :: HasTerm env => [GhciPkgInfo] -> RIO env () @@ -1136,44 +1138,49 @@ , parens $ fillSep $ punctuate "," $ map (style Good . fromPackageName) nonLocalTargets - , flow "are not local packages, and so cannot be directly loaded. In \ + , flow "are not project packages, and so cannot be directly loaded. In \ \future versions of Stack, this might be supported - see" - , style Url "https://github.com/commercialhaskell/stack/issues/1441" - , "." + , style Url "https://github.com/commercialhaskell/stack/issues/1441" <> "." , flow "It can still be useful to specify these, as they will be passed \ - \to ghci via -package flags." + \to ghci via" + , style Shell "-package" + , "flags." ] when (null localTargets && isNothing mfileTargets) $ do smWanted <- view $ buildConfigL . to (.smWanted) - stackYaml <- view stackYamlL - prettyNote $ vsep - [ flow "No local targets specified, so a plain ghci will be started with \ - \no package hiding or package options." - , "" - , flow $ T.unpack $ utf8BuilderToText $ - "You are using snapshot: " <> - display smWanted.snapshotLocation - , "" - , flow "If you want to use package hiding and options, then you can try \ - \one of the following:" - , "" - , bulletedList - [ fillSep - [ flow "If you want to start a different project configuration \ - \than" - , pretty stackYaml <> "," - , flow "then you can use" - , style Shell "stack init" - , flow "to create a new stack.yaml for the packages in the \ - \current directory." - , line - ] - , flow "If you want to use the project configuration at" - , pretty stackYaml <> "," - , flow "then you can add to its 'packages' field." - ] - , "" - ] + configFile <- view configFileL + case configFile of + -- A user-specific global configuration file + Left _ -> prettyThrowM ConfigFileNotProjectLevelBug + -- A project-level configuration file + Right projectConfigFile -> prettyNote $ vsep + [ flow "No project package targets specified, so a plain ghci will be \ + \started with no package hiding or package options." + , "" + , flow $ T.unpack $ utf8BuilderToText $ + "You are using snapshot: " <> + display smWanted.snapshotLocation + , "" + , flow "If you want to use package hiding and options, then you can try \ + \one of the following:" + , "" + , bulletedList + [ fillSep + [ flow "If you want to start a different project configuration \ + \than" + , pretty projectConfigFile <> "," + , flow "then you can use" + , style Shell "stack init" + , flow "to create a new stack.yaml for the packages in the \ + \current directory." + , line + ] + , flow "If you want to use the project configuration at" + , pretty projectConfigFile <> "," + , flow "then you can add to its 'packages' field." + ] + , "" + ] -- Adds in intermediate dependencies between ghci targets. Note that it will -- return a Lib component for these intermediate dependencies even if they don't
src/Stack/Hoogle.hs view
@@ -104,26 +104,24 @@ generateDbIfNeeded :: Path Abs File -> RIO EnvConfig () generateDbIfNeeded hooglePath = do databaseExists <- checkDatabaseExists - if databaseExists && not rebuild - then pure () - else - if setup || rebuild - then do - prettyWarn $ - if rebuild - then flow "Rebuilding database ..." - else - fillSep - [ flow "No Hoogle database yet. Automatically building \ - \Haddock documentation and Hoogle database (use" - , style Shell "--no-setup" - , flow "to disable) ..." - ] - buildHaddocks - prettyInfoS "Built Haddock documentation." - generateDb hooglePath - prettyInfoS "Generated Hoogle database." - else prettyThrowIO HoogleDatabaseNotFound + unless (databaseExists && not rebuild) $ + if setup || rebuild + then do + prettyWarnL $ + if rebuild + then + [ flow "Rebuilding database ..." ] + else + [ flow "No Hoogle database yet. Automatically building \ + \Haddock documentation and Hoogle database (use" + , style Shell "--no-setup" + , flow "to disable) ..." + ] + buildHaddocks + prettyInfoS "Built Haddock documentation." + generateDb hooglePath + prettyInfoS "Generated Hoogle database." + else prettyThrowIO HoogleDatabaseNotFound generateDb :: Path Abs File -> RIO EnvConfig () generateDb hooglePath = do
src/Stack/Init.hs view
@@ -43,19 +43,19 @@ ( BuildPlanCheck (..), DepError (..), checkSnapBuildPlan , removeSrcPkgDefaultFlags, selectBestSnapshot ) -import Stack.Config ( getSnapshots, makeConcreteResolver ) +import Stack.Config ( getSnapshots, makeConcreteSnapshot ) import Stack.Constants ( stackDotYaml, stackProgName' ) import Stack.Prelude import Stack.Runners ( ShouldReexec (..), withConfig, withGlobalProject ) import Stack.SourceMap ( SnapshotCandidate, loadProjectSnapshotCandidate ) -import Stack.Types.Config ( HasConfig ) +import Stack.Types.Config ( HasConfig, Config (..), configL ) import Stack.Types.GHCVariant ( HasGHCVariant ) import Stack.Types.GlobalOpts ( GlobalOpts (..) ) import Stack.Types.Project ( Project (..) ) import Stack.Types.Runner (Runner, globalOptsL ) -import Stack.Types.Resolver ( AbstractResolver, Snapshots (..) ) +import Stack.Types.Snapshot ( AbstractSnapshot, Snapshots (..) ) import Stack.Types.Version ( stackMajorVersion ) -- | Type representing exceptions thrown by functions exported by the @@ -75,8 +75,8 @@ | ConfigFileAlreadyExists FilePath | PackageNameInvalid [(Path Abs File, PackageName)] | NoMatchingSnapshot !(NonEmpty SnapName) - | ResolverMismatch !RawSnapshotLocation String - | ResolverPartial !RawSnapshotLocation !String + | SnapshotMismatch !RawSnapshotLocation String + | SnapshotPartial !RawSnapshotLocation !String deriving (Show, Typeable) instance Pretty InitPrettyException where @@ -143,12 +143,12 @@ <> bulletedList (map (fromString . show) (NE.toList names)) <> blankLine <> resolveOptions - pretty (ResolverMismatch resolver errDesc) = + pretty (SnapshotMismatch snapshot errDesc) = "[S-6395]" <> line <> fillSep [ "Snapshot" - , style Url (pretty $ PrettyRawSnapshotLocation resolver) + , style Url (pretty $ PrettyRawSnapshotLocation snapshot) , flow "does not have a matching compiler to build some or all of \ \your package(s)." ] @@ -156,12 +156,12 @@ <> indent 4 (string errDesc) <> line <> resolveOptions - pretty (ResolverPartial resolver errDesc) = + pretty (SnapshotPartial snapshot errDesc) = "[S-2422]" <> line <> fillSep [ "Snapshot" - , style Url (pretty $ PrettyRawSnapshotLocation resolver) + , style Url (pretty $ PrettyRawSnapshotLocation snapshot) , flow "does not have all the packages to match your requirements." ] <> blankLine @@ -206,16 +206,16 @@ pwd <- getCurrentDir go <- view globalOptsL withGlobalProject $ - withConfig YesReexec (initProject pwd initOpts go.resolver) + withConfig YesReexec (initProject pwd initOpts go.snapshot) -- | Generate a @stack.yaml@ file. initProject :: (HasConfig env, HasGHCVariant env) => Path Abs Dir -> InitOpts - -> Maybe AbstractResolver + -> Maybe AbstractSnapshot -> RIO env () -initProject currDir initOpts mresolver = do +initProject currDir initOpts mASnapshot = do let dest = currDir </> stackDotYaml reldest <- toFilePath <$> makeRelativeToCurrentDir dest exists <- doesFileExist dest @@ -244,8 +244,10 @@ let absDir = parent fp in ResolvedPath (RelFilePath $ T.pack $ makeRelDir absDir) absDir pkgDirs = Map.map (fpToPkgDir . fst) bundle - (snapshotLoc, flags, extraDeps, rbundle) <- - getDefaultResolver initOpts mresolver pkgDirs + defaultInitSnapshot <- view $ configL . to (.defaultInitSnapshot) + let mASnapshot' = getFirst $ First mASnapshot <> defaultInitSnapshot + (snapshot, flags, extraDeps, rbundle) <- + getDefaultSnapshot initOpts mASnapshot' pkgDirs let ignored = Map.difference bundle rbundle dupPkgMsg | dupPkgs /= [] = @@ -256,12 +258,12 @@ missingPkgMsg | Map.size ignored > 0 = "Warning (added by new or init): Some packages were found to be \ - \incompatible with the resolver and have been left commented out \ + \incompatible with the snapshot and have been left commented out \ \in the packages section.\n" | otherwise = "" extraDepMsg | Map.size extraDeps > 0 = - "Warning (added by new or init): Specified resolver could not \ + "Warning (added by new or init): Specified snapshot could not \ \satisfy all dependencies. Some external packages have been added \ \as dependencies.\n" | otherwise = "" @@ -286,7 +288,7 @@ , packages = resolvedRelative <$> Map.elems rbundle , extraDeps = map toRawPL deps , flagsByPkg = removeSrcPkgDefaultFlags gpds flags - , resolver = snapshotLoc + , snapshot , compiler = Nothing , extraPackageDBs = [] , curator = Nothing @@ -296,7 +298,7 @@ prettyInfoL [ flow "Initialising Stack's project-level YAML configuration file \ \using snapshot" - , pretty (PrettyRawSnapshotLocation snapshotLoc) <> "." + , pretty (PrettyRawSnapshotLocation snapshot) <> "." ] prettyInfoL $ let n = Map.size bundle + length dupPkgs @@ -405,10 +407,10 @@ -- Per Section Help comments = [ ("user-message" , userMsgHelp) - , ("resolver" , resolverHelp) + , ("snapshot" , snapshotHelp) , ("packages" , packageHelp) , ("extra-deps" , extraDepsHelp) - , ("flags" , "# Override default flag values for local packages and extra-deps") + , ("flags" , "# Override default flag values for project packages and extra-deps") , ("extra-package-dbs", "# Extra package databases containing global packages") ] -- Help strings @@ -419,20 +421,20 @@ , "For advanced use and comprehensive documentation of the format, please see:" , "https://docs.haskellstack.org/en/stable/yaml_configuration/" ] - resolverHelp = commentHelp - [ "Resolver to choose a 'specific' stackage snapshot or a compiler version." + snapshotHelp = commentHelp + [ "A 'specific' Stackage snapshot or a compiler version." , "A snapshot resolver dictates the compiler version and the set of packages" , "to be used for project dependencies. For example:" , "" - , "resolver: lts-22.21" - , "resolver: nightly-2024-05-06" - , "resolver: ghc-9.6.5" + , "snapshot: lts-22.28" + , "snapshot: nightly-2024-07-05" + , "snapshot: ghc-9.6.6" , "" , "The location of a snapshot can be provided as a file or url. Stack assumes" , "a snapshot provided as a file might change, whereas a url resource does not." , "" - , "resolver: ./custom-snapshot.yaml" - , "resolver: https://example.com/snapshots/2023-01-01.yaml" + , "snapshot: ./custom-snapshot.yaml" + , "snapshot: https://example.com/snapshots/2024-01-01.yaml" ] userMsgHelp = commentHelp [ "A warning or info to be displayed to the user on config load." ] @@ -448,7 +450,7 @@ , " - wai" ] extraDepsHelp = commentHelp - [ "Dependency packages to be pulled from upstream that are not in the resolver." + [ "Dependency packages to be pulled from upstream that are not in the snapshot." , "These entries can reference officially published versions as well as" , "forks / in-progress versions pinned to a git hash. For example:" , "" @@ -484,11 +486,11 @@ getSnapshots (prettyThrowIO . SnapshotDownloadFailure) --- | Get the default resolver value -getDefaultResolver :: +-- | Get the default snapshot value +getDefaultSnapshot :: (HasConfig env, HasGHCVariant env) => InitOpts - -> Maybe AbstractResolver + -> Maybe AbstractSnapshot -> Map PackageName (ResolvedPath Dir) -- ^ Src package name: cabal dir -> RIO env @@ -496,21 +498,21 @@ , Map PackageName (Map FlagName Bool) , Map PackageName Version , Map PackageName (ResolvedPath Dir)) - -- ^ ( Resolver + -- ^ ( Snapshot -- , Flags for src packages and extra deps -- , Extra dependencies -- , Src packages actually considered) -getDefaultResolver initOpts mresolver pkgDirs = do - (candidate, loc) <- case mresolver of - Nothing -> selectSnapResolver - Just ar -> do - sl <- makeConcreteResolver ar +getDefaultSnapshot initOpts mASnapshot pkgDirs = do + (candidate, loc) <- case mASnapshot of + Nothing -> selectSnapshot + Just as -> do + sl <- makeConcreteSnapshot as c <- loadProjectSnapshotCandidate sl NoPrintWarnings False pure (c, sl) - getWorkingResolverPlan initOpts pkgDirs candidate loc + getWorkingSnapshotPlan initOpts pkgDirs candidate loc where -- TODO support selecting best across regular and custom snapshots - selectSnapResolver = do + selectSnapshot = do snaps <- fmap getRecommendedSnapshots getSnapshots' (c, l, r) <- selectBestSnapshot (Map.elems pkgDirs) snaps case r of @@ -518,7 +520,7 @@ -> prettyThrowM $ NoMatchingSnapshot snaps _ -> pure (c, l) -getWorkingResolverPlan :: +getWorkingSnapshotPlan :: (HasConfig env, HasGHCVariant env) => InitOpts -> Map PackageName (ResolvedPath Dir) @@ -534,7 +536,7 @@ -- , Flags for src packages and extra deps -- , Extra dependencies -- , Src packages actually considered) -getWorkingResolverPlan initOpts pkgDirs0 snapCandidate snapLoc = do +getWorkingSnapshotPlan initOpts pkgDirs0 snapCandidate snapLoc = do prettyInfoL [ flow "Selected the snapshot" , pretty (PrettyRawSnapshotLocation snapLoc) <> "." @@ -542,7 +544,7 @@ go pkgDirs0 where go pkgDirs = do - eres <- checkBundleResolver initOpts snapLoc snapCandidate (Map.elems pkgDirs) + eres <- checkBundleSnapshot initOpts snapLoc snapCandidate (Map.elems pkgDirs) -- if some packages failed try again using the rest case eres of Right (f, edeps)-> pure (snapLoc, f, edeps, pkgDirs) @@ -576,7 +578,7 @@ isAvailable k _ = k `notElem` ignored available = Map.filterWithKey isAvailable pkgDirs -checkBundleResolver :: +checkBundleSnapshot :: (HasConfig env, HasGHCVariant env) => InitOpts -> RawSnapshotLocation @@ -586,7 +588,7 @@ -> RIO env (Either [PackageName] ( Map PackageName (Map FlagName Bool) , Map PackageName Version)) -checkBundleResolver initOpts snapshotLoc snapCandidate pkgDirs = do +checkBundleSnapshot initOpts snapshotLoc snapCandidate pkgDirs = do result <- checkSnapBuildPlan pkgDirs Nothing snapCandidate case result of BuildPlanCheckOk f -> pure $ Right (f, Map.empty) @@ -597,23 +599,23 @@ prettyWarnS "Omitting packages with unsatisfied dependencies" pure $ Left $ failedUserPkgs e else - prettyThrowM $ ResolverPartial snapshotLoc (show result) + prettyThrowM $ SnapshotPartial snapshotLoc (show result) BuildPlanCheckFail _ e _ | initOpts.omitPackages -> do prettyWarn $ fillSep - [ "Resolver compiler mismatch:" + [ "Snapshot compiler mismatch:" , style Current (fromString . T.unpack $ textDisplay snapshotLoc) ] <> line <> indent 4 (string $ show result) pure $ Left $ failedUserPkgs e - | otherwise -> prettyThrowM $ ResolverMismatch snapshotLoc (show result) + | otherwise -> prettyThrowM $ SnapshotMismatch snapshotLoc (show result) where warnPartial res = do prettyWarn $ fillSep - [ "Resolver" + [ "Snapshot" , style Current (fromString . T.unpack $ textDisplay snapshotLoc) , flow "will need external packages:" ] @@ -636,8 +638,8 @@ -- |Yields the minimum LTS supported by Stack. minSupportedLts :: SnapName -- See https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md --- under Stack version 2.1.1. -minSupportedLts = LTS 3 0 +-- under Stack version 3.1.1. +minSupportedLts = LTS 12 0 findCabalDirs :: HasConfig env @@ -669,8 +671,8 @@ when (null cabaldirs) $ prettyWarn $ fillSep - [ flow "Stack did not find any local package directories. You may \ - \want to create a package with" + [ flow "Stack did not find any local directories containing a \ + \package description. You may want to create a package with" , style Shell (flow "stack new") , flow "instead." ]
src/Stack/List.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE NoImplicitPrelude #-} -{-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE OverloadedStrings #-} -- | Types and functions related to Stack's @list@ command. @@ -8,15 +7,14 @@ , listPackages ) where -import Pantry ( loadSnapshot ) import qualified RIO.ByteString.Lazy as Lazy import qualified RIO.Map as Map import RIO.Process ( HasProcessContext ) -import Stack.Config ( makeConcreteResolver ) +import Stack.Config ( getRawSnapshot ) import Stack.Prelude import Stack.Runners ( ShouldReexec (..), withConfig ) -import Stack.Types.GlobalOpts ( GlobalOpts (..) ) -import Stack.Types.Runner ( Runner, globalOptsL ) +import Stack.SourceMap ( globalsFromHints ) +import Stack.Types.Runner ( Runner ) -- | Type representing exceptions thrown by functions exported by the -- "Stack.List" module. @@ -35,22 +33,22 @@ -- | Function underlying the @stack list@ command. List packages. listCmd :: [String] -> RIO Runner () listCmd names = withConfig NoReexec $ do - mresolver <- view $ globalOptsL . to (.resolver) - mSnapshot <- forM mresolver $ \resolver -> do - concrete <- makeConcreteResolver resolver - loc <- completeSnapshotLocation concrete - loadSnapshot loc - listPackages mSnapshot names + mSnapshot <- getRawSnapshot + let mWc = rsCompiler <$> mSnapshot + mGlobals <- mapM globalsFromHints mWc + listPackages mSnapshot mGlobals names -- | Intended to work for the command line command. listPackages :: forall env. (HasPantryConfig env, HasProcessContext env, HasTerm env) => Maybe RawSnapshot -- ^ When looking up by name, take from this build plan. + -> Maybe (Map PackageName Version) + -- ^ Global hints for snapshot wanted compiler. -> [String] -- ^ Names or identifiers. -> RIO env () -listPackages mSnapshot input = do +listPackages mSnapshot mGlobals input = do let (errs1, names) = case mSnapshot of Just snapshot | null input -> ([], Map.keys (rsPackages snapshot)) _ -> partitionEithers $ map parse input @@ -105,11 +103,15 @@ -> RIO env (Either StyleDoc PackageIdentifier) toLocSnapshot snapshot name = case Map.lookup name (rsPackages snapshot) of - Nothing -> - pure $ Left $ fillSep - [ flow "Package does not appear in snapshot:" - , style Current (fromPackageName name) <> "." - ] + Nothing -> case Map.lookup name =<< mGlobals of + Nothing -> + pure $ Left $ fillSep + [ flow "Package does not appear in snapshot (directly or \ + \indirectly):" + , style Current (fromPackageName name) <> "." + ] + Just version -> + pure $ Right $ PackageIdentifier name version Just sp -> do loc <- cplComplete <$> completePackageLocation (rspLocation sp) pure $ Right (packageLocationIdent loc)
src/Stack/Lock.hs view
@@ -132,7 +132,7 @@ -> RIO env ( SMWanted, [CompletedPLI]) ) -> RIO env SMWanted -lockCachedWanted stackFile resolver fillWanted = do +lockCachedWanted stackFile snapshot fillWanted = do lockFile <- liftIO $ addExtension ".lock" stackFile let getLockExists = doesFileExist lockFile lfb <- view lockFileBehaviorL @@ -157,7 +157,7 @@ pkgLocCache = toMap locked.pkgImmutableLocations debugRSL <- view rslInLogL (snap, slocCompleted, pliCompleted) <- - loadAndCompleteSnapshotRaw' debugRSL resolver slocCache pkgLocCache + loadAndCompleteSnapshotRaw' debugRSL snapshot slocCache pkgLocCache let compiler = snapshotCompiler snap snPkgs = Map.mapWithKey (\n p h -> snapToDepPackage h n p)
src/Stack/Ls.hs view
@@ -13,11 +13,13 @@ , ListDepsFormat (..) , ListDepsFormatOpts (..) , ListDepsTextFilter (..) + , ListGlobalsOpts (..) , ListStylesOpts (..) , ListToolsOpts (..) , lsCmd ) where +import Control.Monad.Extra ( whenJust ) import Data.Aeson ( FromJSON, Value (..), (.:), encode ) import Data.Array.IArray ( (//), elems ) import qualified Data.ByteString.Lazy.Char8 as LBC8 @@ -38,6 +40,8 @@ ) import Path ( parent ) import RIO.List ( sort ) +import Stack.Build.Installed ( getInstalled, toInstallMap ) +import Stack.Config ( withBuildConfig ) import Stack.Constants ( osIsWindows ) import Stack.DependencyGraph ( createPrunedDependencyGraph ) import Stack.Prelude hiding ( Nightly, Snapshot ) @@ -45,14 +49,19 @@ ( ShouldReexec (..), withConfig, withDefaultEnvConfig ) import Stack.Setup.Installed ( Tool (..), filterTools, listInstalled, toolString ) +import Stack.SourceMap ( globalsFromHints ) +import Stack.Types.BuildConfig + ( BuildConfig (..), HasBuildConfig (..) ) import Stack.Types.Config ( Config (..), HasConfig (..) ) import Stack.Types.DependencyTree ( DependencyTree (..), DotPayload (..), licenseText , versionText ) import Stack.Types.DotOpts ( DotOpts (..) ) -import Stack.Types.EnvConfig ( installationRootDeps ) +import Stack.Types.DumpPackage ( DumpPackage (..) ) +import Stack.Types.EnvConfig ( EnvConfig (..), installationRootDeps ) import Stack.Types.Runner ( HasRunner, Runner, terminalL ) +import Stack.Types.SourceMap ( SMWanted (..) ) import System.Console.ANSI.Codes ( SGR (Reset), setSGRCode, sgrToCode ) import System.Process.Pager ( pageText ) @@ -78,6 +87,7 @@ -- | Type representing subcommands for the @stack ls@ command. data LsCmds = LsSnapshot SnapshotOpts + | LsGlobals ListGlobalsOpts | LsDependencies ListDepsOpts | LsStyles ListStylesOpts | LsTools ListToolsOpts @@ -105,6 +115,11 @@ -- ^ Stackage Nightly deriving (Eq, Ord, Show) +newtype ListGlobalsOpts = ListGlobalsOpts + { globalHints :: Bool + -- ^ Use global hints instead of relying on an actual GHC installation. + } + data ListDepsOpts = ListDepsOpts { format :: !ListDepsFormat -- ^ Format of printing dependencies @@ -130,7 +145,7 @@ = FilterPackage PackageName -- ^ Item is a package name. | FilterLocals - -- ^ Item represents all local packages. + -- ^ Item represents all project packages. -- | Type representing command line options for the @stack ls stack-colors@ and -- @stack ls stack-colours@ commands. @@ -184,7 +199,7 @@ displaySnap :: Snapshot -> [Text] displaySnap snap = - ["Resolver name: " <> snap.snapId, "\n" <> snap.title <> "\n\n"] + ["Snapshot name: " <> snap.snapId, "\n" <> snap.title <> "\n\n"] displaySingleSnap :: [Snapshot] -> Text displaySingleSnap snapshots = @@ -248,6 +263,7 @@ displayLocalSnapshot isStdoutTerminal $ L.filter (L.isPrefixOf "night") snapData _ -> liftIO $ displayLocalSnapshot isStdoutTerminal snapData + LsGlobals _ -> pure () LsDependencies _ -> pure () LsStyles _ -> pure () LsTools _ -> pure () @@ -271,6 +287,7 @@ displaySnapshotData isStdoutTerminal $ filterSnapshotData snapData Nightly _ -> liftIO $ displaySnapshotData isStdoutTerminal snapData + LsGlobals _ -> pure () LsDependencies _ -> pure () LsStyles _ -> pure () LsTools _ -> pure () @@ -284,6 +301,7 @@ case sopt.viewType of Local -> handleLocal lsOpts Remote -> handleRemote lsOpts + LsGlobals globalsOpts -> withConfig NoReexec $ listGlobalsCmd globalsOpts LsDependencies depOpts -> listDependencies depOpts LsStyles stylesOpts -> withConfig NoReexec $ listStylesCmd stylesOpts LsTools toolsOpts -> withConfig NoReexec $ listToolsCmd toolsOpts @@ -329,6 +347,23 @@ filtered pkgName installed = Tool <$> filterTools (mkPackageName pkgName) (const True) installed +listGlobalsCmd :: ListGlobalsOpts -> RIO Config () +listGlobalsCmd opts = do + idents <- if opts.globalHints + then + withBuildConfig $ do + buildConfig <- view buildConfigL + globals <- globalsFromHints buildConfig.smWanted.compiler + pure $ map (uncurry PackageIdentifier) (Map.toList globals) + else + withDefaultEnvConfig $ do + envConfig <- ask + installMap <- toInstallMap envConfig.sourceMap + (_, globalDump, _, _) <- getInstalled installMap + pure $ L.sort $ map (.packageIdent) globalDump + forM_ idents $ \ident -> + prettyInfo $ fromString $ packageIdentifierString ident + listDependencies :: ListDepsOpts -> RIO Runner () listDependencies opts = do let dotOpts = opts.dotOpts @@ -382,15 +417,17 @@ toSeq = Seq.fromList . Set.toList go index name = let newDepsCounts = remainingDepsCounts ++ [Set.size packages - index - 1] - in case Map.lookup name dependencyMap of - Just (deps, payload) -> do - printTreeNode opts dotOpts depth newDepsCounts deps payload name - if Just depth == dotOpts.dependencyDepth - then pure () - else printTree opts dotOpts (depth + 1) newDepsCounts deps - dependencyMap - -- TODO: Define this behaviour, maybe pure an error? - Nothing -> pure () + -- TODO: Define the 'Nothing' behaviour, maybe pure an error? + in whenJust (Map.lookup name dependencyMap) $ \(deps, payload) -> do + printTreeNode opts dotOpts depth newDepsCounts deps payload name + unless (Just depth == dotOpts.dependencyDepth) $ + printTree + opts + dotOpts + (depth + 1) + newDepsCounts + deps + dependencyMap printTreeNode :: ListDepsFormatOpts
src/Stack/New.hs view
@@ -11,6 +11,7 @@ , new ) where +import Control.Monad.Extra ( whenJust ) import Control.Monad.Trans.Writer.Strict ( execWriterT ) import Data.Aeson as A import qualified Data.Aeson.KeyMap as KeyMap @@ -236,7 +237,7 @@ exists <- doesFileExist $ dir </> stackDotYaml when (newOpts.init && (initOpts.forceOverwrite || not exists)) $ do go <- view globalOptsL - initProject dir initOpts go.resolver + initProject dir initOpts go.snapshot -- | Create a new project with the given options. new :: HasConfig env => NewOpts -> Bool -> RIO env (Path Abs Dir) @@ -570,7 +571,7 @@ prettyNote $ missingParameters missingKeys - config.userConfigPath + config.userGlobalConfigFile pure $ M.fromList results where onlyMissingKeys (Mustache.VariableNotFound ks) = map T.unpack ks @@ -660,17 +661,15 @@ runTemplateInits :: HasConfig env => Path Abs Dir -> RIO env () runTemplateInits dir = do config <- view configL - case config.scmInit of - Nothing -> pure () - Just Git -> withWorkingDir (toFilePath dir) $ + whenJust config.scmInit $ \Git -> + withWorkingDir (toFilePath dir) $ catchAny (proc "git" ["init"] runProcess_) - ( \_ -> prettyWarn $ - fillSep - [ flow "Stack failed to run a" - , style Shell (flow "git init") - , flow "command. Ignoring..." - ] + ( \_ -> prettyWarnL + [ flow "Stack failed to run a" + , style Shell (flow "git init") + , flow "command. Ignoring..." + ] ) --------------------------------------------------------------------------------
src/Stack/Options/BuildMonoidParser.hs view
@@ -7,7 +7,6 @@ , cabalVerbosityParser ) where -import qualified Data.Text as T import Distribution.Parsec ( eitherParsec ) import Options.Applicative ( Parser, eitherReader, flag, help, long, metavar, option @@ -27,6 +26,7 @@ ( BuildOptsMonoid (..), CabalVerbosity, readProgressBarFormat , toFirstCabalVerbosity ) +import Stack.Types.ComponentUtils ( unqualCompFromString ) buildOptsMonoidParser :: GlobalOptsContext -> Parser BuildOptsMonoid buildOptsMonoidParser hide0 = BuildOptsMonoid @@ -41,6 +41,9 @@ <*> haddockOptsParser hideBool <*> openHaddocks <*> haddockDeps + <*> haddockExecutables + <*> haddockTests + <*> haddockBenchmarks <*> haddockInternal <*> haddockHyperlinkSource <*> haddockForHackage @@ -133,6 +136,21 @@ "building Haddock documentation for dependencies. (default: if building \ \Haddock documentation, true; otherwise, false)" hide + haddockExecutables = firstBoolFlagsFalse + "haddock-executables" + "also building Haddock documentation for all executables (like \ + \'cabal haddock --executables')." + hide + haddockTests = firstBoolFlagsFalse + "haddock-tests" + "also building Haddock documentation for all test suites (like \ + \'cabal haddock --tests')." + hide + haddockBenchmarks = firstBoolFlagsFalse + "haddock-benchmarks" + "also building Haddock documentation for all benchmarks (like \ + \'cabal haddock --benchmarks')." + hide haddockInternal = firstBoolFlagsFalse "haddock-internal" "building Haddock documentation for internal modules (like \ @@ -172,8 +190,9 @@ hide forceDirty = firstBoolFlagsFalse "force-dirty" - "forcing the treatment of all local packages as having dirty files. \ - \Useful for cases where Stack can't detect a file change." + "forcing the treatment of all project packages and local extra-deps as \ + \having dirty files. Useful for cases where Stack can't detect a file \ + \change." hide tests = firstBoolFlagsFalse "test" @@ -195,7 +214,7 @@ ++ splitObjsWarning ) hide - skipComponents = many (fmap T.pack (strOption + skipComponents = many (fmap unqualCompFromString (strOption ( long "skip" <> help "Skip given component (can be specified multiple times)." <> hide
src/Stack/Options/BuildParser.hs view
@@ -15,10 +15,12 @@ , metavar, option, strOption, switch, value ) import Options.Applicative.Args ( cmdOption ) -import Options.Applicative.Builder.Extra ( textArgument, textOption ) +import Options.Applicative.Builder.Extra + ( firstBoolFlagsNoDefault, textArgument, textOption ) import Stack.Options.Completion ( flagCompleter, ghcOptsCompleter, targetCompleter ) import Stack.Options.PackageParser ( readFlag ) +import Stack.Options.Utils ( hideMods ) import Stack.Prelude import Stack.Types.BuildOptsCLI ( ApplyCLIFlag, BuildCommand, BuildOptsCLI (..) @@ -61,6 +63,10 @@ ) <*> progsOptionsParser <*> flagsParser + <*> firstBoolFlagsNoDefault + "allow-newer" + "ignoring of lower and upper version bounds in Cabal files." + (hideMods False) <*> ( flag' BSOnlyDependencies ( long "dependencies-only" <> help "A synonym for --only-dependencies." @@ -121,7 +127,8 @@ many (textArgument ( metavar "TARGET" <> completer targetCompleter - <> help "If none specified, use all local packages. See \ + <> help "Can be specified multiple times. If none specified, use all \ + \project packages. See \ \https://docs.haskellstack.org/en/stable/build_command/#target-syntax \ \for details." )) @@ -132,8 +139,12 @@ ( long "flag" <> completer flagCompleter <> metavar "PACKAGE:[-]FLAG" - <> help "Override flags set in stack.yaml (applies to local packages \ - \and extra-deps)." + <> help "Set (or unset) the Cabal flag for the package (or use '*' for \ + \all packages) (can be specified multiple times). Applies to \ + \project packages, packages included directly in the snapshot, \ + \and extra-deps. Takes precedence over any Cabal flags \ + \specified for the package in the snapshot or in the \ + \project-level configuration file (stack.yaml)." )) progsOptionsParser :: Parser [(Text, [Text])]
src/Stack/Options/ConfigParser.hs view
@@ -35,7 +35,7 @@ configOptsParser currentDir hide0 = ( \stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch ghcVariant ghcBuild jobs extraIncludeDirs extraLibDirs - customPreprocessorExts overrideGccPath overrideHpack skipGHCCheck skipMsys + customPreprocessorExts overrideGccPath overrideHpack hpackForce skipGHCCheck skipMsys localBinPath setupInfoLocations modifyCodePage allowDifferentUser dumpLogs colorWhen snapshotLocation noRunCompile -> mempty { stackRoot @@ -55,6 +55,7 @@ , customPreprocessorExts , overrideGccPath , overrideHpack + , hpackForce , skipMsys , localBinPath , setupInfoLocations @@ -147,6 +148,10 @@ <> hide )) <*> firstBoolFlagsFalse + "hpack-force" + "overwriting of Cabal files that have been modified manually." + hide + <*> firstBoolFlagsFalse "skip-ghc-check" "skipping the GHC version and architecture check." hide @@ -181,7 +186,7 @@ hide <*> fmap toDumpLogs (firstBoolFlagsNoDefault "dump-logs" - "dump the build output logs for local packages to the console. \ + "dump the build output logs for project packages to the console. \ \(default: dump warning logs)" hide) <*> optionalFirst (option readColorWhen
src/Stack/Options/DotParser.hs view
@@ -71,6 +71,6 @@ globalHints = switch ( long "global-hints" - <> help "Do not require an install GHC; instead, use a hints file for \ + <> help "Do not require an installed GHC; instead, use a hints file for \ \global packages." )
src/Stack/Options/GhciParser.hs view
@@ -27,7 +27,7 @@ <$> many (textArgument ( metavar "TARGET/FILE" <> completer (targetCompleter <> fileExtCompleter [".hs", ".lhs"]) - <> help "If none specified, use all local packages. See \ + <> help "If none specified, use all project packages. See \ \https://docs.haskellstack.org/en/stable/build_command/#target-syntax \ \for details. If a path to a .hs or .lhs file is specified, it \ \will be loaded." @@ -79,12 +79,6 @@ <*> switch ( long "load-local-deps" <> help "Load all local dependencies of your targets." - ) - -- TODO: deprecate this? probably useless. - <*> switch - ( long "skip-intermediate-deps" - <> help "Skip loading intermediate target dependencies." - <> internal ) <*> optional (boolFlagsNoDefault "package-hiding"
src/Stack/Options/GlobalParser.hs view
@@ -22,8 +22,8 @@ import Stack.Prelude import Stack.Options.ConfigParser ( configOptsParser ) import Stack.Options.LogLevelParser ( logLevelOptsParser ) -import Stack.Options.ResolverParser - ( abstractResolverOptsParser, compilerOptsParser ) +import Stack.Options.SnapshotParser + ( abstractSnapshotOptsParser, compilerOptsParser ) import Stack.Options.Utils ( GlobalOptsContext (..), hideMods ) import Stack.Types.GlobalOpts ( GlobalOpts (..) ) import Stack.Types.GlobalOptsMonoid ( GlobalOptsMonoid (..) ) @@ -63,10 +63,10 @@ "inclusion of information about build plan construction in logs." hide <*> configOptsParser currentDir kind - <*> optionalFirst (abstractResolverOptsParser hide0) + <*> optionalFirst (abstractSnapshotOptsParser hide0) <*> pure (First Nothing) <*> optionalFirst (compilerOptsParser hide0) - -- resolver root is only set via the script command + -- snapshot root is only set via the script command <*> firstBoolFlagsNoDefault "terminal" "overriding terminal detection in the case of running in a false \ @@ -104,7 +104,7 @@ <*> optionalFirst (option readLockFileBehavior ( long "lock-file" <> help "Specify how to interact with lock files. (default: if \ - \resolver is overridden: read-only; otherwise: read/write)" + \snapshot is overridden: read-only; otherwise: read/write)" <> hide )) where @@ -118,19 +118,19 @@ -> GlobalOptsMonoid -> m GlobalOpts globalOptsFromMonoid defaultTerminal globalMonoid = do - resolver <- for (getFirst globalMonoid.resolver) $ \ur -> do + snapshot <- for (getFirst globalMonoid.snapshot) $ \us -> do root <- - case globalMonoid.resolverRoot of + case globalMonoid.snapshotRoot of First Nothing -> getCurrentDir First (Just dir) -> resolveDir' dir - resolvePaths (Just root) ur + resolvePaths (Just root) us stackYaml <- case getFirst globalMonoid.stackYaml of Nothing -> pure SYLDefault Just fp -> SYLOverride <$> resolveFile' fp let lockFileBehavior = let defLFB = - case getFirst globalMonoid.resolver of + case getFirst globalMonoid.snapshot of Nothing -> LFBReadWrite _ -> LFBReadOnly in fromFirst defLFB globalMonoid.lockFileBehavior @@ -142,7 +142,7 @@ , rslInLog = fromFirstFalse globalMonoid.rslInLog , planInLog = fromFirstFalse globalMonoid.planInLog , configMonoid = globalMonoid.configMonoid - , resolver + , snapshot , compiler = getFirst globalMonoid.compiler , terminal = fromFirst defaultTerminal globalMonoid.terminal , stylesUpdate = globalMonoid.styles
src/Stack/Options/LsParser.hs view
@@ -14,8 +14,9 @@ import Stack.Ls ( ListDepsFormat (..), ListDepsFormatOpts (..) , ListDepsOpts (..), ListDepsTextFilter (..) - , ListStylesOpts (..), ListToolsOpts (..), LsCmdOpts (..) - , LsCmds (..), LsView (..), SnapshotOpts (..) + , ListGlobalsOpts (..), ListStylesOpts (..) + , ListToolsOpts (..), LsCmdOpts (..), LsCmds (..) + , LsView (..), SnapshotOpts (..), ListGlobalsOpts ) import Stack.Options.DotParser ( dotOptsParser ) import Stack.Prelude @@ -23,7 +24,13 @@ -- | Parse command line arguments for Stack's @ls@ command. lsOptsParser :: OA.Parser LsCmdOpts lsOptsParser = LsCmdOpts - <$> OA.hsubparser (lsSnapCmd <> lsDepsCmd <> lsStylesCmd <> lsToolsCmd) + <$> OA.hsubparser + ( lsSnapCmd + <> lsGlobalsCmd + <> lsDepsCmd + <> lsStylesCmd + <> lsToolsCmd + ) lsSnapCmd :: OA.Mod OA.CommandFields LsCmds lsSnapCmd = OA.command "snapshots" $ @@ -31,10 +38,19 @@ OA.progDesc "View snapshots. (default: local)" <> OA.footer localSnapshotMsg +lsGlobalsCmd :: OA.Mod OA.CommandFields LsCmds +lsGlobalsCmd = OA.command "globals" $ + OA.info lsGlobalsOptsParser $ + OA.progDesc "View global packages." + <> OA.footer globalFooter + lsDepsCmd :: OA.Mod OA.CommandFields LsCmds lsDepsCmd = OA.command "dependencies" $ OA.info lsDepOptsParser $ - OA.progDesc "View the dependencies." + OA.progDesc + "View the packages and versions used for a project. Use a command if \ + \the first target specified has the name of a command. Targets other \ + \than project packages are ignored." <> OA.footer globalFooter lsStylesCmd :: OA.Mod OA.CommandFields LsCmds @@ -59,6 +75,9 @@ lsCmdOptsParser :: OA.Parser LsCmds lsCmdOptsParser = LsSnapshot <$> lsViewSnapCmd +lsGlobalsOptsParser :: OA.Parser LsCmds +lsGlobalsOptsParser = LsGlobals <$> listGlobalsOptsParser + lsDepOptsParser :: OA.Parser LsCmds lsDepOptsParser = LsDependencies <$> listDepsOptsParser @@ -103,6 +122,15 @@ localSnapshotMsg = "A local snapshot is identified by a hash code. " <> pagerMsg +-- | Parser for arguments to `stack ls globals`. +listGlobalsOptsParser :: OA.Parser ListGlobalsOpts +listGlobalsOptsParser = ListGlobalsOpts <$> globalHints + where + globalHints = boolFlags True + "global-hints" + "use of a hints file for global packages, rather than an installed GHC" + idm + -- | Parser for arguments to `stack ls dependencies`. listDepsOptsParser :: OA.Parser ListDepsOpts listDepsOptsParser = OA.subparser @@ -144,7 +172,7 @@ ( OA.long "filter" <> OA.metavar "ITEM" <> OA.help "Item to be filtered out of the results, if present, being either \ - \$locals (for all local packages) or a package name (can be \ + \$locals (for all project packages) or a package name (can be \ \specified multiple times)." ))
− src/Stack/Options/ResolverParser.hs
@@ -1,41 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-} -{-# LANGUAGE DataKinds #-} - -module Stack.Options.ResolverParser - ( abstractResolverOptsParser - , compilerOptsParser - , readCompilerVersion - ) where - -import qualified Data.Text as T -import Options.Applicative - ( Parser, ReadM, help, long, metavar, option, readerError ) -import Options.Applicative.Types ( readerAsk ) -import Stack.Options.Utils ( hideMods ) -import Stack.Prelude -import Stack.Types.Resolver ( AbstractResolver, readAbstractResolver ) - --- | Parser for the snapshot -abstractResolverOptsParser :: Bool -> Parser (Unresolved AbstractResolver) -abstractResolverOptsParser hide = option readAbstractResolver - ( long "snapshot" - <> long "resolver" - <> metavar "SNAPSHOT" - <> help "Override snapshot in the project configuration file." - <> hideMods hide - ) - -compilerOptsParser :: Bool -> Parser WantedCompiler -compilerOptsParser hide = option readCompilerVersion - ( long "compiler" - <> metavar "COMPILER" - <> help "Use the specified compiler." - <> hideMods hide - ) - -readCompilerVersion :: ReadM WantedCompiler -readCompilerVersion = do - s <- readerAsk - case parseWantedCompiler (T.pack s) of - Left{} -> readerError $ "Failed to parse compiler: " ++ s - Right x -> pure x
src/Stack/Options/SetupParser.hs view
@@ -19,8 +19,8 @@ setupOptsParser = SetupCmdOpts <$> OA.optional (OA.argument readVersion ( OA.metavar "GHC_VERSION" - <> OA.help "Version of GHC to install, e.g. 9.6.5. (default: install \ - \the version implied by the resolver)" + <> OA.help "Version of GHC to install, e.g. 9.6.6. (default: install \ + \the version implied by the snapshot)" )) <*> OA.boolFlags False "reinstall"
+ src/Stack/Options/SnapshotParser.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE DataKinds #-} + +module Stack.Options.SnapshotParser + ( abstractSnapshotOptsParser + , compilerOptsParser + , readCompilerVersion + ) where + +import qualified Data.Text as T +import Options.Applicative + ( Parser, ReadM, help, long, metavar, option, readerError ) +import Options.Applicative.Types ( readerAsk ) +import Stack.Options.Utils ( hideMods ) +import Stack.Prelude +import Stack.Types.Snapshot ( AbstractSnapshot, readAbstractSnapshot ) + +-- | Parser for the snapshot +abstractSnapshotOptsParser :: Bool -> Parser (Unresolved AbstractSnapshot) +abstractSnapshotOptsParser hide = option readAbstractSnapshot + ( long "snapshot" + <> long "resolver" + <> metavar "SNAPSHOT" + <> help "Override snapshot in the project configuration file." + <> hideMods hide + ) + +compilerOptsParser :: Bool -> Parser WantedCompiler +compilerOptsParser hide = option readCompilerVersion + ( long "compiler" + <> metavar "COMPILER" + <> help "Use the specified compiler." + <> hideMods hide + ) + +readCompilerVersion :: ReadM WantedCompiler +readCompilerVersion = do + s <- readerAsk + case parseWantedCompiler (T.pack s) of + Left{} -> readerError $ "Failed to parse compiler: " ++ s + Right x -> pure x
src/Stack/Options/UploadParser.hs view
@@ -11,7 +11,8 @@ , metavar, option, readerError, short, strArgument, strOption , switch ) -import Options.Applicative.Builder.Extra ( boolFlags, dirCompleter ) +import Options.Applicative.Builder.Extra + ( boolFlags, dirCompleter, firstBoolFlagsTrue ) import Options.Applicative.Types ( readerAsk ) import Stack.Prelude import Stack.Upload ( UploadOpts (..), UploadVariant (..) ) @@ -27,6 +28,7 @@ <*> buildPackageOption <*> tarDirParser <*> uploadVariantParser + <*> saveHackageCredsOption where itemsToWorkWithParser = many (strArgument ( metavar "ITEM" @@ -70,3 +72,7 @@ ( long "candidate" <> help "Upload as, or for, a package candidate." ) + saveHackageCredsOption = firstBoolFlagsTrue + "save-hackage-creds" + "saving user's Hackage username and password in a local file." + idm
src/Stack/Options/Utils.hs view
@@ -14,8 +14,8 @@ -- | Allows adjust global options depending on their context -- Note: This was being used to remove ambiguity between the local and global --- implementation of stack init --resolver option. Now that stack init has no --- local --resolver this is not being used anymore but the code is kept for any +-- implementation of stack init --snapshot option. Now that stack init has no +-- local --snapshot this is not being used anymore but the code is kept for any -- similar future use cases. data GlobalOptsContext = OuterGlobalOpts -- ^ Global options before subcommand name
src/Stack/Package.hs view
@@ -27,7 +27,7 @@ , buildableTestSuites , buildableBenchmarks , getPackageOpts - , processPackageDepsToList + , processPackageDepsEither , listOfPackageDeps , setOfPackageDeps , topSortPackageComponent @@ -35,7 +35,6 @@ import qualified Data.Map.Strict as M import qualified Data.Set as S -import Data.STRef ( STRef, modifySTRef', readSTRef, newSTRef ) import qualified Data.Text as T import Distribution.CabalSpecVersion ( cabalSpecToVersionDigits ) import Distribution.Compiler @@ -50,6 +49,7 @@ , Library (..), PackageDescription (..), PackageFlag (..) , SetupBuildInfo (..), TestSuite (..), allLibraries , buildType, depPkgName, depVerRange + , unqualComponentNameToPackageName ) import qualified Distribution.PackageDescription as Executable ( Executable (..) ) @@ -71,26 +71,26 @@ , isComponentBuildable, stackBenchmarkFromCabal , stackExecutableFromCabal, stackForeignLibraryFromCabal , stackLibraryFromCabal, stackTestFromCabal - , stackUnqualToQual ) import Stack.ComponentFile ( buildDir, componentAutogenDir, componentBuildDir , componentOutputDir, packageAutogenDir ) -import Stack.Constants (relFileCabalMacrosH, relDirLogs) +import Stack.Constants ( relFileCabalMacrosH, relDirLogs ) import Stack.Constants.Config ( distDirFromDir ) import Stack.PackageFile ( getPackageFile, stackPackageFileFromCabal ) import Stack.Prelude hiding ( Display (..) ) -import Stack.Types.BuildConfig - ( HasBuildConfig (..), getProjectWorkDir ) +import Stack.Types.BuildConfig ( HasBuildConfig (..), getWorkDir ) import Stack.Types.CompCollection ( CompCollection, collectionLookup, foldAndMakeCollection - , foldComponentToAnotherCollection, getBuildableSetText + , foldComponentToAnotherCollection, getBuildableSet + , getBuildableSetText ) import Stack.Types.Compiler ( ActualCompiler (..) ) import Stack.Types.CompilerPaths ( cabalVersionL ) import Stack.Types.Component ( HasBuildInfo, HasComponentInfo, StackUnqualCompName (..) ) +import Stack.Types.ComponentUtils ( emptyCompName, toCabalName ) import qualified Stack.Types.Component as Component import Stack.Types.Config ( Config (..), HasConfig (..) ) import Stack.Types.Dependency @@ -113,7 +113,7 @@ ) import Stack.Types.PackageFile ( DotCabalPath, PackageComponentFile (..) ) -import Stack.Types.SourceMap (Target(..)) +import Stack.Types.SourceMap ( Target(..), PackageType (..) ) import Stack.Types.Version ( VersionRange, intersectVersionRanges, withinRange ) import System.FilePath ( replaceExtension ) @@ -206,7 +206,8 @@ getPackageFile stackPackage cabalFP let subLibs = S.toList $ subLibComponents $ M.keysSet componentsModules - excludedSubLibs <- mapM (parsePackageNameThrowing . T.unpack) subLibs + excludedSubLibs = + map (unqualComponentNameToPackageName . toCabalName) subLibs componentsOpts <- generatePkgDescOpts installMap installedMap @@ -260,7 +261,7 @@ } let insertInMap name compVal = M.insert name (generate name compVal) let translatedInsertInMap constructor name = - insertInMap (stackUnqualToQual constructor name) + insertInMap (constructor name) let makeBuildInfoOpts selector constructor = foldOnNameAndBuildInfo (selector pkg) @@ -330,7 +331,7 @@ srcOpts = map (("-i" <>) . toFilePathNoTrailingSep) (concat - [ [ componentBuildDir bi.cabalVersion bi.componentName bi.distDir ] + [ [ componentBuildDir bi.componentName bi.distDir ] , [ bi.cabalDir | null bi.buildInfo.hsSourceDirs ] @@ -338,12 +339,11 @@ (toIncludeDir . getSymbolicPath) bi.buildInfo.hsSourceDirs , [ componentAutogen ] - , maybeToList (packageAutogenDir bi.cabalVersion bi.distDir) + , [ packageAutogenDir bi.distDir ] , [ componentOutputDir bi.componentName bi.distDir ] ]) ++ [ "-stubdir=" ++ toFilePathNoTrailingSep (buildDir bi.distDir) ] - componentAutogen = - componentAutogenDir bi.cabalVersion bi.componentName bi.distDir + componentAutogen = componentAutogenDir bi.componentName bi.distDir toIncludeDir "." = Just bi.cabalDir toIncludeDir relDir = concatAndCollapseAbsDir bi.cabalDir relDir includeOpts = @@ -565,11 +565,11 @@ -> m (Path Abs File) buildLogPath package' msuffix = do env <- ask - let stack = getProjectWorkDir env + let workDir = getWorkDir env fp <- parseRelFile $ concat $ packageIdentifierString (packageIdentifier package') : maybe id (\suffix -> ("-" :) . (suffix :)) msuffix [".log"] - pure $ stack </> relDirLogs </> fp + pure $ workDir </> relDirLogs </> fp {- FIXME -- | Create a 'ProjectPackage' from a directory containing a package. @@ -667,20 +667,20 @@ gatherUnknownTools :: HasBuildInfo x => CompCollection x -> Set Text gatherUnknownTools = foldr' addUnknownTools mempty -buildableForeignLibs :: Package -> Set Text -buildableForeignLibs pkg = getBuildableSetText pkg.foreignLibraries +buildableForeignLibs :: Package -> Set StackUnqualCompName +buildableForeignLibs pkg = getBuildableSet pkg.foreignLibraries -buildableSubLibs :: Package -> Set Text -buildableSubLibs pkg = getBuildableSetText pkg.subLibraries +buildableSubLibs :: Package -> Set StackUnqualCompName +buildableSubLibs pkg = getBuildableSet pkg.subLibraries -buildableExes :: Package -> Set Text -buildableExes pkg = getBuildableSetText pkg.executables +buildableExes :: Package -> Set StackUnqualCompName +buildableExes pkg = getBuildableSet pkg.executables -buildableTestSuites :: Package -> Set Text -buildableTestSuites pkg = getBuildableSetText pkg.testSuites +buildableTestSuites :: Package -> Set StackUnqualCompName +buildableTestSuites pkg = getBuildableSet pkg.testSuites -buildableBenchmarks :: Package -> Set Text -buildableBenchmarks pkg = getBuildableSetText pkg.benchmarks +buildableBenchmarks :: Package -> Set StackUnqualCompName +buildableBenchmarks pkg = getBuildableSet pkg.benchmarks -- | Apply a generic processing function in a Monad over all of the Package's -- components. @@ -737,12 +737,12 @@ -- | This is a function to iterate in a monad over all of a package component's -- dependencies, and yield a collection of results. processPackageDeps :: - (Monad m, Monoid (targetedCollection resT)) + (Monad m) => Package - -> (resT -> targetedCollection resT -> targetedCollection resT) - -> (PackageName -> DepValue -> m resT) - -> m (targetedCollection resT) - -> m (targetedCollection resT) + -> (smallResT -> resT -> resT) + -> (PackageName -> DepValue -> m smallResT) + -> m resT + -> m resT processPackageDeps pkg combineResults fn = do let asPackageNameSet accessor = S.map (mkPackageName . T.unpack) $ getBuildableSetText $ accessor pkg @@ -772,6 +772,21 @@ -> m [resT] processPackageDepsToList pkg fn = processPackageDeps pkg (:) fn (pure []) +-- | Iterate/fold on all the package dependencies, components, setup deps and +-- all. +processPackageDepsEither :: + (Monad m, Monoid a, Monoid b) + => Package + -> (PackageName -> DepValue -> m (Either a b)) + -> m (Either a b) +processPackageDepsEither pkg fn = + processPackageDeps pkg combineRes fn (pure (Right mempty)) + where + combineRes (Left err) (Left errs) = Left (errs <> err) + combineRes _ (Left b) = Left b + combineRes (Left err) _ = Left err + combineRes (Right a) (Right b) = Right $ a <> b + -- | List all package's dependencies in a "free" context through the identity -- monad. listOfPackageDeps :: Package -> [PackageName] @@ -784,71 +799,90 @@ runIdentity $ processPackageDeps pkg S.insert (\pn _ -> pure pn) (pure mempty) -- | This implements a topological sort on all targeted components for the build --- and their dependencies. It's only targeting internal dependencies, so it's doing --- a topological sort on a subset of a package's components. +-- and their dependencies. It's only targeting internal dependencies, so it's +-- doing a topological sort on a subset of a package's components. -- --- Note that in Cabal they use the Data.Graph struct to pursue the same goal. But dong this here --- would require a large number intermediate data structure. --- This is needed because we need to get the right GhcPkgId of the relevant internal dependencies --- of a component before building it as a component. +-- Note that in Cabal they use the Data.Graph struct to pursue the same goal. +-- But dong this here would require a large number intermediate data structure. +-- This is needed because we need to get the right GhcPkgId of the relevant +-- internal dependencies of a component before building it as a component. topSortPackageComponent :: Package -> Target -> Bool - -- ^ Include directTarget or not. False here means we won't - -- include the actual targets in the result, only their deps. - -- Using it with False here only in GHCi + -- ^ Include directTarget or not. False here means we won't include the + -- actual targets in the result, only their deps. Using it with False here + -- only in GHCi -> Seq NamedComponent -topSortPackageComponent package target includeDirectTarget = runST $ do - alreadyProcessedRef <- newSTRef (mempty :: Set NamedComponent) - let processInitialComponents c = case target of - TargetAll{} -> processComponent includeDirectTarget alreadyProcessedRef c +topSortPackageComponent package target includeDirectTarget = + topProcessPackageComponent package target processor mempty + where + processor packageType component + | not includeDirectTarget && packageType == PTProject = id + | otherwise = \v -> v |> component.qualifiedName + +-- | Process a package's internal components in the order of their topological sort. +-- The first iteration will effect the component depending on no other component etc, +-- iterating by increasing amount of required dependencies. +-- 'PackageType' with value 'PTProject' here means the component is a direct target +-- and 'PTDependency' means it's a dependency of a direct target. +topProcessPackageComponent :: forall b. + Package + -> Target + -> ( forall component. (HasComponentInfo component) + => PackageType + -> component + -> b + -> b + ) + -> b + -> b +topProcessPackageComponent package target fn res = do + let initialState = (mempty, res) + processInitialComponents c = case target of + TargetAll{} -> processComponent PTProject c TargetComps targetSet -> if S.member c.qualifiedName targetSet - then processComponent includeDirectTarget alreadyProcessedRef c + then processComponent PTProject c else id - processPackageComponent package processInitialComponents (pure mempty) - where - processComponent :: forall s component. HasComponentInfo component - => Bool + snd $ processPackageComponent package processInitialComponents initialState + where + processComponent :: HasComponentInfo component + => PackageType -- ^ Finally add this component in the seq - -> STRef s (Set NamedComponent) - -> component - -> ST s (Seq NamedComponent) - -> ST s (Seq NamedComponent) - processComponent finallyAddComponent alreadyProcessedRef component res = do - let depMap = componentDependencyMap component - internalDep = M.lookup package.name depMap - processSubDep = processOneDep alreadyProcessedRef internalDep res - qualName = component.qualifiedName - processSubDepSaveName - | finallyAddComponent = (|> qualName) <$> processSubDep - | otherwise = processSubDep - -- This is an optimization, the only components we are likely to process - -- multiple times are the ones we can find in dependencies, otherwise we - -- only fold on a single version of each component by design. - if isPotentialDependency qualName - then do - alreadyProcessed <- readSTRef alreadyProcessedRef - if S.member qualName alreadyProcessed - then res - else modifySTRef' alreadyProcessedRef (S.insert qualName) - >> processSubDepSaveName - else processSubDepSaveName - lookupLibName isMain name = if isMain - then package.library - else collectionLookup name package.subLibraries - processOneDep alreadyProcessed mDependency res = - case (.depType) <$> mDependency of - Just (AsLibrary (DepLibrary mainLibDep subLibDeps)) -> do - let processMainLibDep = - case (mainLibDep, lookupLibName True mempty) of - (True, Just mainLib) -> - processComponent True alreadyProcessed mainLib - _ -> id - processSingleSubLib name = - case lookupLibName False name.unqualCompToText of - Just lib -> processComponent True alreadyProcessed lib - Nothing -> id - processSubLibDep r = foldr' processSingleSubLib r subLibDeps - processSubLibDep (processMainLibDep res) - _ -> res + -> component + -> (Set NamedComponent, b) + -> (Set NamedComponent, b) + processComponent packageType component currentRes@(_a, !_b) = do + let depMap = componentDependencyMap component + internalDep = M.lookup package.name depMap + qualName = component.qualifiedName + alreadyProcessed = fst currentRes + !appendToResult = fn packageType component + -- This is an optimization, the only components we are likely to process + -- multiple times are the ones we can find in dependencies, otherwise we + -- only fold on a single version of each component by design. + processedDeps = processOneDep internalDep currentRes + if isPotentialDependency qualName + then + if S.member qualName alreadyProcessed + then currentRes + else bimap (S.insert qualName) appendToResult processedDeps + else second appendToResult processedDeps + lookupLibName isMain name = if isMain + then package.library + else collectionLookup name package.subLibraries + processOneDep mDependency res' = + case (.depType) <$> mDependency of + Just (AsLibrary (DepLibrary mainLibDep subLibDeps)) -> do + let processMainLibDep = + case (mainLibDep, lookupLibName True emptyCompName) of + (True, Just mainLib) -> + processComponent PTDependency mainLib + _ -> id + processSingleSubLib name = + case lookupLibName False name of + Just lib -> processComponent PTDependency lib + Nothing -> id + processSubLibDep r = foldr' processSingleSubLib r subLibDeps + processSubLibDep (processMainLibDep res') + _ -> res'
src/Stack/PackageDump.hs view
@@ -10,10 +10,12 @@ , conduitDumpPackage , ghcPkgDump , ghcPkgDescribe + , ghcPkgField , sinkMatching , pruneDeps ) where +import Control.Monad.Extra ( whenJust ) import Data.Attoparsec.Args ( EscapingMode (..), argsParser ) import Data.Attoparsec.Text as P import Data.Conduit ( await, leftover, toConsumer, yield ) @@ -21,6 +23,7 @@ import qualified Data.Conduit.Text as CT import qualified Data.Map as Map import qualified Data.Set as Set +import qualified Distribution.Pretty as C import qualified Distribution.Text as C import Distribution.Types.MungedPackageName ( decodeCompatPackageName ) @@ -31,7 +34,7 @@ import Stack.GhcPkg ( createDatabase ) import Stack.Prelude import Stack.Types.CompilerPaths ( GhcPkgExe (..), HasCompiler (..) ) -import Stack.Types.Component ( StackUnqualCompName(..) ) +import Stack.Types.ComponentUtils ( unqualCompFromText ) import Stack.Types.DumpPackage ( DumpPackage (..), SublibDump (..) ) import Stack.Types.GhcPkgId ( GhcPkgId, parseGhcPkgId ) @@ -90,6 +93,27 @@ pkgexe ["describe", "--simple-output", packageNameString pkgName'] +-- | Call @ghc-pkg field@ with appropriate flags and stream to the given +-- sink, using the given package database. Throws 'ExitCodeException' if the +-- process fails (for example, if the package is not found in the package +-- database or the field is not found in the package's *.conf file). +ghcPkgField :: + (HasCompiler env, HasProcessContext env, HasTerm env) + => GhcPkgExe + -> Path Abs Dir + -- ^ A package database. + -> MungedPackageId + -- ^ A munged package identifier. + -> String + -- ^ A field name. + -> ConduitM Text Void (RIO env) a + -- ^ Sink. + -> RIO env a +ghcPkgField pkgexe pkgDb mungedPkgId fieldName = ghcPkgCmdArgs + pkgexe + ["field", C.prettyShow mungedPkgId, fieldName, "--simple-output" ] + [pkgDb] + -- | Call @ghc-pkg@ and stream to the given sink, using the either the global -- package database or the given package databases. ghcPkgCmdArgs :: @@ -237,7 +261,7 @@ fromCabalName libName' MungedPackageName _parentPackageName _ -> "" libName = - maybe getLibNameFromLegacyName StackUnqualCompName maybeLibName + maybe getLibNameFromLegacyName unqualCompFromText maybeLibName sublib = flip SublibDump libName <$> maybePackageName parseQuoted key = case mapM (P.parseOnly (argsParser NoEscaping)) val of @@ -321,15 +345,13 @@ noIndent = do mx <- await - case mx of - Nothing -> pure () - Just bs -> do - let (spaces, val) = T.span (== ' ') bs - if T.length spaces == 0 - then leftover val - else do - yield val - loopIndent (T.length spaces) + whenJust mx $ \bs -> do + let (spaces, val) = T.span (== ' ') bs + if T.length spaces == 0 + then leftover val + else do + yield val + loopIndent (T.length spaces) loopIndent i = loop where
src/Stack/Path.hs view
@@ -13,6 +13,7 @@ , pathsFromEnvConfig ) where +import Control.Exception ( throw ) import Data.List ( intercalate ) import qualified Data.Text as T import qualified Data.Text.IO as T @@ -30,14 +31,13 @@ import Stack.Runners ( ShouldReexec (..), withConfig, withDefaultEnvConfig ) import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), projectRootL - , stackYamlL - ) + ( BuildConfig (..), HasBuildConfig (..), configFileL ) import Stack.Types.BuildOptsMonoid ( buildOptsMonoidHaddockL ) import Stack.Types.CompilerPaths ( CompilerPaths (..), HasCompiler (..), getCompilerPath ) import Stack.Types.Config - ( Config (..), HasConfig (..), stackGlobalConfigL ) + ( Config (..), HasConfig (..), userGlobalConfigFileL ) +import Stack.Types.Config.Exception ( ConfigPrettyException (..) ) import Stack.Types.EnvConfig ( EnvConfig, HasEnvConfig (..), bindirCompilerTools , hpcReportDir, installationRootDeps, installationRootLocal @@ -236,9 +236,9 @@ -- to generate an appropriate string. Trailing slashes are removed, see #506. pathsFromConfig :: [(String, Text, Config -> Text)] pathsFromConfig = - [ ( "Global Stack configuration file" + [ ( "User-specific global configuration file" , T.pack stackGlobalConfigOptionName - , view (stackGlobalConfigL . to toFilePath . to T.pack) + , view (userGlobalConfigFileL . to toFilePath . to T.pack) ) , ( "Install location for GHC and other core tools (see 'stack ls tools' command)" , "programs" @@ -261,14 +261,14 @@ -- #506. pathsFromEnvConfig :: [(String, Text, UseHaddocks (EnvConfigPathInfo -> Text))] pathsFromEnvConfig = - [ ( "Project root (derived from stack.yaml file)" + [ ( "Project root (derived from the project-level configuration file; \ + \stack.yaml, by default)" , "project-root" - , WithoutHaddocks $ - view (projectRootL . to toFilePathNoTrailingSep . to T.pack) + , WithoutHaddocks $ view (configFileL . to toProjectConfigFileRootPath) ) - , ( "Configuration location (where the stack.yaml file is)" + , ( "Project-level configuration file (stack.yaml, by default)" , "config-location" - , WithoutHaddocks $ view (stackYamlL . to toFilePath . to T.pack) + , WithoutHaddocks $ view (configFileL . to toProjectConfigFilePath) ) , ( "PATH environment variable" , "bin-path" @@ -350,6 +350,17 @@ , WithoutHaddocks $ T.pack . toFilePathNoTrailingSep . (.hpcDir) ) ] + where + toProjectConfigFileRootPath :: Either (Path Abs File) (Path Abs File) -> Text + toProjectConfigFileRootPath (Left _) = + throw $ PrettyException ConfigFileNotProjectLevelBug + toProjectConfigFileRootPath (Right projectConfigFile) = + T.pack $ toFilePathNoTrailingSep $ parent projectConfigFile + toProjectConfigFilePath :: Either (Path Abs File) (Path Abs File) -> Text + toProjectConfigFilePath (Left _) = + throw $ PrettyException ConfigFileNotProjectLevelBug + toProjectConfigFilePath (Right projectConfigFile) = + T.pack $ toFilePath projectConfigFile -- | 'Text' equivalent of 'stackRootOptionName'. stackRootOptionName' :: Text
src/Stack/Runners.hs view
@@ -253,7 +253,7 @@ shouldUpgradeCheck :: RIO Config () shouldUpgradeCheck = do config <- ask - when config.recommendUpgrade $ do + when config.recommendStackUpgrade $ do now <- getCurrentTime let yesterday = addUTCTime (-(24 * 60 * 60)) now checks <- upgradeChecksSince yesterday @@ -281,7 +281,7 @@ [ flow "Tired of seeing this? Add" , style Shell (flow "recommend-stack-upgrade: false") , "to" - , pretty config.userConfigPath <> "." + , pretty config.userGlobalConfigFile <> "." ] <> blankLine _ -> pure ()
src/Stack/SDist.hs view
@@ -15,17 +15,18 @@ , readLocalPackage ) where -import qualified Codec.Archive.Tar.Utf8 as Tar +import qualified Codec.Archive.Tar as Tar import qualified Codec.Archive.Tar.Entry as Tar import qualified Codec.Compression.GZip as GZip import Conduit ( runConduitRes, sourceLazy, sinkFileCautious ) import Control.Concurrent.Execute ( ActionContext (..), Concurrency (..) ) +import Control.Monad.Extra ( whenJust ) import qualified Data.ByteString as S -import qualified Data.ByteString.Char8 as S8 import qualified Data.ByteString.Lazy as L import Data.Char ( toLower ) import Data.Data ( cast ) +import qualified Data.Either.Extra as EE import qualified Data.List as List import qualified Data.Map.Strict as Map import qualified Data.Set as Set @@ -65,7 +66,7 @@ import Stack.SourceMap ( mkProjectPackage ) import Stack.Types.Build ( TaskType (..) ) import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), stackYamlL ) + ( BuildConfig (..), HasBuildConfig (..), configFileL ) import Stack.Types.BuildOpts ( BuildOpts (..) ) import Stack.Types.BuildOptsCLI ( defaultBuildOptsCLI ) import Stack.Types.Config ( Config (..), HasConfig (..) ) @@ -152,12 +153,15 @@ dirs <- view $ buildConfigL . to (map ppRoot . Map.elems . (.smWanted.project)) when (null dirs) $ do - stackYaml <- view stackYamlL + configFile <- view configFileL + -- We are indifferent as to whether the configuration file is a + -- user-specific global or a project-level one. + let eitherConfigFile = EE.fromEither configFile prettyErrorL [ style Shell "stack sdist" , flow "expects a list of targets, and otherwise defaults to all \ \of the project's packages. However, the configuration at" - , pretty stackYaml + , pretty eitherConfigFile , flow "contains no packages, so no sdist tarballs will be \ \generated." ] @@ -185,7 +189,8 @@ createDirectoryIfMissing True $ FP.takeDirectory targetTarPath copyFile (toFilePath tarPath) targetTarPath --- | Given the path to a local package, creates its source distribution tarball. +-- | Given the path to a package directory, creates a source distribution +-- tarball for the package. -- -- While this yields a 'FilePath', the name of the tarball, this tarball is not -- written to the disk and instead yielded as a lazy bytestring. @@ -194,7 +199,7 @@ => Maybe PvpBounds -- ^ Override Config value -> Path Abs Dir - -- ^ Path to local package + -- ^ Path to package directory -> RIO env ( FilePath @@ -250,13 +255,9 @@ -- prone and more predictable to read everything in at once, so that's what -- we're doing for now: let tarPath isDir fp = - case Tar.toTarPath isDir (forceUtf8Enc (pkgIdName FP.</> fp)) of + case Tar.toTarPath isDir (pkgIdName FP.</> fp) of Left e -> prettyThrowIO $ ToTarPathException e Right tp -> pure tp - -- convert a String of proper characters to a String of bytes in UTF8 - -- encoding masquerading as characters. This is necessary for tricking the - -- tar package into proper character encoding. - forceUtf8Enc = S8.unpack . T.encodeUtf8 . T.pack packWith f isDir fp = liftIO $ f (pkgFp FP.</> fp) =<< tarPath isDir fp packDir = packWith Tar.packDirectoryEntry True packFile fp @@ -600,9 +601,7 @@ flow "Package check reported the following warnings:" <> line <> bulletedList (map (fromString . show) warnings) - case nonEmpty errors of - Nothing -> pure () - Just ne -> prettyThrowM $ CheckException ne + whenJust (nonEmpty errors) $ \ne -> prettyThrowM $ CheckException ne buildExtractedTarball :: HasEnvConfig env => ResolvedPath Dir -> RIO env () buildExtractedTarball pkgDir = do
src/Stack/Script.hs view
@@ -164,9 +164,10 @@ then (NoRun, SECompile) else (opts.shouldRun, opts.compile) - root <- withConfig NoReexec $ view stackRootL outputDir <- if opts.useRoot then do + root <- local (over globalOptsL modifyGO) $ + withConfig NoReexec $ view stackRootL scriptFileAsDir <- maybe (throwIO $ FailedToParseScriptFileAsDirBug scriptFile) pure
src/Stack/Setup.hs view
@@ -44,6 +44,7 @@ import qualified Data.Conduit.List as CL import Data.Conduit.Process.Typed ( createSource ) import Data.Conduit.Zlib ( ungzip ) +import qualified Data.Either.Extra as EE import Data.List.Split ( splitOn ) import qualified Data.Map as Map import qualified Data.Set as Set @@ -78,7 +79,8 @@ import Path.IO ( canonicalizePath, doesFileExist, ensureDir, executable , getPermissions, ignoringAbsence, listDir, removeDirRecur - , renameDir, renameFile, resolveFile', withTempDir + , removeFile, renameDir, renameFile, resolveFile' + , withTempDir ) import RIO.List ( headMaybe, intercalate, intersperse, isPrefixOf @@ -122,7 +124,7 @@ import Stack.Storage.User ( loadCompilerPaths, saveCompilerPaths ) import Stack.Types.Build.Exception ( BuildPrettyException (..) ) import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), projectRootL + ( BuildConfig (..), HasBuildConfig (..), configFileRootL , wantedCompilerVersionL ) import Stack.Types.BuildOptsCLI ( BuildOptsCLI (..) ) @@ -157,10 +159,11 @@ ( GHCVariant (..), HasGHCVariant (..), ghcVariantName , ghcVariantSuffix ) +import Stack.Types.GlobalOpts ( GlobalOpts (..) ) import Stack.Types.Platform ( HasPlatform (..), PlatformVariant (..) , platformOnlyRelDir ) -import Stack.Types.Runner ( HasRunner (..) ) +import Stack.Types.Runner ( HasRunner (..), Runner (..) ) import Stack.Types.SetupInfo ( SetupInfo (..) ) import Stack.Types.SourceMap ( SMActual (..), SMWanted (..), SourceMap (..) ) @@ -168,6 +171,7 @@ ( VersionCheck, stackMinorVersion, stackVersion ) import Stack.Types.VersionedDownloadInfo ( VersionedDownloadInfo (..) ) +import Stack.Types.WantedCompilerSetter ( WantedCompilerSetter (..) ) import qualified System.Directory as D import System.Environment ( getExecutablePath, lookupEnv ) import System.IO.Error ( isPermissionError ) @@ -618,8 +622,9 @@ -- ^ Should we use a system compiler installation, if available? , wantedCompiler :: !WantedCompiler , compilerCheck :: !VersionCheck - , stackYaml :: !(Maybe (Path Abs File)) - -- ^ If we got the desired GHC version from that file + , configFile :: !(Maybe (Path Abs File)) + -- ^ If we got the desired GHC version from that configuration file, which + -- may be either a user-specific global or a project-level one. , forceReinstall :: !Bool , sanityCheck :: !Bool -- ^ Run a sanity check on the selected GHC @@ -645,18 +650,19 @@ setupEnv needTargets buildOptsCLI mResolveMissingGHC = do config <- view configL bc <- view buildConfigL - let stackYaml = bc.stackYaml + -- We are indifferent as to whether the configuration file is a + -- user-specific global or a project-level one. + let eitherConfigFile = EE.fromEither bc.configFile platform <- view platformL wcVersion <- view wantedCompilerVersionL - wanted <- view wantedCompilerVersionL - actual <- either throwIO pure $ wantedToActual wanted + actual <- either throwIO pure $ wantedToActual wcVersion let wc = actual^.whichCompilerL - let sopts = SetupOpts + sopts = SetupOpts { installIfMissing = config.installGHC , useSystem = config.systemGHC , wantedCompiler = wcVersion , compilerCheck = config.compilerCheck - , stackYaml = Just stackYaml + , configFile = Just eitherConfigFile , forceReinstall = False , sanityCheck = False , skipGhcCheck = config.skipGHCCheck @@ -727,7 +733,8 @@ mGhcRtsEnvVar <- liftIO $ lookupEnv "GHCRTS" envRef <- liftIO $ newIORef Map.empty - let getProcessContext' es = do + let msysEnv = maybe "" (T.pack . show) config.msysEnvironment + getProcessContext' es = do m <- readIORef envRef case Map.lookup es m of Just eo -> pure eo @@ -753,9 +760,9 @@ $ case (sopts.skipMsys, platform) of (False, Platform Cabal.I386 Cabal.Windows) -> - Map.insert "MSYSTEM" "MINGW32" + Map.insert "MSYSTEM" msysEnv (False, Platform Cabal.X86_64 Cabal.Windows) -> - Map.insert "MSYSTEM" "MINGW64" + Map.insert "MSYSTEM" msysEnv _ -> id -- See https://github.com/commercialhaskell/stack/issues/3444 @@ -1055,24 +1062,25 @@ let cabalVersion = cp.cabalVersion notifyIfCabalUntested <- view $ configL . to (.notifyIfCabalUntested) if - | cabalVersion < mkVersion [1, 24, 0] -> do - prettyWarnL - [ flow "Stack no longer supports Cabal versions below 1.24.0.0, but \ - \version" - , fromString (versionString cabalVersion) - , flow "was found. This invocation will most likely fail. To fix \ - \this, either use an older version of Stack or a newer \ - \resolver. Acceptable resolvers: lts-7.0/nightly-2016-05-26 \ - \or later." - ] - | cabalVersion < mkVersion [2, 2, 0] -> do + | cabalVersion < mkVersion [2, 2] -> do + -- Due to a bug, Stack 2.15.1 does not support Cabal < 2. + let downgradeRecommendation = fillSep $ + [ flow "Stack 2.15.5 or earlier" ] + <> [ flow "(except Stack 2.15.1)" | cabalVersion < mkVersion [2] ] prettyWarnL - [ flow "Stack's support of Cabal versions below 2.2.0.0 is \ - \deprecated and may be removed from the next version of \ - \ Stack. Cabal version" + [ flow "Stack uses the version of the Cabal package that comes with \ + \the specified version of GHC. However, Stack no longer \ + \supports such Cabal versions before 2.2. Version" , fromString (versionString cabalVersion) - , flow "was found. Consider using a resolver that is \ - \lts-12.0 or later or nightly-2018-03-13 or later." + , flow "was found. This invocation of Stack may fail. To fix this, \ + \either use" + , downgradeRecommendation + , flow "or use a snapshot that specifies a version of GHC that is \ + \8.4 or later. Stackage LTS Haskell 12.0" + , parens (style Shell "lts-12.0") + , flow "or later or Nightly 2018-03-13" + , parens (style Shell "nightly-2018-03-13") + , flow "or later specify such GHC versions." ] | cabalVersion >= mkVersion [3, 11] && notifyIfCabalUntested -> prettyWarnL @@ -1119,7 +1127,7 @@ tool (installMsys2Windows si) | otherwise -> do - prettyWarnS "Continuing despite missing tool: MSYS2." + prettyWarnS "Stack is not using a Stack-supplied MSYS2." pure Nothing _ -> pure Nothing @@ -1154,6 +1162,11 @@ (Just tool, False) -> [(tool, compilerBuild)] _ -> []) possibleCompilers + globalOpts = config.runner.globalOpts + wantedCompilerSetter + | isJust globalOpts.compiler = CompilerAtCommandLine + | isJust globalOpts.snapshot = SnapshotAtCommandLine + | otherwise = YamlConfiguration sopts.configFile logDebug $ "Found already installed GHC builds: " <> mconcat (intersperse ", " (map (fromString . compilerBuildName . snd) existingCompilers)) @@ -1198,7 +1211,7 @@ [] -> CompilerBuildStandard (_, compilerBuild):_ -> compilerBuild) sopts.compilerCheck - sopts.stackYaml + wantedCompilerSetter suggestion -- | Ensure compiler is installed. @@ -1573,11 +1586,11 @@ stack args = proc "stack" args'' runProcess_ where args'' = "--stack-yaml=" <> relFileHadrianStackDotYaml' : args' - -- If a resolver is specified on the command line, Stack will - -- apply it. This allows the resolver specified in Hadrian's + -- If a snapshot is specified on the command line, Stack will + -- apply it. This allows the snapshot specified in Hadrian's -- stack.yaml file to be overridden. - args' = maybe args addResolver config.resolver - addResolver resolver = "--snapshot=" <> show resolver : args + args' = maybe args addSnapshot config.snapshot + addSnapshot snapshot = "--snapshot=" <> show snapshot : args happy = stack ["install", "happy"] alex = stack ["install", "alex"] -- Executed in the Stack environment, because GHC is required. @@ -1931,17 +1944,28 @@ getInstalledTool installed name goodVersion = Tool <$> maximumByMaybe (comparing pkgVersion) (filterTools name goodVersion installed) +-- | Obtain and install the specified tool, using the specified download +-- information and installer. Also deletes the archive file for the tool after +-- installation. downloadAndInstallTool :: (HasTerm env, HasBuildConfig env) => Path Abs Dir + -- ^ Location of the directory for tools. -> DownloadInfo + -- ^ Information about the file to obtain. -> Tool + -- ^ The tool in question. -> ( Path Abs File + -- Location of archive file. -> ArchiveType + -- Type of archive file. -> Path Abs Dir + -- Tempory directory to use. -> Path Abs Dir + -- Destination directory for installed tool. -> RIO env () ) + -- ^ Installer. -> RIO env Tool downloadAndInstallTool programsDir downloadInfo tool installer = do ensureDir programsDir @@ -1954,6 +1978,7 @@ installer file at tempDir dir markInstalled programsDir tool liftIO $ ignoringAbsence (removeDirRecur tempDir) + liftIO $ ignoringAbsence (removeFile file) pure tool -- Exceptions thrown by this function are caught by @@ -2158,8 +2183,8 @@ pure path (parseRelFile -> Just path) -> do warnOnIgnoredChecks - root <- view projectRootL - pure (root </> path) + configFileRoot <- view configFileRootL + pure (configFileRoot </> path) _ -> prettyThrowIO $ URLInvalid url where url = T.unpack downloadInfo.url
src/Stack/Setup/Installed.hs view
@@ -32,14 +32,16 @@ import Path.IO ( doesDirExist, ignoringAbsence, listDir, removeFile ) import RIO.Process ( HasProcessContext, proc, readProcess_ ) import Stack.Constants - ( relDirBin, relDirInclude, relDirLib, relDirLocal, relDirMingw - , relDirMingw32, relDirMingw64, relDirUsr + ( relDirBin, relDirInclude, relDirLib, relDirLocal + , relDirMingw, relDirUsr ) import Stack.Prelude import Stack.Types.Compiler ( ActualCompiler (..), WhichCompiler (..) ) import Stack.Types.Config ( Config (..), HasConfig (..) ) +import Stack.Types.Config.Exception ( ConfigPrettyException (..) ) import Stack.Types.ExtraDirs ( ExtraDirs (..) ) +import Stack.Types.MsysEnvironment ( relDirMsysEnv ) data Tool = Tool PackageIdentifier -- ^ e.g. ghc-7.8.4, msys2-20150512 @@ -144,34 +146,24 @@ , dir </> relDirMingw </> relDirBin ] } - (Platform Cabal.I386 Cabal.Windows, "msys2") -> pure mempty - { bins = - [ dir </> relDirMingw32 </> relDirBin - , dir </> relDirUsr </> relDirBin - , dir </> relDirUsr </> relDirLocal </> relDirBin - ] - , includes = - [ dir </> relDirMingw32 </> relDirInclude - ] - , libs = - [ dir </> relDirMingw32 </> relDirLib - , dir </> relDirMingw32 </> relDirBin - ] - } - (Platform Cabal.X86_64 Cabal.Windows, "msys2") -> pure mempty - { bins = - [ dir </> relDirMingw64 </> relDirBin - , dir </> relDirUsr </> relDirBin - , dir </> relDirUsr </> relDirLocal </> relDirBin - ] - , includes = - [ dir </> relDirMingw64 </> relDirInclude - ] - , libs = - [ dir </> relDirMingw64 </> relDirLib - , dir </> relDirMingw64 </> relDirBin - ] - } + (Platform _ Cabal.Windows, "msys2") -> do + relDirMsysEnvPrefix <- case config.msysEnvironment of + Just msysEnv -> pure $ relDirMsysEnv msysEnv + Nothing -> throwM NoMsysEnvironmentBug + pure mempty + { bins = + [ dir </> relDirMsysEnvPrefix </> relDirBin + , dir </> relDirUsr </> relDirBin + , dir </> relDirUsr </> relDirLocal </> relDirBin + ] + , includes = + [ dir </> relDirMsysEnvPrefix </> relDirInclude + ] + , libs = + [ dir </> relDirMsysEnvPrefix </> relDirLib + , dir </> relDirMsysEnvPrefix </> relDirBin + ] + } (_, isGHC -> True) -> pure mempty { bins = [ dir </> relDirBin
src/Stack/SetupCmd.hs view
@@ -12,12 +12,13 @@ , setup ) where +import qualified Data.Either.Extra as EE import Stack.Prelude import Stack.Runners ( ShouldReexec (..), withBuildConfig, withConfig ) import Stack.Setup ( SetupOpts (..), ensureCompilerAndMsys ) import Stack.Types.BuildConfig - ( HasBuildConfig, stackYamlL, wantedCompilerVersionL ) + ( HasBuildConfig, configFileL, wantedCompilerVersionL ) import Stack.Types.CompilerPaths ( CompilerPaths (..) ) import Stack.Types.Config ( Config (..), HasConfig (..) ) import Stack.Types.GHCVariant ( HasGHCVariant ) @@ -40,14 +41,22 @@ if installGHC then withBuildConfig $ do - (wantedCompiler, compilerCheck, mstack) <- + (wantedCompiler, compilerCheck, mConfigFile) <- case sco.compilerVersion of Just v -> pure (v, MatchMinor, Nothing) - Nothing -> (,,) - <$> view wantedCompilerVersionL - <*> view (configL . to (.compilerCheck)) - <*> (Just <$> view stackYamlL) - setup sco wantedCompiler compilerCheck mstack + Nothing -> do + wantedCompilerVersion <- view wantedCompilerVersionL + compilerCheck <- view (configL . to (.compilerCheck)) + configFile <- view configFileL + -- We are indifferent as to whether the configuration file is a + -- user-specific global or a project-level one. + let eitherConfigFile = EE.fromEither configFile + pure + ( wantedCompilerVersion + , compilerCheck + , Just eitherConfigFile + ) + setup sco wantedCompiler compilerCheck mConfigFile else prettyWarnL [ "The" @@ -63,15 +72,17 @@ -> WantedCompiler -> VersionCheck -> Maybe (Path Abs File) + -- ^ If we got the desired GHC version from that configuration file, which + -- may be either a user-specific global or a project-level one. -> RIO env () -setup sco wantedCompiler compilerCheck stackYaml = do +setup sco wantedCompiler compilerCheck configFile = do config <- view configL sandboxedGhc <- (.sandboxed) . fst <$> ensureCompilerAndMsys SetupOpts { installIfMissing = True , useSystem = config.systemGHC && not sco.forceReinstall , wantedCompiler , compilerCheck - , stackYaml + , configFile , forceReinstall = sco.forceReinstall , sanityCheck = True , skipGhcCheck = False
src/Stack/SourceMap.hs view
@@ -13,7 +13,6 @@ , DumpedGlobalPackage , actualFromGhc , actualFromHints - , checkFlagsUsedThrowing , globalCondCheck , pruneGlobals , globalsFromHints @@ -32,18 +31,15 @@ import qualified Pantry.SHA256 as SHA256 import qualified RIO.Map as Map import RIO.Process ( HasProcessContext ) -import qualified RIO.Set as Set import Stack.Constants ( stackProgName' ) import Stack.PackageDump ( conduitDumpPackage, ghcPkgDump ) import Stack.Prelude -import Stack.Types.Build.Exception ( BuildPrettyException (..) ) import Stack.Types.Compiler ( ActualCompiler, actualToWanted, wantedToActual ) import Stack.Types.CompilerPaths ( CompilerPaths (..), GhcPkgExe, HasCompiler (..) ) import Stack.Types.Config ( HasConfig ) import Stack.Types.DumpPackage ( DumpPackage (..) ) -import Stack.Types.UnusedFlags ( FlagSource, UnusedFlags (..) ) import Stack.Types.Platform ( HasPlatform (..) ) import Stack.Types.Runner ( rslInLogL ) import Stack.Types.SourceMap @@ -214,46 +210,6 @@ condCheck (PD.Arch arch') = pure $ arch' == arch condCheck c = Left c pure condCheck - -checkFlagsUsedThrowing :: - (MonadIO m, MonadThrow m) - => Map PackageName (Map FlagName Bool) - -> FlagSource - -> Map PackageName ProjectPackage - -> Map PackageName DepPackage - -> m () -checkFlagsUsedThrowing packageFlags source prjPackages deps = do - unusedFlags <- - forMaybeM (Map.toList packageFlags) $ \(pname, flags) -> - getUnusedPackageFlags (pname, flags) source prjPackages deps - unless (null unusedFlags) $ - prettyThrowM $ InvalidFlagSpecification $ Set.fromList unusedFlags - -getUnusedPackageFlags :: - MonadIO m - => (PackageName, Map FlagName Bool) - -> FlagSource - -> Map PackageName ProjectPackage - -> Map PackageName DepPackage - -> m (Maybe UnusedFlags) -getUnusedPackageFlags (name, userFlags) source prj deps = - let maybeCommon = fmap (.projectCommon) (Map.lookup name prj) - <|> fmap (.depCommon) (Map.lookup name deps) - in case maybeCommon of - -- Package is not available as project or dependency - Nothing -> - pure $ Just $ UFNoPackage source name - -- Package exists, let's check if the flags are defined - Just common -> do - gpd <- liftIO common.gpd - let pname = pkgName $ PD.package $ PD.packageDescription gpd - pkgFlags = Set.fromList $ map PD.flagName $ PD.genPackageFlags gpd - unused = Map.keysSet $ Map.withoutKeys userFlags pkgFlags - if Set.null unused - -- All flags are defined, nothing to do - then pure Nothing - -- Error about the undefined flags - else pure $ Just $ UFFlagsNotDefined source pname pkgFlags unused pruneGlobals :: Map PackageName DumpedGlobalPackage
src/Stack/Storage/Project.hs view
@@ -33,12 +33,15 @@ import Pantry.SQLite ( initStorage, withStorage_ ) import Stack.Prelude import Stack.Storage.Util - ( handleMigrationException, updateList, updateSet ) + ( handleMigrationException, listUpdateDiff, setUpdateDiff + , updateCollection + ) import Stack.Types.Build ( CachePkgSrc, ConfigCache (..) ) import Stack.Types.BuildConfig ( BuildConfig (..), HasBuildConfig (..) ) import Stack.Types.Cache ( ConfigCacheType ) -import Stack.Types.ConfigureOpts ( ConfigureOpts (..) ) +import Stack.Types.ConfigureOpts + ( ConfigureOpts (..), configureOptsFromDb ) import Stack.Types.GhcPkgId ( GhcPkgId ) import Stack.Types.Storage ( ProjectStorage (..) ) @@ -115,20 +118,15 @@ -> ReaderT SqlBackend (RIO env) ConfigCache readConfigCache (Entity parentId configCacheParent) = do let pkgSrc = configCacheParent.configCacheParentPkgSrc - pathRelated <- - map ((.configCacheDirOptionValue) . entityVal) <$> + pathRelatedInfo <- selectList [ConfigCacheDirOptionParent ==. parentId] [Asc ConfigCacheDirOptionIndex] - nonPathRelated <- - map ((.configCacheNoDirOptionValue) . entityVal) <$> + nonPathRelatedInfo <- selectList [ConfigCacheNoDirOptionParent ==. parentId] [Asc ConfigCacheNoDirOptionIndex] - let configureOpts = ConfigureOpts - { pathRelated - , nonPathRelated - } + let configureOpts = configureOptsFromDb pathRelatedInfo nonPathRelatedInfo deps <- Set.fromList . map ((.configCacheDepValue) . entityVal) <$> selectList [ConfigCacheDepParent ==. parentId] [] @@ -192,39 +190,35 @@ , ConfigCacheParentPathEnvVar =. new.pathEnvVar ] pure (parentId, Just old) - updateList - ConfigCacheDirOption - ConfigCacheDirOptionParent - parentId - ConfigCacheDirOptionIndex + updateCollection + (listUpdateDiff ConfigCacheDirOptionIndex) + (uncurry $ ConfigCacheDirOption parentId) + [ConfigCacheDirOptionParent ==. parentId] (maybe [] (.configureOpts.pathRelated) mold) new.configureOpts.pathRelated - updateList - ConfigCacheNoDirOption - ConfigCacheNoDirOptionParent - parentId - ConfigCacheNoDirOptionIndex + updateCollection + (listUpdateDiff ConfigCacheNoDirOptionIndex) + (uncurry $ ConfigCacheNoDirOption parentId) + [ConfigCacheNoDirOptionParent ==. parentId] (maybe [] (.configureOpts.nonPathRelated) mold) new.configureOpts.nonPathRelated - updateSet - ConfigCacheDep - ConfigCacheDepParent - parentId - ConfigCacheDepValue + updateCollection + (setUpdateDiff ConfigCacheDepValue) + (ConfigCacheDep parentId) + [ConfigCacheDepParent ==. parentId] (maybe Set.empty (.deps) mold) new.deps - updateSet - ConfigCacheComponent - ConfigCacheComponentParent - parentId - ConfigCacheComponentValue + updateCollection + (setUpdateDiff ConfigCacheComponentValue) + (ConfigCacheComponent parentId) + [ConfigCacheComponentParent ==. parentId] (maybe Set.empty (.components) mold) new.components --- | Mark 'ConfigCache' as inactive in the database. --- We use a flag instead of deleting the records since, in most cases, the same --- cache will be written again within in a few seconds (after --- `cabal configure`), so this avoids unnecessary database churn. +-- | Mark 'ConfigCache' as inactive in the database. We use a flag instead of +-- deleting the records since, in most cases, the same cache will be written +-- again within in a few seconds (after `cabal configure`), so this avoids +-- unnecessary database churn. deactiveConfigCache :: HasBuildConfig env => ConfigCacheKey -> RIO env () deactiveConfigCache (UniqueConfigCacheParent dir type_) = withProjectStorage $
src/Stack/Storage/User.hs view
@@ -45,7 +45,7 @@ import Path.IO ( resolveFile', resolveDir' ) import qualified RIO.FilePath as FP import Stack.Prelude -import Stack.Storage.Util ( handleMigrationException, updateSet ) +import Stack.Storage.Util ( handleMigrationException, updateCollection, setUpdateDiff ) import Stack.Types.Build ( PrecompiledCache (..) ) import Stack.Types.Cache ( Action (..) ) import Stack.Types.Compiler ( ActualCompiler, compilerVersionText ) @@ -260,18 +260,16 @@ precompiledCacheParentLibrary ] pure (parentId, Just old) - updateSet - PrecompiledCacheSubLib - PrecompiledCacheSubLibParent - parentId - PrecompiledCacheSubLibValue + updateCollection + (setUpdateDiff PrecompiledCacheSubLibValue) + (PrecompiledCacheSubLib parentId) + [PrecompiledCacheSubLibParent ==. parentId] (maybe Set.empty (toFilePathSet . (.subLibs)) mold) (toFilePathSet new.subLibs) - updateSet - PrecompiledCacheExe - PrecompiledCacheExeParent - parentId - PrecompiledCacheExeValue + updateCollection + (setUpdateDiff PrecompiledCacheExeValue) + (PrecompiledCacheExe parentId) + [PrecompiledCacheExeParent ==. parentId] (maybe Set.empty (toFilePathSet . (.exes)) mold) (toFilePathSet new.exes) where
src/Stack/Storage/Util.hs view
@@ -5,75 +5,67 @@ -- | Utils for the other Stack.Storage modules module Stack.Storage.Util ( handleMigrationException - , updateList - , updateSet + , updateCollection + , setUpdateDiff + , listUpdateDiff ) where import qualified Data.Set as Set import Database.Persist - ( BaseBackend, EntityField, PersistEntity + ( BaseBackend, EntityField, Filter, PersistEntity , PersistEntityBackend, PersistField, PersistQueryWrite - , SafeToInsert, (<-.), (==.), deleteWhere, insertMany_ + , SafeToInsert, (<-.), deleteWhere, insertMany_ ) import Stack.Prelude import Stack.Types.Storage ( StoragePrettyException (..) ) --- | Efficiently update a set of values stored in a database table -updateSet :: +-- | Efficiently update a collection of values with a given diff function. +updateCollection :: ( PersistEntityBackend record ~ BaseBackend backend - , PersistField parentid - , PersistField value - , Ord value + , Eq (collection rawValue) , PersistEntity record + , PersistField value , MonadIO m , PersistQueryWrite backend , SafeToInsert record + , Foldable collection ) - => (parentid -> value -> record) - -> EntityField record parentid - -> parentid - -> EntityField record value - -> Set value - -> Set value + => (collection rawValue -> collection rawValue -> ([Filter record], [value])) + -> (value -> record) + -> [Filter record] + -> collection rawValue + -> collection rawValue -> ReaderT backend m () -updateSet recordCons parentFieldCons parentId valueFieldCons old new = +updateCollection fnDiffer recordCons extra old new = when (old /= new) $ do - deleteWhere - [ parentFieldCons ==. parentId - , valueFieldCons <-. Set.toList (Set.difference old new) - ] - insertMany_ $ - map (recordCons parentId) $ Set.toList (Set.difference new old) + let (oldMinusNewFilter, newMinusOld) = fnDiffer old new + unless (null oldMinusNewFilter) $ deleteWhere + (extra ++ oldMinusNewFilter) + unless (null newMinusOld) $ insertMany_ $ + map recordCons $ toList newMinusOld --- | Efficiently update a list of values stored in a database table. -updateList :: - ( PersistEntityBackend record ~ BaseBackend backend - , PersistField parentid - , Ord value - , PersistEntity record - , MonadIO m - , PersistQueryWrite backend - , SafeToInsert record - ) - => (parentid -> Int -> value -> record) - -> EntityField record parentid - -> parentid - -> EntityField record Int +setUpdateDiff :: + (Ord value, PersistField value) + => EntityField record value + -> Set value + -> Set value + -> ([Filter record], [value]) +setUpdateDiff indexFieldCons old new = + let oldMinusNew = Set.difference old new + in ([indexFieldCons <-. toList oldMinusNew], toList $ Set.difference new old) + +listUpdateDiff :: + (Ord value) + => EntityField record Int -> [value] -> [value] - -> ReaderT backend m () -updateList recordCons parentFieldCons parentId indexFieldCons old new = - when (old /= new) $ do - let oldSet = Set.fromList (zip [0 ..] old) - newSet = Set.fromList (zip [0 ..] new) - deleteWhere - [ parentFieldCons ==. parentId - , indexFieldCons <-. - map fst (Set.toList $ Set.difference oldSet newSet) - ] - insertMany_ $ - map (uncurry $ recordCons parentId) $ - Set.toList (Set.difference newSet oldSet) + -> ([Filter record], [(Int, value)]) +listUpdateDiff indexFieldCons old new = + let oldSet = Set.fromList (zip [0 ..] old) + newSet = Set.fromList (zip [0 ..] new) + oldMinusNew = Set.difference oldSet newSet + indexList = map fst (Set.toList oldMinusNew) + in ([indexFieldCons <-. indexList], toList $ Set.difference newSet oldSet) handleMigrationException :: HasLogFunc env => RIO env a -> RIO env a handleMigrationException inner = do
src/Stack/Types/ApplyGhcOptions.hs view
@@ -10,9 +10,9 @@ -- | Which packages do ghc-options on the command line apply to? data ApplyGhcOptions - = AGOTargets -- ^ all local targets - | AGOLocals -- ^ all local packages, even non-targets - | AGOEverything -- ^ every package + = AGOTargets -- ^ All project packages that are targets. + | AGOLocals -- ^ All project packages, even non-targets. + | AGOEverything -- ^ All packages, project packages and dependencies. deriving (Bounded, Enum, Eq, Ord, Read, Show) instance FromJSON ApplyGhcOptions where
src/Stack/Types/ApplyProgOptions.hs view
@@ -11,9 +11,9 @@ -- | Which packages do all and any --PROG-option options on the command line -- apply to? data ApplyProgOptions - = APOTargets -- ^ All local packages that are targets. - | APOLocals -- ^ All local packages (targets or otherwise). - | APOEverything -- ^ All packages (local or otherwise). + = APOTargets -- ^ All project packages that are targets. + | APOLocals -- ^ All project packages (targets or otherwise). + | APOEverything -- ^ All packages (project packages or dependencies). deriving (Bounded, Enum, Eq, Ord, Read, Show) instance FromJSON ApplyProgOptions where
src/Stack/Types/Build.hs view
@@ -45,7 +45,6 @@ import Data.Aeson ( ToJSON, FromJSON ) import qualified Data.ByteString as S import Data.List as L -import qualified Data.Map as Map import qualified Data.Text as T import Database.Persist.Sql ( PersistField (..), PersistFieldSql (..) @@ -59,7 +58,11 @@ ( BenchmarkOpts (..), BuildOpts (..), TestOpts (..) ) import Stack.Types.BuildOptsCLI ( BuildSubset (..), FileWatchOpts (..) ) -import Stack.Types.ConfigureOpts ( ConfigureOpts, configureOpts ) +import Stack.Types.ComponentUtils ( StackUnqualCompName ) +import Stack.Types.ConfigureOpts + ( BaseConfigOpts, ConfigureOpts, PackageConfigureOpts + , configureOpts + ) import Stack.Types.GhcPkgId ( GhcPkgId ) import Stack.Types.IsMutable ( IsMutable (..) ) import Stack.Types.Package @@ -67,6 +70,7 @@ , LocalPackage (..), Package (..), PackageSource (..) , packageIdentifier, psVersion ) +import Stack.Types.EnvConfig ( EnvConfig ) -- | Package dependency oracle. newtype PkgDepsOracle @@ -156,18 +160,16 @@ -- | Given the IDs of any missing packages, produce the configure options data TaskConfigOpts = TaskConfigOpts { missing :: !(Set PackageIdentifier) - -- ^ Dependencies for which we don't yet have an GhcPkgId - , opts :: !(Map PackageIdentifier GhcPkgId -> ConfigureOpts) - -- ^ Produce the list of options given the missing @GhcPkgId@s + -- ^ Dependencies for which we don't yet have a 'GhcPkgId' + , envConfig :: !EnvConfig + , baseConfigOpts :: !BaseConfigOpts + , isLocalNonExtraDep :: !Bool + , isMutable :: !IsMutable + , pkgConfigOpts :: PackageConfigureOpts } instance Show TaskConfigOpts where - show (TaskConfigOpts missing f) = concat - [ "Missing: " - , show missing - , ". Without those: " - , show $ f Map.empty - ] + show tco = "Missing: " ++ show tco.missing -- | Type representing different types of task, depending on what is to be -- built. @@ -229,7 +231,7 @@ -- ^ Final actions to be taken (test, benchmark, etc) , unregisterLocal :: !(Map GhcPkgId (PackageIdentifier, Text)) -- ^ Text is reason we're unregistering, for display only - , installExes :: !(Map Text InstallLocation) + , installExes :: !(Map StackUnqualCompName InstallLocation) -- ^ Executables that should be installed after successful building } deriving Show
src/Stack/Types/Build/ConstructPlan.hs view
@@ -12,9 +12,11 @@ , toTask , adrVersion , adrHasLibrary + , isAdrToInstall , Ctx (..) , UnregisterState (..) , ToolWarning (..) + , MissingPresentDeps (..) ) where import Generics.Deriving.Monoid ( mappenddefault, memptydefault ) @@ -29,6 +31,7 @@ import Stack.Types.BuildConfig ( BuildConfig (..), HasBuildConfig(..) ) import Stack.Types.CompilerPaths ( HasCompiler (..) ) +import Stack.Types.ComponentUtils ( StackUnqualCompName ) import Stack.Types.Config ( HasConfig (..) ) import Stack.Types.ConfigureOpts ( BaseConfigOpts ) import Stack.Types.Curator ( Curator ) @@ -39,6 +42,7 @@ import Stack.Types.GHCVariant ( HasGHCVariant (..) ) import Stack.Types.Installed ( InstallLocation, Installed (..), installedVersion ) +import Stack.Types.IsMutable ( IsMutable ) import Stack.Types.Package ( ExeName (..), LocalPackage (..), Package (..) , PackageSource (..) @@ -87,7 +91,7 @@ { wFinals :: !(Map PackageName (Either ConstructPlanException Task)) -- ^ A dictionary of package names, and either a final task to perform when -- building the package or an exception. - , wInstall :: !(Map Text InstallLocation) + , wInstall :: !(Map StackUnqualCompName InstallLocation) -- ^ A dictionary of executables to be installed, and location where the -- executable's binary is placed. , wDirty :: !(Map PackageName Text) @@ -118,6 +122,10 @@ -- ^ An existing installation provides the package name. deriving Show +isAdrToInstall :: AddDepRes -> Bool +isAdrToInstall ADRToInstall{} = True +isAdrToInstall _ = False + toTask :: AddDepRes -> Maybe Task toTask (ADRToInstall task) = Just task toTask (ADRFound _ _) = Nothing @@ -138,6 +146,23 @@ adrHasLibrary (ADRFound _ Library{}) = True adrHasLibrary (ADRFound _ Executable{}) = False +data MissingPresentDeps = MissingPresentDeps + { missingPackages :: !(Set PackageIdentifier) + , presentPackages :: !(Map PackageIdentifier GhcPkgId) + , isMutable :: !IsMutable + } + deriving (Show) + +instance Semigroup MissingPresentDeps where + (<>) a b = MissingPresentDeps + { missingPackages = missingPackages a <> missingPackages b + , presentPackages = presentPackages a <> presentPackages b + , isMutable = isMutable a <> isMutable b + } + +instance Monoid MissingPresentDeps where + mempty = MissingPresentDeps mempty mempty mempty + -- | Type representing values used as the environment to be read from during the -- construction of a build plan (the \'context\'). data Ctx = Ctx @@ -212,8 +237,8 @@ instance HasEnvConfig Ctx where envConfigL = lens (.ctxEnvConfig) (\x y -> x { ctxEnvConfig = y }) --- | State to be maintained during the calculation of local packages to --- unregister. +-- | State to be maintained during the calculation of project packages and local +-- extra-deps to unregister. data UnregisterState = UnregisterState { toUnregister :: !(Map GhcPkgId (PackageIdentifier, Text)) , toKeep :: ![DumpPackage]
src/Stack/Types/Build/Exception.hs view
@@ -27,12 +27,13 @@ import qualified Distribution.Version as C import RIO.NonEmpty ( nonEmpty ) import RIO.Process ( showProcessArgDebug ) -import Stack.Constants - ( defaultUserConfigPath, wiredInPackages ) +import Stack.Constants ( defaultUserConfigPath, wiredInPackages ) import Stack.Prelude import Stack.Types.Compiler ( ActualCompiler, compilerVersionString ) import Stack.Types.CompilerBuild ( CompilerBuild, compilerBuildSuffix ) +import Stack.Types.ComponentUtils + ( StackUnqualCompName, unqualCompToString ) import Stack.Types.DumpPackage ( DumpPackage ) import Stack.Types.UnusedFlags ( FlagSource (..), UnusedFlags (..) ) import Stack.Types.GHCVariant ( GHCVariant, ghcVariantSuffix ) @@ -41,6 +42,7 @@ import Stack.Types.Package ( Package (..), packageIdentifier ) import Stack.Types.ParentMap ( ParentMap ) import Stack.Types.Version ( VersionCheck (..), VersionRange ) +import Stack.Types.WantedCompilerSetter ( WantedCompilerSetter (..) ) -- | Type representing exceptions thrown by functions exported by modules with -- names beginning @Stack.Build@. @@ -54,7 +56,7 @@ (Path Abs File) -- stack.yaml | TestSuiteFailure PackageIdentifier - (Map Text (Maybe ExitCode)) + (Map StackUnqualCompName (Maybe ExitCode)) (Maybe (Path Abs File)) S.ByteString | TestSuiteTypeUnsupported TestSuiteInterface @@ -120,7 +122,7 @@ [ ["Test suite failure for package " ++ packageIdentifierString ident] , flip map (Map.toList codes) $ \(name, mcode) -> concat [ " " - , T.unpack name + , unqualCompToString name , ": " , case mcode of Nothing -> " executable not found" @@ -149,7 +151,7 @@ -- Suppressing duplicate output displayException (LocalPackageDoesn'tMatchTarget name localV requestedV) = concat [ "Error: [S-5797]\n" - , "Version for local package " + , "Version for project package " , packageNameString name , " is " , versionString localV @@ -224,7 +226,7 @@ data BuildPrettyException = ConstructPlanFailed [ConstructPlanException] - (Path Abs File) + (Either (Path Abs File) (Path Abs File)) (Path Abs Dir) Bool -- Is the project the implicit global project? ParentMap @@ -248,27 +250,27 @@ [Text] -- log contents | TargetParseException [StyleDoc] | SomeTargetsNotBuildable [(PackageName, NamedComponent)] - | InvalidFlagSpecification (Set UnusedFlags) + | InvalidFlagSpecification [UnusedFlags] | GHCProfOptionInvalid - | NotOnlyLocal [PackageName] [Text] + | NotOnlyLocal [PackageName] [StackUnqualCompName] | CompilerVersionMismatch (Maybe (ActualCompiler, Arch)) -- found (WantedCompiler, Arch) -- expected GHCVariant -- expected CompilerBuild -- expected VersionCheck - (Maybe (Path Abs File)) -- Path to the stack.yaml file + WantedCompilerSetter -- Way that the wanted compiler is set StyleDoc -- recommended resolution deriving (Show, Typeable) instance Pretty BuildPrettyException where - pretty ( ConstructPlanFailed errs stackYaml stackRoot isImplicitGlobal parents wanted prunedGlobalDeps ) = + pretty ( ConstructPlanFailed errs configFile stackRoot isImplicitGlobal parents wanted prunedGlobalDeps ) = "[S-4804]" <> line <> flow "Stack failed to construct a build plan." <> blankLine <> pprintExceptions - errs stackYaml stackRoot isImplicitGlobal parents wanted prunedGlobalDeps + errs configFile stackRoot isImplicitGlobal parents wanted prunedGlobalDeps pretty (ExecutionFailure es) = "[S-7282]" <> line @@ -310,7 +312,7 @@ <> line <> flow "Invalid flag specification:" <> line - <> bulletedList (map go (Set.toList unused)) + <> bulletedList (map go (L.sort unused)) where showFlagSrc :: FlagSource -> StyleDoc showFlagSrc FSCommandLine = flow "(specified on the command line)" @@ -387,10 +389,18 @@ fillSep ( "Executables:" : mkNarrativeList Nothing False - (map (fromString . T.unpack) exes :: [StyleDoc]) + (map (fromString . unqualCompToString) exes :: [StyleDoc]) ) <> line - pretty (CompilerVersionMismatch mactual (expected, eArch) ghcVariant ghcBuild check mstack resolution) = + pretty ( CompilerVersionMismatch + mactual + (expected, eArch) + ghcVariant + ghcBuild + check + wantedCompilerSetter + resolution + ) = "[S-6362]" <> line <> fillSep @@ -415,12 +425,25 @@ , parens ( fillSep [ flow "based on" - , case mstack of - Nothing -> flow "command line arguments" - Just stack -> fillSep - [ flow "resolver setting in" - , pretty stack + , case wantedCompilerSetter of + CompilerAtCommandLine -> fillSep + [ "the" + , style Shell "--compiler" + , "option" ] + SnapshotAtCommandLine -> fillSep + [ "the" + , style Shell "--snapshot" <> "," + , "or" + , style Shell "--resolver" <> "," + , "option" + ] + YamlConfiguration mConfigFile -> case mConfigFile of + Nothing -> flow "command line arguments" + Just configFile -> fillSep + [ flow "the configuration in" + , pretty configFile + ] ] ) <> "." @@ -456,21 +479,22 @@ , style Shell "my-package-0.1.2.3" <> ")," , flow "a package component (e.g." , style Shell "my-package:test:my-test-suite" <> ")," - , flow "or, failing that, a relative path to a directory that is a \ - \local package directory or a parent directory of one or more \ - \local package directories." + , flow "or, failing that, a relative path to a local directory for a \ + \package or a parent directory of one or more such directories." ] pprintExceptions :: [ConstructPlanException] - -> Path Abs File + -> Either (Path Abs File) (Path Abs File) + -- ^ The configuration file, which may be either (Left) a user-specific + -- global one or (Right) a project-level one. -> Path Abs Dir -> Bool -> ParentMap -> Set PackageName -> Map PackageName [PackageName] -> StyleDoc -pprintExceptions exceptions stackYaml stackRoot isImplicitGlobal parentMap wanted' prunedGlobalDeps = +pprintExceptions exceptions configFile stackRoot isImplicitGlobal parentMap wanted' prunedGlobalDeps = fillSep [ flow ( "While constructing the build plan, Stack encountered the \ @@ -517,20 +541,24 @@ then ["also"] else [ fillSep - $ [ "in" + $ [ "pass" + , style Shell "--allow-newer" <> "," + , flow "or, in" , pretty (defaultUserConfigPath stackRoot) , flow ( "(global configuration)" <> if isImplicitGlobal then "," else mempty ) ] - <> ( if isImplicitGlobal - then [] - else - [ "or" - , pretty stackYaml - , flow "(project-level configuration)," - ] + <> ( case configFile of + Left _ -> [] + Right projectConfigFile -> if isImplicitGlobal + then [] + else + [ "or" + , pretty projectConfigFile + , flow "(project-level configuration)," + ] ) <> [ "set" , style Shell (flow "allow-newer: true") @@ -553,14 +581,23 @@ ] ] | otherwise = - [ fillSep - [ style Recommendation (flow "Recommended action:") - , flow "try adding the following to your" - , style Shell "extra-deps" - , "in" - , pretty stackYaml - , "(project-level configuration):" - ] + [ fillSep + [ style Recommendation (flow "Recommended action:") + , flow "try adding the following to your" + , case configFile of + Left _ -> fillSep + [ style Shell "--extra-dep" + , flow "options of the" + , style Shell (flow "stack script") + , "command:" + ] + Right projectConfigFile -> fillSep + [ style Shell "extra-deps" + , "in" + , pretty projectConfigFile + , "(project-level configuration):" + ] + ] <> blankLine <> vsep (map pprintExtra (Map.toList extras)) ] @@ -740,12 +777,15 @@ , style Shell "build-tools" , "or" , style Shell "build-tool-depends" - , flow "(Cabal file)" - , flow "or an omission from the" - , style Shell "packages" - , flow "list in" - , pretty stackYaml - , flow "(project-level configuration).)" + , case configFile of + Left _ -> flow "(Cabal file)." + Right projectConfigFile -> fillSep + [ flow "(Cabal file) or an omission from the" + , style Shell "packages" + , flow "list in" + , pretty projectConfigFile + , flow "(project-level configuration).)" + ] ] | otherwise -> "" Just (laVer, _)
src/Stack/Types/BuildConfig.hs view
@@ -8,12 +8,13 @@ module Stack.Types.BuildConfig ( BuildConfig (..) , HasBuildConfig (..) - , stackYamlL - , projectRootL - , getProjectWorkDir + , configFileL + , configFileRootL + , getWorkDir , wantedCompilerVersionL ) where +import qualified Data.Either.Extra as EE import Path ( (</>), parent ) import RIO.Process ( HasProcessContext (..) ) import Stack.Prelude @@ -35,12 +36,14 @@ , smWanted :: !SMWanted , extraPackageDBs :: ![Path Abs Dir] -- ^ Extra package databases - , stackYaml :: !(Path Abs File) - -- ^ Location of the stack.yaml file. + , configFile :: !(Either (Path Abs File) (Path Abs File)) + -- ^ Either (Left) the location of the user-specific global configuration + -- file or, in most cases, (Right) the location of the project-level + -- coniguration file (stack.yaml, by default). -- - -- Note: if the STACK_YAML environment variable is used, this may be - -- different from projectRootL </> "stack.yaml" if a different file - -- name is used. + -- Note: if the STACK_YAML environment variable is used, the location of the + -- project-level configuration file may be different from + -- projectRootL </> "stack.yaml" if a different file name is used. , projectStorage :: !ProjectStorage -- ^ Database connection pool for project Stack database , curator :: !(Maybe Curator) @@ -85,19 +88,22 @@ buildConfigL = id {-# INLINE buildConfigL #-} -stackYamlL :: HasBuildConfig env => Lens' env (Path Abs File) -stackYamlL = buildConfigL . lens (.stackYaml) (\x y -> x { stackYaml = y }) +configFileL :: + HasBuildConfig env + => Lens' env (Either (Path Abs File) (Path Abs File)) +configFileL = buildConfigL . lens (.configFile) (\x y -> x { configFile = y }) --- | Directory containing the project's stack.yaml file -projectRootL :: HasBuildConfig env => Getting r env (Path Abs Dir) -projectRootL = stackYamlL . to parent +-- | Directory containing the configuration file. +configFileRootL :: HasBuildConfig env => Getting r env (Path Abs Dir) +configFileRootL = configFileL . to EE.fromEither . to parent --- | Per-project work dir -getProjectWorkDir :: (HasBuildConfig env, MonadReader env m) => m (Path Abs Dir) -getProjectWorkDir = do - root <- view projectRootL +-- | Work directory in the directory of the configuration file (global or +-- project-level). +getWorkDir :: (HasBuildConfig env, MonadReader env m) => m (Path Abs Dir) +getWorkDir = do + configFileRoot <- view configFileRootL workDir <- view workDirL - pure (root </> workDir) + pure (configFileRoot </> workDir) -- | The compiler specified by the @SnapshotDef@. This may be different from the -- actual compiler used!
src/Stack/Types/BuildOpts.hs view
@@ -16,6 +16,7 @@ import Stack.Prelude import Stack.Types.BuildOptsMonoid ( CabalVerbosity (..), ProgressBarFormat (..) ) +import Stack.Types.Component ( StackUnqualCompName ) -- | Build options that is interpreted by the build command. This is built up -- from BuildOptsCLI and BuildOptsMonoid @@ -32,6 +33,15 @@ -- ^ Open haddocks in the browser? , haddockDeps :: !(Maybe Bool) -- ^ Build haddocks for dependencies? + , haddockExecutables :: !Bool + -- ^ Also build Haddock documentation for all executable components, like + -- @runghc Setup.hs haddock --executables@. + , haddockTests :: !Bool + -- ^ Also build Haddock documentation for all test suite components, like + -- @runghc Setup.hs haddock --tests@. + , haddockBenchmarks :: !Bool + -- ^ Also build Haddock documentation for all benchmark components, like + -- @runghc Setup.hs haddock --benchmarks@. , haddockInternal :: !Bool -- ^ Build haddocks for all symbols and packages, like -- @cabal haddock --internal@ @@ -52,7 +62,8 @@ , keepTmpFiles :: !Bool -- ^ Keep intermediate files and build directories , forceDirty :: !Bool - -- ^ Force treating all local packages as having dirty files + -- ^ Force treating all project packages and local extra-deps as having + -- dirty files. , tests :: !Bool -- ^ Turn on tests for local targets , testOpts :: !TestOpts @@ -69,7 +80,7 @@ -- ^ Ask Cabal to be verbose in its builds , splitObjs :: !Bool -- ^ Whether to enable split-objs. - , skipComponents :: ![Text] + , skipComponents :: ![StackUnqualCompName] -- ^ Which components to skip when building , interleavedOutput :: !Bool -- ^ Should we use the interleaved GHC output when building
src/Stack/Types/BuildOptsCLI.hs view
@@ -19,13 +19,15 @@ import qualified Data.Text as T import Stack.Prelude --- | Build options that may only be specified from the CLI +-- | Build options that are specified from the CLI and not specified as +-- non-project specific configuration options under the build key. data BuildOptsCLI = BuildOptsCLI { targetsCLI :: ![Text] , dryrun :: !Bool , ghcOptions :: ![Text] , progsOptions :: ![(Text, [Text])] , flags :: !(Map ApplyCLIFlag (Map FlagName Bool)) + , allowNewer :: !(First Bool) , buildSubset :: !BuildSubset , fileWatch :: !FileWatchOpts , watchAll :: !Bool @@ -41,6 +43,7 @@ { targetsCLI = [] , dryrun = False , flags = Map.empty + , allowNewer = mempty , ghcOptions = [] , progsOptions = [] , buildSubset = BSAll
src/Stack/Types/BuildOptsMonoid.hs view
@@ -31,12 +31,17 @@ import Distribution.Verbosity ( Verbosity, normal, verbose ) import Generics.Deriving.Monoid ( mappenddefault, memptydefault ) import Stack.Prelude hiding ( trace ) +import Stack.Types.ComponentUtils ( StackUnqualCompName ) --- | Build options that may be specified in the stack.yaml or from the CLI +-- | Build options that may be specified as non-project specific configuration +-- options under the build key (with certain exceptions) or from the CLI. data BuildOptsMonoid = BuildOptsMonoid { trace :: !Any + -- ^ Cannot be specified under the build key , profile :: !Any + -- ^ Cannot be specified under the build key , noStrip :: !Any + -- ^ Cannot be specified under the build key , libProfile :: !FirstFalse , exeProfile :: !FirstFalse , libStrip :: !FirstTrue @@ -45,6 +50,9 @@ , haddockOpts :: !HaddockOptsMonoid , openHaddocks :: !FirstFalse , haddockDeps :: !(First Bool) + , haddockExecutables :: !FirstFalse + , haddockTests :: !FirstFalse + , haddockBenchmarks :: !FirstFalse , haddockInternal :: !FirstFalse , haddockHyperlinkSource :: !FirstTrue , haddockForHackage :: !FirstFalse @@ -61,7 +69,7 @@ , reconfigure :: !FirstFalse , cabalVerbose :: !(First CabalVerbosity) , splitObjs :: !FirstFalse - , skipComponents :: ![Text] + , skipComponents :: ![StackUnqualCompName] , interleavedOutput :: !FirstTrue , progressBar :: !(First ProgressBarFormat) , ddumpDir :: !(First Text) @@ -81,6 +89,9 @@ haddockOpts <- jsonSubWarnings (o ..:? haddockOptsArgName ..!= mempty) openHaddocks <- FirstFalse <$> o ..:? openHaddocksArgName haddockDeps <- First <$> o ..:? haddockDepsArgName + haddockExecutables <- FirstFalse <$> o ..:? haddockExecutablesArgName + haddockTests <- FirstFalse <$> o ..:? haddockTestsArgName + haddockBenchmarks <- FirstFalse <$> o ..:? haddockBenchmarksArgName haddockInternal <- FirstFalse <$> o ..:? haddockInternalArgName haddockHyperlinkSource <- FirstTrue <$> o ..:? haddockHyperlinkSourceArgName haddockForHackage <- FirstFalse <$> o ..:? haddockForHackageArgName @@ -115,6 +126,9 @@ , haddockOpts , openHaddocks , haddockDeps + , haddockExecutables + , haddockTests + , haddockBenchmarks , haddockInternal , haddockHyperlinkSource , haddockForHackage @@ -160,6 +174,15 @@ haddockDepsArgName :: Text haddockDepsArgName = "haddock-deps" + +haddockExecutablesArgName :: Text +haddockExecutablesArgName = "haddock-executables" + +haddockTestsArgName :: Text +haddockTestsArgName = "haddock-tests" + +haddockBenchmarksArgName :: Text +haddockBenchmarksArgName = "haddock-benchmarks" haddockInternalArgName :: Text haddockInternalArgName = "haddock-internal"
src/Stack/Types/Cache.hs view
@@ -12,7 +12,8 @@ , SqlType (..) ) import Stack.Prelude -import Stack.Types.GhcPkgId ( GhcPkgId, parseGhcPkgId, unGhcPkgId ) +import Stack.Types.GhcPkgId + ( GhcPkgId, ghcPkgIdToText, parseGhcPkgId ) -- | Type of config cache data ConfigCacheType @@ -24,7 +25,7 @@ instance PersistField ConfigCacheType where toPersistValue ConfigCacheTypeConfig = PersistText "config" toPersistValue (ConfigCacheTypeFlagLibrary v) = - PersistText $ "lib:" <> unGhcPkgId v + PersistText $ "lib:" <> ghcPkgIdToText v toPersistValue (ConfigCacheTypeFlagExecutable v) = PersistText $ "exe:" <> T.pack (packageIdentifierString v) fromPersistValue (PersistText t) =
src/Stack/Types/CompCollection.hs view
@@ -34,9 +34,9 @@ import qualified Data.Set as Set import Stack.Prelude import Stack.Types.Component - ( HasBuildInfo, HasName, StackBuildInfo (..) - , StackUnqualCompName (..) - ) + ( HasBuildInfo, HasName, StackBuildInfo (..) ) +import Stack.Types.ComponentUtils + ( StackUnqualCompName, unqualCompToText ) -- | A type representing collections of components, distinguishing buildable -- components and non-buildable components. @@ -116,12 +116,12 @@ -- | Get the names of the buildable components in the given collection, as a -- 'Set' of 'Text'. getBuildableSetText :: CompCollection component -> Set Text -getBuildableSetText = Set.mapMonotonic (.unqualCompToText) . getBuildableSet +getBuildableSetText = Set.mapMonotonic unqualCompToText . getBuildableSet -- | Get the names of the buildable components in the given collection, as a -- list of 'Text. getBuildableListText :: CompCollection component -> [Text] -getBuildableListText = getBuildableListAs (.unqualCompToText) +getBuildableListText = getBuildableListAs unqualCompToText -- | Apply the given function to the names of the buildable components in the -- given collection, yielding a list. @@ -142,25 +142,24 @@ -- components, yields 'Just' @component@ if the collection includes a buildable -- component of that name, and 'Nothing' otherwise. collectionLookup :: - Text + StackUnqualCompName -- ^ Name of the buildable component. -> CompCollection component -- ^ Collection of components. -> Maybe component -collectionLookup needle haystack = - M.lookup (StackUnqualCompName needle) haystack.buildableOnes +collectionLookup needle haystack = M.lookup needle haystack.buildableOnes -- | For a given collection of components, yields a list of pairs for buildable -- components of the name of the component and the component. -collectionKeyValueList :: CompCollection component -> [(Text, component)] -collectionKeyValueList haystack = - (\(StackUnqualCompName k, !v) -> (k, v)) - <$> M.toList haystack.buildableOnes +collectionKeyValueList :: + CompCollection component + -> [(StackUnqualCompName, component)] +collectionKeyValueList haystack = M.toList haystack.buildableOnes -- | Yields 'True' if, and only if, the given collection of components includes -- a buildable component with the given name. collectionMember :: - Text + StackUnqualCompName -- ^ Name of the buildable component. -> CompCollection component -- ^ Collection of components.
src/Stack/Types/CompilerBuild.hs view
@@ -11,6 +11,7 @@ import Data.Text as T import Stack.Prelude +-- | Build of the compiler distribution (e.g. standard, gmp4, tinfo6) data CompilerBuild = CompilerBuildStandard | CompilerBuildSpecialized String
src/Stack/Types/Component.hs view
@@ -34,7 +34,8 @@ import Distribution.Utils.Path ( PackageDir, SourceDir, SymbolicPath ) import GHC.Records ( HasField (..) ) import Stack.Prelude -import Stack.Types.ComponentUtils ( StackUnqualCompName (..) ) +import Stack.Types.ComponentUtils + ( StackUnqualCompName (..), emptyCompName ) import Stack.Types.Dependency ( DepValue ) import Stack.Types.NamedComponent ( NamedComponent (..) ) @@ -166,22 +167,22 @@ instance HasField "qualifiedName" StackLibrary NamedComponent where getField v - | rawName == mempty = CLib + | rawName == emptyCompName = CLib | otherwise = CSubLib rawName where - rawName = v.name.unqualCompToText + rawName = v.name instance HasField "qualifiedName" StackForeignLibrary NamedComponent where - getField = CFlib . (.name.unqualCompToText) + getField = CFlib . (.name) instance HasField "qualifiedName" StackExecutable NamedComponent where - getField = CExe . (.name.unqualCompToText) + getField = CExe . (.name) instance HasField "qualifiedName" StackTestSuite NamedComponent where - getField = CTest . (.name.unqualCompToText) + getField = CTest . (.name) instance HasField "qualifiedName" StackBenchmark NamedComponent where - getField = CTest . (.name.unqualCompToText) + getField = CBench . (.name) -- | Type synonym for a 'HasField' constraint which represent a virtual field, -- computed from the type, the NamedComponent constructor and the name.
src/Stack/Types/ComponentUtils.hs view
@@ -12,15 +12,22 @@ -- component and related helper functions. module Stack.Types.ComponentUtils ( StackUnqualCompName (..) + , unqualCompToText + , unqualCompFromText + , unqualCompToString + , unqualCompFromString + , emptyCompName , fromCabalName , toCabalName ) where +import Data.Aeson ( FromJSON (..) ) +import Data.Hashable ( Hashable (..) ) +import Distribution.Compat.Binary ( decode, encode ) import Distribution.PackageDescription ( UnqualComponentName, mkUnqualComponentName - , unUnqualComponentName + , unUnqualComponentName, unUnqualComponentNameST ) -import RIO.Text (pack, unpack) import Stack.Prelude -- | Type representing the name of an \'unqualified\' component (that is, the @@ -33,15 +40,29 @@ -- Ideally, we would use the Cabal-syntax type and not 'Text', to avoid -- unnecessary work, but there is no 'Hashable' instance for -- 'Distribution.Types.UnqualComponentName.UnqualComponentName' yet. -newtype StackUnqualCompName = StackUnqualCompName - { unqualCompToText :: Text - } - deriving (Data, Eq, Generic, Hashable, IsString, NFData, Ord, Read, Show, Typeable) +newtype StackUnqualCompName = StackUnqualCompName UnqualComponentName + deriving (Data, Eq, Generic, IsString, NFData, Ord, Read, Show, Typeable) +instance Hashable StackUnqualCompName where + hashWithSalt a v = hashWithSalt a (show v) + fromCabalName :: UnqualComponentName -> StackUnqualCompName -fromCabalName unqualName = - StackUnqualCompName $ pack . unUnqualComponentName $ unqualName +fromCabalName = StackUnqualCompName toCabalName :: StackUnqualCompName -> UnqualComponentName -toCabalName (StackUnqualCompName unqualName) = - mkUnqualComponentName (unpack unqualName) +toCabalName (StackUnqualCompName unqualName) = unqualName + +unqualCompToString :: StackUnqualCompName -> String +unqualCompToString = unUnqualComponentName . toCabalName +unqualCompFromString :: String -> StackUnqualCompName +unqualCompFromString = StackUnqualCompName . mkUnqualComponentName +unqualCompToText :: StackUnqualCompName -> Text +unqualCompToText = (decode . encode) . unUnqualComponentNameST . toCabalName +unqualCompFromText :: Text -> StackUnqualCompName +unqualCompFromText = StackUnqualCompName . decode . encode + +emptyCompName :: StackUnqualCompName +emptyCompName = StackUnqualCompName $ mkUnqualComponentName "" + +instance FromJSON StackUnqualCompName where + parseJSON = fmap (StackUnqualCompName . decode . encode) <$> parseJSON @Text
src/Stack/Types/Config.hs view
@@ -21,7 +21,7 @@ , buildOptsL , envOverrideSettingsL , globalOptsL - , stackGlobalConfigL + , userGlobalConfigFileL , stackRootL , workDirL -- * Helper logging functions @@ -43,15 +43,16 @@ import Stack.Types.DumpLogs ( DumpLogs ) import Stack.Types.EnvSettings ( EnvSettings ) import Stack.Types.GHCVariant ( GHCVariant (..), HasGHCVariant (..) ) +import Stack.Types.MsysEnvironment ( MsysEnvironment ) import Stack.Types.Nix ( NixOpts ) import Stack.Types.Platform ( HasPlatform (..), PlatformVariant ) import Stack.Types.Project ( Project (..) ) import Stack.Types.ProjectConfig ( ProjectConfig (..) ) import Stack.Types.PvpBounds ( PvpBounds ) -import Stack.Types.Resolver ( AbstractResolver ) import Stack.Types.Runner ( HasRunner (..), Runner, globalOptsL ) import Stack.Types.SCM ( SCM ) import Stack.Types.SetupInfo ( SetupInfo ) +import Stack.Types.Snapshot ( AbstractSnapshot ) import Stack.Types.Storage ( UserStorage ) import Stack.Types.TemplateName ( TemplateName ) import Stack.Types.Version ( VersionCheck (..), VersionRange ) @@ -60,8 +61,8 @@ data Config = Config { workDir :: !(Path Rel Dir) -- ^ this allows to override .stack-work directory - , userConfigPath :: !(Path Abs File) - -- ^ Path to user configuration file (usually ~/.stack/config.yaml) + , userGlobalConfigFile :: !(Path Abs File) + -- ^ The user-specific global configuration file. , build :: !BuildOpts -- ^ Build configuration , docker :: !DockerOpts @@ -100,12 +101,18 @@ -- ^ Don't bother checking the GHC version or architecture. , skipMsys :: !Bool -- ^ On Windows: don't use a sandboxed MSYS + , msysEnvironment :: !(Maybe MsysEnvironment) + -- ^ On Windows: what MSYS2 environment to apply. Nothing on other operating + -- systems. , compilerCheck :: !VersionCheck -- ^ Specifies which versions of the compiler are acceptable. , compilerRepository :: !CompilerRepository -- ^ Specifies the repository containing the compiler sources , localBin :: !(Path Abs Dir) -- ^ Directory we should install executables into + , fileWatchHook :: !(Maybe (Path Abs File)) + -- ^ Optional path of executable used to override --file-watch + -- post-processing. , requireStackVersion :: !VersionRange -- ^ Require a version of Stack within this range. , jobs :: !Int @@ -146,12 +153,15 @@ , applyProgOptions :: !ApplyProgOptions -- ^ Which packages do all and any --PROG-option options on the command line -- apply to? - , allowNewer :: !Bool + , allowNewer :: !(First Bool) -- ^ Ignore version ranges in .cabal files. Funny naming chosen to -- match cabal. , allowNewerDeps :: !(Maybe [PackageName]) -- ^ Ignore dependency upper and lower bounds only for specified -- packages. No effect unless allow-newer is enabled. + , defaultInitSnapshot :: !(First AbstractSnapshot) + -- ^ An optional default snapshot to use with @stack init@ when none is + -- specified at the command line. , defaultTemplate :: !(Maybe TemplateName) -- ^ The default template to use when none is specified. -- (If Nothing, the 'default' default template is used.) @@ -165,20 +175,20 @@ , allowLocals :: !Bool -- ^ Are we allowed to build local packages? The script -- command disallows this. - , saveHackageCreds :: !Bool + , saveHackageCreds :: !FirstTrue -- ^ Should we save Hackage credentials to a file? , hackageBaseUrl :: !Text -- ^ Hackage base URL used when uploading packages , runner :: !Runner , pantryConfig :: !PantryConfig , stackRoot :: !(Path Abs Dir) - , resolver :: !(Maybe AbstractResolver) - -- ^ Any resolver override from the command line + , snapshot :: !(Maybe AbstractSnapshot) + -- ^ Any snapshot override from the command line , userStorage :: !UserStorage -- ^ Database connection pool for user Stack database , hideSourcePaths :: !Bool -- ^ Enable GHC hiding source paths? - , recommendUpgrade :: !Bool + , recommendStackUpgrade :: !Bool -- ^ Recommend a Stack upgrade? , notifyIfNixOnPath :: !Bool -- ^ Notify if the Nix package manager (nix) is on the PATH, but @@ -281,10 +291,10 @@ stackRootL = configL . lens (.stackRoot) (\x y -> x { stackRoot = y }) -stackGlobalConfigL :: HasConfig s => Lens' s (Path Abs File) -stackGlobalConfigL = configL . lens - (.userConfigPath) - (\x y -> x { userConfigPath = y }) +userGlobalConfigFileL :: HasConfig s => Lens' s (Path Abs File) +userGlobalConfigFileL = configL . lens + (.userGlobalConfigFile) + (\x y -> x { userGlobalConfigFile = y }) buildOptsL :: HasConfig s => Lens' s BuildOpts buildOptsL = configL . lens (.build) (\x y -> x { build = y })
src/Stack/Types/Config/Exception.hs view
@@ -8,18 +8,19 @@ ( ConfigException (..) , ConfigPrettyException (..) , ParseAbsolutePathException (..) - , packageIndicesWarning ) where import qualified Data.Text as T import Data.Yaml ( ParseException ) import qualified Data.Yaml as Yaml +import Distribution.System ( Arch ) import Path( dirname, filename ) import Stack.Prelude import Stack.Types.ConfigMonoid ( configMonoidAllowDifferentUserName , configMonoidGHCVariantName, configMonoidSystemGHCName ) +import Stack.Types.MsysEnvironment ( MsysEnvironment ) import Stack.Types.Version ( VersionRange, stackVersion, versionRangeText ) @@ -32,6 +33,7 @@ | UnableToExtractArchive Text (Path Abs File) | BadStackVersionException VersionRange | NoSuchDirectory FilePath + | NoSuchFile FilePath | ParseGHCVariantException String | BadStackRoot (Path Abs Dir) | Won'tCreateStackRootInDirectoryOwnedByDifferentUser @@ -41,7 +43,7 @@ | UserDoesn'tOwnDirectory (Path Abs Dir) | ManualGHCVariantSettingsAreIncompatibleWithSystemGHC | NixRequiresSystemGhc - | NoResolverWhenUsingNoProject + | NoSnapshotWhenUsingNoProject | NoLTSWithMajorVersion Int | NoLTSFound deriving (Show, Typeable) @@ -96,6 +98,11 @@ , "No directory could be located matching the supplied path: " , dir ] + displayException (NoSuchFile file) = concat + [ "Error: [S-4335]\n" + , "No file could be located matching the supplied path: " + , file + ] displayException (ParseGHCVariantException v) = concat [ "Error: [S-3938]\n" , "Invalid ghc-variant value: " @@ -139,9 +146,9 @@ , configMonoidSystemGHCName , "' or disable the Nix integration." ] - displayException NoResolverWhenUsingNoProject = + displayException NoSnapshotWhenUsingNoProject = "Error: [S-5027]\n" - ++ "When using the script command, you must provide a resolver argument" + ++ "When using the script command, you must provide a snapshot argument" displayException (NoLTSWithMajorVersion n) = concat [ "Error: [S-3803]\n" , "No LTS release found with major version " @@ -157,8 +164,10 @@ data ConfigPrettyException = ParseConfigFileException !(Path Abs File) !ParseException | StackWorkEnvNotRelativeDir !String - | MultiplePackageIndices [PackageIndexConfig] | DuplicateLocalPackageNames ![(PackageName, [PackageLocation])] + | BadMsysEnvironment !MsysEnvironment !Arch + | NoMsysEnvironmentBug + | ConfigFileNotProjectLevelBug deriving (Show, Typeable) instance Pretty ConfigPrettyException where @@ -198,25 +207,14 @@ \of the project or package. Stack encountered the value:" , style Error (fromString x) <> "." ] - pretty (MultiplePackageIndices pics) = - "[S-3251]" - <> line - <> fillSep - [ flow "When using the" - , style Shell "package-indices" - , flow "key to override the default package index, you must \ - \provide exactly one value, received:" - , bulletedList (map (string . show) pics) - ] - <> blankLine - <> packageIndicesWarning pretty (DuplicateLocalPackageNames pairs) = "[S-5470]" <> line <> fillSep - [ flow "The same package name is used in more than one local package or" - , style Shell "extra-deps" <> "." - ] + [ flow "The same package name is used in more than one project \ + \package or" + , style Shell "extra-deps" <> "." + ] <> mconcat (map go pairs) where go (name, dirs) = @@ -227,6 +225,19 @@ ] <> line <> bulletedList (map (fromString . T.unpack . textDisplay) dirs) + pretty (BadMsysEnvironment msysEnv arch) = + "[S-6854]" + <> line + <> fillSep + [ flow "The specified MSYS2 environment" + , style Error (fromString $ show msysEnv) + , flow "is not consistent with the architecture" + , fromString (show arch) <> "." + ] + pretty NoMsysEnvironmentBug = bugPrettyReport "[S-5006]" $ + flow "No default MSYS2 environment." + pretty ConfigFileNotProjectLevelBug = bugPrettyReport "[S-8398]" $ + flow "The configuration file is not a project-level one." instance Exception ConfigPrettyException @@ -241,13 +252,4 @@ , envVar , " environment variable (expected absolute directory): " , dir - ] - -packageIndicesWarning :: StyleDoc -packageIndicesWarning = - fillSep - [ "The" - , style Shell "package-indices" - , flow "key is deprecated in favour of" - , style Shell "package-index" <> "." ]
src/Stack/Types/ConfigMonoid.hs view
@@ -11,14 +11,14 @@ , configMonoidAllowDifferentUserName , configMonoidGHCVariantName , configMonoidInstallGHCName + , configMonoidRecommendStackUpgradeName , configMonoidSystemGHCName ) where import Data.Aeson.Types ( Object, Value ) import Data.Aeson.WarningParser ( WarningParser, WithJSONWarnings, (..:?), (..!=) - , jsonSubWarnings, jsonSubWarningsT, jsonSubWarningsTT - , withObjectWarnings + , jsonSubWarnings, jsonSubWarningsT, withObjectWarnings ) import Casa.Client ( CasaRepoPrefix ) import Control.Monad.Writer ( tell ) @@ -45,6 +45,7 @@ import Stack.Types.GhcOptionKey ( GhcOptionKey (..) ) import Stack.Types.GhcOptions ( GhcOptions (..) ) import Stack.Types.GHCVariant ( GHCVariant ) +import Stack.Types.MsysEnvironment ( MsysEnvironment ) import Stack.Types.Nix ( NixOptsMonoid ) import Stack.Types.PvpBounds ( PvpBounds ) import Stack.Types.SCM ( SCM ) @@ -53,9 +54,10 @@ import Stack.Types.Version ( IntersectingVersionRange (..), VersionCheck ) import qualified System.FilePath as FilePath +import Stack.Types.Snapshot (AbstractSnapshot) --- | An uninterpreted representation of configuration options. --- Configurations may be "cascaded" using mappend (left-biased). +-- | An uninterpreted representation of configuration options. Configurations +-- may be "cascaded" using mappend (left-biased). data ConfigMonoid = ConfigMonoid { stackRoot :: !(First (Path Abs Dir)) -- ^ See: 'clStackRoot' @@ -77,8 +79,6 @@ -- ^ See: 'configLatestSnapshot' , packageIndex :: !(First PackageIndexConfig) -- ^ See: 'withPantryConfig' - , packageIndices :: !(First [PackageIndexConfig]) - -- ^ Deprecated in favour of package-index , systemGHC :: !(First Bool) -- ^ See: 'configSystemGHC' , installGHC :: !FirstTrue @@ -87,6 +87,8 @@ -- ^ See: 'configSkipGHCCheck' , skipMsys :: !FirstFalse -- ^ See: 'configSkipMsys' + , msysEnvironment :: !(First MsysEnvironment) + -- ^ See: 'configMsysEnvironment' , compilerCheck :: !(First VersionCheck) -- ^ See: 'configCompilerCheck' , compilerRepository :: !(First CompilerRepository) @@ -107,14 +109,18 @@ -- ^ See: 'configExtraLibDirs' , customPreprocessorExts :: ![Text] -- ^ See: 'configCustomPreprocessorExts' - , overrideGccPath :: !(First (Path Abs File)) + , overrideGccPath :: !(First (Path Abs File)) -- ^ Allow users to override the path to gcc , overrideHpack :: !(First FilePath) -- ^ Use Hpack executable (overrides bundled Hpack) + , hpackForce :: !FirstFalse + -- ^ Pass --force to Hpack to always overwrite Cabal file , concurrentTests :: !(First Bool) -- ^ See: 'configConcurrentTests' , localBinPath :: !(First FilePath) -- ^ Used to override the binary installation dir + , fileWatchHook :: !(First FilePath) + -- ^ Path to executable used to override --file-watch post-processing. , templateParameters :: !(Map Text Text) -- ^ Template parameters. , scmInit :: !(First SCM) @@ -151,6 +157,9 @@ -- ^ See 'configMonoidAllowNewer' , allowNewerDeps :: !(Maybe AllowNewerDeps) -- ^ See 'configMonoidAllowNewerDeps' + , defaultInitSnapshot :: !(First (Unresolved AbstractSnapshot)) + -- ^ An optional default snapshot to use with @stack init@ when none is + -- specified. , defaultTemplate :: !(First TemplateName) -- ^ The default template to use when none is specified. -- (If Nothing, the 'default' default template is used.) @@ -159,7 +168,7 @@ -- installation. , dumpLogs :: !(First DumpLogs) -- ^ See 'configDumpLogs' - , saveHackageCreds :: !(First Bool) + , saveHackageCreds :: !FirstTrue -- ^ See 'configSaveHackageCreds' , hackageBaseUrl :: !(First Text) -- ^ See 'configHackageBaseUrl' @@ -168,8 +177,8 @@ , styles :: !StylesUpdate , hideSourcePaths :: !FirstTrue -- ^ See 'configHideSourcePaths' - , recommendUpgrade :: !FirstTrue - -- ^ See 'configRecommendUpgrade' + , recommendStackUpgrade :: !FirstTrue + -- ^ See 'configRecommendStackUpgrade' , notifyIfNixOnPath :: !FirstTrue -- ^ See 'configNotifyIfNixOnPath' , notifyIfGhcUntested :: !FirstTrue @@ -184,12 +193,14 @@ -- ^ Casa repository prefix (deprecated). , snapshotLocation :: !(First Text) -- ^ Custom location of LTS/Nightly snapshots + , globalHintsLocation :: !(First (Unresolved GlobalHintsLocation)) + -- ^ Custom location of global hints , noRunCompile :: !FirstFalse -- ^ See: 'configNoRunCompile' , stackDeveloperMode :: !(First Bool) -- ^ See 'configStackDeveloperMode' } - deriving (Generic, Show) + deriving Generic instance Semigroup ConfigMonoid where (<>) = mappenddefault @@ -231,12 +242,11 @@ packageIndex <- First <$> jsonSubWarningsT (obj ..:? configMonoidPackageIndexName) - packageIndices <- - First <$> jsonSubWarningsTT (obj ..:? configMonoidPackageIndicesName) systemGHC <- First <$> obj ..:? configMonoidSystemGHCName installGHC <- FirstTrue <$> obj ..:? configMonoidInstallGHCName skipGHCCheck <- FirstFalse <$> obj ..:? configMonoidSkipGHCCheckName skipMsys <- FirstFalse <$> obj ..:? configMonoidSkipMsysName + msysEnvironment <- First <$> obj ..:? configMonoidMsysEnvironmentName requireStackVersion <- IntersectingVersionRange . (.versionRangeJSON) <$> ( obj ..:? configMonoidRequireStackVersionName @@ -254,8 +264,10 @@ obj ..:? configMonoidCustomPreprocessorExtsName ..!= [] overrideGccPath <- First <$> obj ..:? configMonoidOverrideGccPathName overrideHpack <- First <$> obj ..:? configMonoidOverrideHpackName + hpackForce <- FirstFalse <$> obj ..:? configMonoidHpackForceName concurrentTests <- First <$> obj ..:? configMonoidConcurrentTestsName localBinPath <- First <$> obj ..:? configMonoidLocalBinPathName + fileWatchHook <- First <$> obj ..:? configMonoidFileWatchHookName templates <- obj ..:? "templates" (scmInit, templateParameters) <- case templates of @@ -304,10 +316,11 @@ applyProgOptions <- First <$> obj ..:? configMonoidApplyProgOptionsName allowNewer <- First <$> obj ..:? configMonoidAllowNewerName allowNewerDeps <- obj ..:? configMonoidAllowNewerDepsName + defaultInitSnapshot <- First <$> obj ..:? configMonoidDefaultInitSnapshotName defaultTemplate <- First <$> obj ..:? configMonoidDefaultTemplateName allowDifferentUser <- First <$> obj ..:? configMonoidAllowDifferentUserName dumpLogs <- First <$> obj ..:? configMonoidDumpLogsName - saveHackageCreds <- First <$> obj ..:? configMonoidSaveHackageCredsName + saveHackageCreds <- FirstTrue <$> obj ..:? configMonoidSaveHackageCredsName hackageBaseUrl <- First <$> obj ..:? configMonoidHackageBaseUrlName configMonoidColorWhenUS <- obj ..:? configMonoidColorWhenUSName configMonoidColorWhenGB <- obj ..:? configMonoidColorWhenGBName @@ -316,7 +329,8 @@ configMonoidStylesGB <- obj ..:? configMonoidStylesGBName let styles = fromMaybe mempty $ configMonoidStylesUS <|> configMonoidStylesGB hideSourcePaths <- FirstTrue <$> obj ..:? configMonoidHideSourcePathsName - recommendUpgrade <- FirstTrue <$> obj ..:? configMonoidRecommendUpgradeName + recommendStackUpgrade <- + FirstTrue <$> obj ..:? configMonoidRecommendStackUpgradeName notifyIfNixOnPath <- FirstTrue <$> obj ..:? configMonoidNotifyIfNixOnPathName notifyIfGhcUntested <- FirstTrue <$> obj ..:? configMonoidNotifyIfGhcUntestedName @@ -327,6 +341,8 @@ casaOpts <- jsonSubWarnings (obj ..:? configMonoidCasaOptsName ..!= mempty) casaRepoPrefix <- First <$> obj ..:? configMonoidCasaRepoPrefixName snapshotLocation <- First <$> obj ..:? configMonoidSnapshotLocationName + globalHintsLocation <- + First <$> jsonSubWarningsT (obj ..:? configMonoidGlobalHintsLocationName) noRunCompile <- FirstFalse <$> obj ..:? configMonoidNoRunCompileName stackDeveloperMode <- First <$> obj ..:? configMonoidStackDeveloperModeName pure ConfigMonoid @@ -340,11 +356,11 @@ , prefixTimestamps , latestSnapshot , packageIndex - , packageIndices , systemGHC , installGHC , skipGHCCheck , skipMsys + , msysEnvironment , compilerCheck , compilerRepository , requireStackVersion @@ -357,8 +373,10 @@ , customPreprocessorExts , overrideGccPath , overrideHpack + , hpackForce , concurrentTests , localBinPath + , fileWatchHook , templateParameters , scmInit , ghcOptionsByName @@ -375,6 +393,7 @@ , applyProgOptions , allowNewer , allowNewerDeps + , defaultInitSnapshot , defaultTemplate , allowDifferentUser , dumpLogs @@ -383,7 +402,7 @@ , colorWhen , styles , hideSourcePaths - , recommendUpgrade + , recommendStackUpgrade , notifyIfNixOnPath , notifyIfGhcUntested , notifyIfCabalUntested @@ -391,6 +410,7 @@ , casaOpts , casaRepoPrefix , snapshotLocation + , globalHintsLocation , noRunCompile , stackDeveloperMode } @@ -425,10 +445,6 @@ configMonoidPackageIndexName :: Text configMonoidPackageIndexName = "package-index" --- Deprecated in favour of package-index -configMonoidPackageIndicesName :: Text -configMonoidPackageIndicesName = "package-indices" - configMonoidSystemGHCName :: Text configMonoidSystemGHCName = "system-ghc" @@ -441,6 +457,9 @@ configMonoidSkipMsysName :: Text configMonoidSkipMsysName = "skip-msys" +configMonoidMsysEnvironmentName :: Text +configMonoidMsysEnvironmentName = "msys-environment" + configMonoidRequireStackVersionName :: Text configMonoidRequireStackVersionName = "require-stack-version" @@ -471,12 +490,18 @@ configMonoidOverrideHpackName :: Text configMonoidOverrideHpackName = "with-hpack" +configMonoidHpackForceName :: Text +configMonoidHpackForceName = "hpack-force" + configMonoidConcurrentTestsName :: Text configMonoidConcurrentTestsName = "concurrent-tests" configMonoidLocalBinPathName :: Text configMonoidLocalBinPathName = "local-bin-path" +configMonoidFileWatchHookName :: Text +configMonoidFileWatchHookName = "file-watch-hook" + configMonoidScmInitName :: Text configMonoidScmInitName = "scm-init" @@ -525,6 +550,9 @@ configMonoidAllowNewerDepsName :: Text configMonoidAllowNewerDepsName = "allow-newer-deps" +configMonoidDefaultInitSnapshotName :: Text +configMonoidDefaultInitSnapshotName = "default-init-snapshot" + configMonoidDefaultTemplateName :: Text configMonoidDefaultTemplateName = "default-template" @@ -555,8 +583,8 @@ configMonoidHideSourcePathsName :: Text configMonoidHideSourcePathsName = "hide-source-paths" -configMonoidRecommendUpgradeName :: Text -configMonoidRecommendUpgradeName = "recommend-stack-upgrade" +configMonoidRecommendStackUpgradeName :: Text +configMonoidRecommendStackUpgradeName = "recommend-stack-upgrade" configMonoidNotifyIfNixOnPathName :: Text configMonoidNotifyIfNixOnPathName = "notify-if-nix-on-path" @@ -578,6 +606,9 @@ configMonoidSnapshotLocationName :: Text configMonoidSnapshotLocationName = "snapshot-location-base" + +configMonoidGlobalHintsLocationName :: Text +configMonoidGlobalHintsLocationName = "global-hints-location" configMonoidNoRunCompileName :: Text configMonoidNoRunCompileName = "script-no-run-compile"
src/Stack/Types/ConfigureOpts.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE DataKinds #-} {-# LANGUAGE NoFieldSelectors #-} {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE OverloadedStrings #-} @@ -6,19 +7,23 @@ module Stack.Types.ConfigureOpts ( ConfigureOpts (..) , BaseConfigOpts (..) + , PackageConfigureOpts (..) , configureOpts - , configureOptsPathRelated - , configureOptsNonPathRelated + , configureOptsFromDb + , renderConfigureOpts + , packageConfigureOptsFromPackage ) where import qualified Data.Map as Map import qualified Data.Text as T +import Database.Persist ( Entity, entityVal ) import Distribution.Types.MungedPackageName ( decodeCompatPackageName ) import Distribution.Types.PackageName ( unPackageName ) import Distribution.Types.UnqualComponentName ( unUnqualComponentName ) import qualified Distribution.Version as C +import GHC.Records ( HasField ) import Path ( (</>), parseRelDir ) import Path.Extra ( toFilePathNoTrailingSep ) import Stack.Constants @@ -29,12 +34,11 @@ import Stack.Types.BuildOpts ( BuildOpts (..) ) import Stack.Types.BuildOptsCLI ( BuildOptsCLI ) import Stack.Types.Compiler ( getGhcVersion, whichCompiler ) -import Stack.Types.Config - ( Config (..), HasConfig (..) ) +import Stack.Types.Config ( Config (..), HasConfig (..) ) import Stack.Types.EnvConfig ( EnvConfig, actualCompilerVersionL ) import Stack.Types.GhcPkgId ( GhcPkgId, ghcPkgIdString ) import Stack.Types.IsMutable ( IsMutable (..) ) -import Stack.Types.Package ( Package (..) ) +import Stack.Types.Package ( Package(..), packageIdentifier ) import System.FilePath ( pathSeparator ) -- | Basic information used to calculate what the configure options are @@ -49,6 +53,40 @@ } deriving Show +-- | All these fields come from the 'Package' data type but bringing the whole +-- Package is way too much, hence this datatype. +data PackageConfigureOpts = PackageConfigureOpts + { pkgCabalConfigOpts :: [Text] + , pkgGhcOptions :: [Text] + , pkgFlags :: Map FlagName Bool + , pkgDefaultFlags :: Map FlagName Bool + , pkgIdentifier :: PackageIdentifier + } + deriving Show + +packageConfigureOptsFromPackage :: + Package + -> PackageConfigureOpts +packageConfigureOptsFromPackage pkg = PackageConfigureOpts + { pkgCabalConfigOpts = pkg.cabalConfigOpts + , pkgGhcOptions = pkg.ghcOptions + , pkgFlags = pkg.flags + , pkgDefaultFlags = pkg.defaultFlags + , pkgIdentifier = packageIdentifier pkg + } + +configureOptsFromDb :: + ( HasField "configCacheDirOptionValue" b1 String + , HasField "configCacheNoDirOptionValue" b2 String + ) + => [Entity b1] + -> [Entity b2] + -> ConfigureOpts +configureOptsFromDb x y = ConfigureOpts + { pathRelated = map ((.configCacheDirOptionValue) . entityVal) x + , nonPathRelated = map ((.configCacheNoDirOptionValue) . entityVal) y + } + -- | Render a @BaseConfigOpts@ to an actual list of options configureOpts :: EnvConfig @@ -56,20 +94,20 @@ -> Map PackageIdentifier GhcPkgId -- ^ dependencies -> Bool -- ^ local non-extra-dep? -> IsMutable - -> Package + -> PackageConfigureOpts -> ConfigureOpts -configureOpts econfig bco deps isLocal isMutable package = ConfigureOpts - { pathRelated = configureOptsPathRelated bco isMutable package +configureOpts econfig bco deps isLocal isMutable pkgConfigureOpts = ConfigureOpts + { pathRelated = configureOptsPathRelated bco isMutable pkgConfigureOpts , nonPathRelated = - configureOptsNonPathRelated econfig bco deps isLocal package + configureOptsNonPathRelated econfig bco deps isLocal pkgConfigureOpts } configureOptsPathRelated :: BaseConfigOpts -> IsMutable - -> Package + -> PackageConfigureOpts -> [String] -configureOptsPathRelated bco isMutable package = concat +configureOptsPathRelated bco isMutable pkgOpts = concat [ ["--user", "--package-db=clear", "--package-db=global"] , map (("--package-db=" ++) . toFilePathNoTrailingSep) $ case isMutable of Immutable -> bco.extraDBs ++ [bco.snapDB] @@ -93,8 +131,7 @@ Nothing -> installRoot </> docDirSuffix Just dir -> installRoot </> docDirSuffix </> dir pkgVerDir = parseRelDir - ( packageIdentifierString - (PackageIdentifier package.name package.version) + ( packageIdentifierString pkgOpts.pkgIdentifier ++ [pathSeparator] ) @@ -104,7 +141,7 @@ -> BaseConfigOpts -> Map PackageIdentifier GhcPkgId -- ^ Dependencies. -> Bool -- ^ Is this a local, non-extra-dep? - -> Package + -> PackageConfigureOpts -> [String] configureOptsNonPathRelated econfig bco deps isLocal package = concat [ depOptions @@ -117,15 +154,9 @@ | not $ bopts.libStrip || bopts.exeStrip ] , ["--disable-executable-stripping" | not bopts.exeStrip && isLocal] - , map (\(name,enabled) -> - "-f" <> - (if enabled - then "" - else "-") <> - flagNameString name) - (Map.toList flags) - , map T.unpack package.cabalConfigOpts - , processGhcOptions package.ghcOptions + , flags + , map T.unpack package.pkgCabalConfigOpts + , processGhcOptions package.pkgGhcOptions , map ("--extra-include-dirs=" ++) config.extraIncludeDirs , map ("--extra-lib-dirs=" ++) config.extraLibDirs , maybe @@ -174,14 +205,21 @@ config = view configL econfig bopts = bco.buildOpts - + mapAndAppend fn = Map.foldrWithKey' (fmap (:) . fn) -- Unioning atop defaults is needed so that all flags are specified with -- --exact-configuration. - flags = package.flags `Map.union` package.defaultFlags + flags = mapAndAppend + renderFlags + [] + (package.pkgFlags `Map.union` package.pkgDefaultFlags) + renderFlags name enabled = + "-f" + <> (if enabled then "" else "-") + <> flagNameString name - depOptions = map toDepOption $ Map.toList deps + depOptions = mapAndAppend toDepOption [] deps - toDepOption (PackageIdentifier name _, gid) = concat + toDepOption (PackageIdentifier name _) gid = concat [ "--dependency=" , depOptionKey , "=" @@ -206,3 +244,7 @@ deriving (Data, Eq, Generic, Show, Typeable) instance NFData ConfigureOpts + +-- | Render configure options as a single list of options. +renderConfigureOpts :: ConfigureOpts -> [String] +renderConfigureOpts copts = copts.pathRelated ++ copts.nonPathRelated
src/Stack/Types/Dependency.hs view
@@ -12,6 +12,7 @@ , libraryDepFromVersionRange , isDepTypeLibrary , getDepSublib + , depValueToTarget ) where import qualified Data.Map as Map @@ -21,6 +22,8 @@ import Stack.Prelude import Stack.Types.ComponentUtils ( StackUnqualCompName (..), fromCabalName ) +import Stack.Types.NamedComponent ( NamedComponent(..) ) +import Stack.Types.SourceMap ( PackageType (..), Target (..) ) -- | The value for a map from dependency name. This contains both the version -- range and the type of dependency. @@ -82,3 +85,12 @@ { versionRange = range , depType = AsLibrary defaultDepLibrary } + +depValueToTarget :: DepValue -> Target +depValueToTarget dv = case dv.depType of + AsLibrary dlib -> TargetComps (completeSet dlib) + AsBuildTool -> TargetAll PTDependency + where + completeSet dlib = + (if dlib.main then Set.insert CLib else id) $ sublibSet dlib + sublibSet dlib = Set.mapMonotonic CSubLib dlib.subLib
src/Stack/Types/Docker.hs view
@@ -149,7 +149,7 @@ [ "Error: [S-6092]\n" , "Could not pull Docker image:\n " , image - , "\nThere may not be an image on the registry for your resolver's LTS \ + , "\nThere may not be an image on the registry for your snapshot's LTS \ \version in\n" , "your configuration file." ]
src/Stack/Types/DownloadInfo.hs view
@@ -14,7 +14,6 @@ ) import Stack.Prelude --- | Build of the compiler distribution (e.g. standard, gmp4, tinfo6) -- | Information for a file to download. data DownloadInfo = DownloadInfo { url :: Text
src/Stack/Types/EnvConfig.hs view
@@ -40,13 +40,13 @@ ) import RIO.Process ( HasProcessContext (..) ) import Stack.Constants - ( bindirSuffix, ghcColorForceFlag, osIsWindows, relDirCompilerTools - , relDirHoogle, relDirHpc, relDirInstall, relDirPkgdb - , relDirSnapshots, relFileDatabaseHoo + ( bindirSuffix, ghcColorForceFlag, osIsWindows + , relDirCompilerTools, relDirHoogle, relDirHpc, relDirInstall + , relDirPkgdb, relDirSnapshots, relFileDatabaseHoo ) import Stack.Prelude import Stack.Types.BuildConfig - ( BuildConfig (..), HasBuildConfig (..), getProjectWorkDir ) + ( BuildConfig (..), HasBuildConfig (..), getWorkDir ) import Stack.Types.BuildOptsCLI ( BuildOptsCLI ) import Stack.Types.Compiler ( ActualCompiler (..), compilerVersionString, getGhcVersion ) @@ -163,7 +163,7 @@ -- | Installation root for locals installationRootLocal :: HasEnvConfig env => RIO env (Path Abs Dir) installationRootLocal = do - workDir <- getProjectWorkDir + workDir <- getWorkDir psc <- useShaPathOnWindows =<< platformSnapAndCompilerRel pure $ workDir </> relDirInstall </> psc @@ -212,7 +212,7 @@ -- | Hoogle directory. hoogleRoot :: HasEnvConfig env => RIO env (Path Abs Dir) hoogleRoot = do - workDir <- getProjectWorkDir + workDir <- getWorkDir psc <- useShaPathOnWindows =<< platformSnapAndCompilerRel pure $ workDir </> relDirHoogle </> psc @@ -231,7 +231,7 @@ root <- installationRootDeps pure $ root </> relDirPkgdb --- | Package database for installing local packages into +-- | Package database for installing project packages and local extra-deps into. packageDatabaseLocal :: HasEnvConfig env => RIO env (Path Abs Dir) packageDatabaseLocal = do root <- installationRootLocal
src/Stack/Types/EnvSettings.hs view
@@ -13,7 +13,7 @@ -- | Controls which version of the environment is used data EnvSettings = EnvSettings { includeLocals :: !Bool - -- ^ include local project bin directory, GHC_PACKAGE_PATH, etc + -- ^ include project's local bin directory, GHC_PACKAGE_PATH, etc , includeGhcPackagePath :: !Bool -- ^ include the GHC_PACKAGE_PATH variable , stackExe :: !Bool
src/Stack/Types/GhcPkgId.hs view
@@ -4,7 +4,7 @@ module Stack.Types.GhcPkgId ( GhcPkgId - , unGhcPkgId + , ghcPkgIdToText , ghcPkgIdParser , parseGhcPkgId , ghcPkgIdString @@ -16,8 +16,11 @@ , satisfy ) import Data.Char ( isAlphaNum ) -import qualified Data.Text as T -import Database.Persist.Sql ( PersistField, PersistFieldSql ) +import Data.Hashable ( Hashable(..) ) +import Database.Persist.Sql + ( PersistField (..), PersistFieldSql (..) ) +import Distribution.Compat.Binary ( decode, encode ) +import Distribution.Types.UnitId ( UnitId, mkUnitId, unUnitId ) import Stack.Prelude import Text.Read ( Read (..) ) @@ -35,18 +38,26 @@ -- | A ghc-pkg package identifier. newtype GhcPkgId - = GhcPkgId Text - deriving (Data, Eq, Generic, Ord, PersistField, PersistFieldSql, Typeable) + = GhcPkgId UnitId + deriving (Data, Eq, Generic, Ord, Typeable) -instance Hashable GhcPkgId +instance PersistField GhcPkgId where + toPersistValue = toPersistValue . ghcPkgIdToText + fromPersistValue = (fmap . fmap) ghcPkgIdFromText fromPersistValue +instance PersistFieldSql GhcPkgId where + sqlType _ = sqlType @Text Proxy + +instance Hashable GhcPkgId where + hashWithSalt a (GhcPkgId v) = hashWithSalt a (encode v) + instance NFData GhcPkgId instance Show GhcPkgId where show = show . ghcPkgIdString instance Read GhcPkgId where - readsPrec i = map (first (GhcPkgId . T.pack)) . readsPrec i + readsPrec i = map (first (GhcPkgId . mkUnitId)) . readsPrec i instance FromJSON GhcPkgId where parseJSON = withText "GhcPkgId" $ \t -> @@ -70,7 +81,7 @@ ghcPkgIdParser :: Parser GhcPkgId ghcPkgIdParser = let elements = "_.-" :: String - in GhcPkgId . T.pack <$> + in GhcPkgId . mkUnitId <$> many1 (choice [alphaNum, satisfy (`elem` elements)]) -- | Parse an alphanumerical character, as recognised by `isAlphaNum`. @@ -80,8 +91,11 @@ -- | Get a string representation of GHC package id. ghcPkgIdString :: GhcPkgId -> String -ghcPkgIdString (GhcPkgId x) = T.unpack x +ghcPkgIdString (GhcPkgId x) = unUnitId x --- | Get a text value of GHC package id -unGhcPkgId :: GhcPkgId -> Text -unGhcPkgId (GhcPkgId v) = v +-- | Get a text value of GHC package id. +ghcPkgIdToText :: GhcPkgId -> Text +ghcPkgIdToText (GhcPkgId v) = decode . encode $ v +-- | Create GhcPkgId from Text. +ghcPkgIdFromText :: Text -> GhcPkgId +ghcPkgIdFromText = GhcPkgId . decode . encode
src/Stack/Types/GlobalOpts.hs view
@@ -12,8 +12,8 @@ import Stack.Types.ConfigMonoid ( ConfigMonoid (..) ) import Stack.Types.DockerEntrypoint ( DockerEntrypoint ) import Stack.Types.LockFileBehavior ( LockFileBehavior ) -import Stack.Types.Resolver ( AbstractResolver ) import Stack.Types.StackYamlLoc ( StackYamlLoc ) +import Stack.Types.Snapshot ( AbstractSnapshot ) -- | Parsed global command-line options. data GlobalOpts = GlobalOpts @@ -31,7 +31,7 @@ -- build plan in logs. , configMonoid :: !ConfigMonoid -- ^ Config monoid, for passing into 'loadConfig' - , resolver :: !(Maybe AbstractResolver) -- ^ Resolver override + , snapshot :: !(Maybe AbstractSnapshot) -- ^ Snapshot override , compiler :: !(Maybe WantedCompiler) -- ^ Compiler override , terminal :: !Bool -- ^ We're in a terminal? , stylesUpdate :: !StylesUpdate -- ^ SGR (Ansi) codes for styles @@ -39,7 +39,6 @@ , stackYaml :: !StackYamlLoc -- ^ Override project stack.yaml , lockFileBehavior :: !LockFileBehavior } - deriving Show globalOptsBuildOptsMonoidL :: Lens' GlobalOpts BuildOptsMonoid globalOptsBuildOptsMonoidL =
src/Stack/Types/GlobalOptsMonoid.hs view
@@ -10,7 +10,7 @@ import Stack.Types.ConfigMonoid ( ConfigMonoid ) import Stack.Types.DockerEntrypoint ( DockerEntrypoint ) import Stack.Types.LockFileBehavior ( LockFileBehavior ) -import Stack.Types.Resolver ( AbstractResolver ) +import Stack.Types.Snapshot ( AbstractSnapshot ) -- | Parsed global command-line options monoid. data GlobalOptsMonoid = GlobalOptsMonoid @@ -30,10 +30,10 @@ -- build plan in logs. , configMonoid :: !ConfigMonoid -- ^ Config monoid, for passing into 'loadConfig' - , resolver :: !(First (Unresolved AbstractResolver)) - -- ^ Resolver override - , resolverRoot :: !(First FilePath) - -- ^ root directory for resolver relative path + , snapshot :: !(First (Unresolved AbstractSnapshot)) + -- ^ Snapshot override + , snapshotRoot :: !(First FilePath) + -- ^ root directory for snapshot relative path , compiler :: !(First WantedCompiler) -- ^ Compiler override , terminal :: !(First Bool)
+ src/Stack/Types/InterfaceOpt.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE NoFieldSelectors #-} + +-- | Type representing Haddock interface options. +module Stack.Types.InterfaceOpt + ( InterfaceOpt (..) + ) where + +import Data.Time ( UTCTime ) +import Stack.Prelude + +-- | Type representing Haddock interface options. +data InterfaceOpt = InterfaceOpt + { readInterfaceArgs :: ![String] + , srcInterfaceFileModTime :: !UTCTime + , srcInterfaceFile :: !(Path Abs File) + , destInterfaceFile :: !(Path Abs File) + } + deriving (Eq, Ord)
+ src/Stack/Types/MsysEnvironment.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE NoImplicitPrelude #-} + +-- | Type representing MSYS2 environments and related functions. +module Stack.Types.MsysEnvironment + ( MsysEnvironment (..) + , msysEnvArch + , relDirMsysEnv + ) where + +import Data.Aeson.Types ( FromJSON (..) ) +import Distribution.System ( Arch (..) ) +import Stack.Constants + ( relDirClang32, relDirClang64, relDirClangArm64 + , relDirMingw32, relDirMingw64, relDirUcrt64 + ) +import Stack.Prelude + +-- | Type representing MSYS2 environments. +data MsysEnvironment + = CLANG32 + | CLANG64 + | CLANGARM64 + | MINGW32 + -- ^ Stack's default on architecture i386, and applied if GHC version is + -- earlier than GHC 9.6. + | MINGW64 + -- ^ Stack's default on architecture x86_64, and applied if GHC version is + -- earlier than GHC 9.6. + | UCRT64 + deriving (Eq, Ord, Show) + +-- | MSYS2 environment names are treated as case sensitive. +instance FromJSON MsysEnvironment where + parseJSON v = do + s <- parseJSON v + case s of + "CLANG32" -> pure CLANG32 + "CLANG64" -> pure CLANG64 + "CLANGARM64" -> pure CLANGARM64 + "MINGW32" -> pure MINGW32 + "MINGW64" -> pure MINGW64 + "UCRT64" -> pure UCRT64 + _ -> fail ("Unknown MSYS2 environment: " <> s) + +-- | Function that yields the architecture relevant to an MSYS2 environment, +-- based on https://www.msys2.org/docs/environments/. +msysEnvArch :: MsysEnvironment -> Arch +msysEnvArch env = case env of + CLANG32 -> I386 + CLANG64 -> X86_64 + CLANGARM64 -> AArch64 + MINGW32 -> I386 + MINGW64 -> X86_64 + UCRT64 -> X86_64 + +-- | Function that yields the prefix relevant to an MSYS2 environment, based on +-- https://www.msys2.org/docs/environments/. +relDirMsysEnv :: MsysEnvironment -> Path Rel Dir +relDirMsysEnv env = case env of + CLANG32 -> relDirClang32 + CLANG64 -> relDirClang64 + CLANGARM64 -> relDirClangArm64 + MINGW32 -> relDirMingw32 + MINGW64 -> relDirMingw64 + UCRT64 -> relDirUcrt64
src/Stack/Types/NamedComponent.hs view
@@ -4,6 +4,7 @@ -- | Module exporting the 'NamedComponent' type and related functions. module Stack.Types.NamedComponent ( NamedComponent (..) + , componentCachePath , renderComponent , renderComponentTo , renderPkgComponents @@ -24,20 +25,23 @@ import qualified Data.Set as Set import qualified Data.Text as T import Stack.Prelude +import Stack.Types.ComponentUtils + ( StackUnqualCompName, unqualCompToString, unqualCompToText + ) -- | Type representing components of a fully-resolved Cabal package. data NamedComponent = CLib -- The \'main\' unnamed library component. - | CSubLib !Text + | CSubLib !StackUnqualCompName -- A named \'subsidiary\' or \'ancillary\` library component (sub-library). - | CFlib !Text + | CFlib !StackUnqualCompName -- A foreign library. - | CExe !Text + | CExe !StackUnqualCompName -- A named executable component. - | CTest !Text + | CTest !StackUnqualCompName -- A named test-suite component. - | CBench !Text + | CBench !StackUnqualCompName -- A named benchmark component. deriving (Eq, Ord, Show) @@ -48,12 +52,20 @@ renderComponent :: NamedComponent -> Text renderComponent CLib = "lib" -renderComponent (CSubLib x) = "sub-lib:" <> x -renderComponent (CFlib x) = "flib:" <> x -renderComponent (CExe x) = "exe:" <> x -renderComponent (CTest x) = "test:" <> x -renderComponent (CBench x) = "bench:" <> x +renderComponent (CSubLib x) = "sub-lib:" <> unqualCompToText x +renderComponent (CFlib x) = "flib:" <> unqualCompToText x +renderComponent (CExe x) = "exe:" <> unqualCompToText x +renderComponent (CTest x) = "test:" <> unqualCompToText x +renderComponent (CBench x) = "bench:" <> unqualCompToText x +componentCachePath :: NamedComponent -> String +componentCachePath CLib = "lib" +componentCachePath (CSubLib x) = "sub-lib-" <> unqualCompToString x +componentCachePath (CFlib x) = "flib-" <> unqualCompToString x +componentCachePath (CExe x) = "exe-" <> unqualCompToString x +componentCachePath (CTest x) = "test-" <> unqualCompToString x +componentCachePath (CBench x) = "bench-" <> unqualCompToString x + renderPkgComponents :: [(PackageName, NamedComponent)] -> Text renderPkgComponents = T.intercalate " " . map renderPkgComponent @@ -61,25 +73,25 @@ renderPkgComponent (pkg, comp) = fromPackageName pkg <> ":" <> renderComponent comp -exeComponents :: Set NamedComponent -> Set Text +exeComponents :: Set NamedComponent -> Set StackUnqualCompName exeComponents = Set.fromList . mapMaybe mExeName . Set.toList where mExeName (CExe name) = Just name mExeName _ = Nothing -testComponents :: Set NamedComponent -> Set Text +testComponents :: Set NamedComponent -> Set StackUnqualCompName testComponents = Set.fromList . mapMaybe mTestName . Set.toList where mTestName (CTest name) = Just name mTestName _ = Nothing -benchComponents :: Set NamedComponent -> Set Text +benchComponents :: Set NamedComponent -> Set StackUnqualCompName benchComponents = Set.fromList . mapMaybe mBenchName . Set.toList where mBenchName (CBench name) = Just name mBenchName _ = Nothing -subLibComponents :: Set NamedComponent -> Set Text +subLibComponents :: Set NamedComponent -> Set StackUnqualCompName subLibComponents = Set.fromList . mapMaybe mSubLibName . Set.toList where mSubLibName (CSubLib name) = Just name @@ -115,13 +127,13 @@ -- often than not, you can keep/parse the components split from the start. splitComponents :: [NamedComponent] - -> ( Set Text + -> ( Set StackUnqualCompName -- ^ Sub-libraries. - , Set Text + , Set StackUnqualCompName -- ^ Executables. - , Set Text + , Set StackUnqualCompName -- ^ Test-suites. - , Set Text + , Set StackUnqualCompName -- ^ Benchmarks. ) splitComponents =
src/Stack/Types/Nix.hs view
@@ -22,7 +22,7 @@ import Generics.Deriving.Monoid ( mappenddefault, memptydefault ) import Stack.Prelude --- | Nix configuration. Parameterize by resolver type to avoid cyclic +-- | Nix configuration. Parameterize by snapshot type to avoid cyclic -- dependency. data NixOpts = NixOpts { enable :: !Bool
src/Stack/Types/Package.hs view
@@ -29,6 +29,7 @@ , dotCabalModule , dotCabalModulePath , installedMapGhcPkgId + , installedPackageToGhcPkgId , lpFiles , lpFilesForComponents , memoizeRefWith @@ -417,6 +418,14 @@ M.mapKeysMonotonic (toCabalMungedPackageIdentifier pkgName version) installedLib.subLib + +installedPackageToGhcPkgId :: + PackageIdentifier + -> Installed + -> Map PackageIdentifier GhcPkgId +installedPackageToGhcPkgId ident (Library ident' libInfo) = + assert (ident == ident') (installedMapGhcPkgId ident libInfo) +installedPackageToGhcPkgId _ (Executable _) = mempty -- | Creates a 'MungedPackageName' identifier. toCabalMungedPackageIdentifier ::
src/Stack/Types/Project.hs view
@@ -27,17 +27,17 @@ -- of the snapshot. , flagsByPkg :: !(Map PackageName (Map FlagName Bool)) -- ^ Flags to be applied on top of the snapshot flags. - , resolver :: !RawSnapshotLocation + , snapshot :: !RawSnapshotLocation -- ^ How we resolve which @Snapshot@ to use , compiler :: !(Maybe WantedCompiler) - -- ^ Override the compiler in 'projectResolver' + -- ^ Override the compiler in 'snapshot' , extraPackageDBs :: ![FilePath] , curator :: !(Maybe Curator) -- ^ Extra configuration intended exclusively for usage by the curator tool. -- In other words, this is /not/ part of the documented and exposed Stack -- API. SUBJECT TO CHANGE. , dropPackages :: !(Set PackageName) - -- ^ Packages to drop from the 'projectResolver'. + -- ^ Packages to drop from the 'snapshot'. } deriving Show @@ -54,7 +54,7 @@ | not (Map.null project.flagsByPkg) ] , ["packages" .= project.packages] - , ["resolver" .= project.resolver] + , ["snapshot" .= project.snapshot] , maybe [] (\c -> ["curator" .= c]) project.curator , [ "drop-packages" .= Set.map CabalString project.dropPackages | not (Set.null project.dropPackages)
src/Stack/Types/ProjectAndConfigMonoid.hs view
@@ -33,7 +33,7 @@ let flagsByPkg = unCabalStringMap <$> unCabalStringMap (flags' :: Map (CabalString PackageName) (Map (CabalString FlagName) Bool)) - resolver' <- jsonSubWarnings $ o ...: ["snapshot", "resolver"] + snapshot' <- jsonSubWarnings $ o ...: ["snapshot", "resolver"] compiler <- o ..:? "compiler" userMsg <- o ..:? "user-message" config <- parseConfigMonoidObject rootDir o @@ -45,11 +45,11 @@ deps' <- mapM (resolvePaths (Just rootDir)) deps let extraDeps = concatMap toList (deps' :: [NonEmpty RawPackageLocation]) - resolver <- resolvePaths (Just rootDir) resolver' + snapshot <- resolvePaths (Just rootDir) snapshot' let project = Project { userMsg - , resolver - , compiler -- FIXME make sure resolver' isn't SLCompiler + , snapshot + , compiler -- FIXME make sure snapshot' isn't SLCompiler , extraPackageDBs , packages , extraDeps
− src/Stack/Types/Resolver.hs
@@ -1,107 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE NoFieldSelectors #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE UndecidableInstances #-} - -module Stack.Types.Resolver - ( AbstractResolver (..) - , readAbstractResolver - , Snapshots (..) - ) where - -import qualified Data.Aeson.Key as Key -import qualified Data.Aeson.KeyMap as KeyMap -import Data.Aeson.Types - ( FromJSON, parseJSON, withObject, withText ) -import Data.Aeson.WarningParser ( (.:) ) -import qualified Data.IntMap.Strict as IntMap -import qualified Data.Text as T -import Data.Text.Read ( decimal ) -import Data.Time ( Day ) -import Options.Applicative ( ReadM ) -import qualified Options.Applicative.Types as OA -import Stack.Prelude - --- | Type representing exceptions thrown by functions exported by the --- "Stack.Types.Resolver" module. -data TypesResolverException - = ParseResolverException !Text - | FilepathInDownloadedSnapshot !Text - deriving (Show, Typeable) - -instance Exception TypesResolverException where - displayException (ParseResolverException t) = concat - [ "Error: [S-8787]\n" - , "Invalid resolver value: " - , T.unpack t - , ". Possible valid values include lts-2.12, nightly-YYYY-MM-DD, \ - \ghc-7.10.2, and ghcjs-0.1.0_ghc-7.10.2. See \ - \https://www.stackage.org/snapshots for a complete list." - ] - displayException (FilepathInDownloadedSnapshot url) = unlines - [ "Error: [S-4865]" - , "Downloaded snapshot specified a 'resolver: { location: filepath }' " - , "field, but filepaths are not allowed in downloaded snapshots.\n" - , "Filepath specified: " ++ T.unpack url - ] - --- | Either an actual resolver value, or an abstract description of one (e.g., --- latest nightly). -data AbstractResolver - = ARLatestNightly - | ARLatestLTS - | ARLatestLTSMajor !Int - | ARResolver !RawSnapshotLocation - | ARGlobal - -instance Show AbstractResolver where - show = T.unpack . utf8BuilderToText . display - -instance Display AbstractResolver where - display ARLatestNightly = "nightly" - display ARLatestLTS = "lts" - display (ARLatestLTSMajor x) = "lts-" <> display x - display (ARResolver usl) = display usl - display ARGlobal = "global" - -readAbstractResolver :: ReadM (Unresolved AbstractResolver) -readAbstractResolver = do - s <- OA.readerAsk - case s of - "global" -> pure $ pure ARGlobal - "nightly" -> pure $ pure ARLatestNightly - "lts" -> pure $ pure ARLatestLTS - 'l':'t':'s':'-':x | Right (x', "") <- decimal $ T.pack x -> - pure $ pure $ ARLatestLTSMajor x' - _ -> pure $ ARResolver <$> parseRawSnapshotLocation (T.pack s) - --- | Most recent Nightly and newest LTS version per major release. -data Snapshots = Snapshots - { nightly :: !Day - , lts :: !(IntMap Int) - } - deriving Show - -instance FromJSON Snapshots where - parseJSON = withObject "Snapshots" $ \o -> Snapshots - <$> (o .: "nightly" >>= parseNightly) - <*> fmap IntMap.unions (mapM (parseLTS . snd) - $ filter (isLTS . Key.toText . fst) - $ KeyMap.toList o) - where - parseNightly t = - case parseSnapName t of - Left e -> fail $ displayException e - Right (LTS _ _) -> fail "Unexpected LTS value" - Right (Nightly d) -> pure d - - isLTS = ("lts-" `T.isPrefixOf`) - - parseLTS = withText "LTS" $ \t -> - case parseSnapName t of - Left e -> fail $ displayException e - Right (LTS x y) -> pure $ IntMap.singleton x y - Right (Nightly _) -> fail "Unexpected nightly value"
+ src/Stack/Types/Snapshot.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE NoFieldSelectors #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +module Stack.Types.Snapshot + ( AbstractSnapshot (..) + , readAbstractSnapshot + , Snapshots (..) + ) where + +import qualified Data.Aeson.Key as Key +import qualified Data.Aeson.KeyMap as KeyMap +import Data.Aeson.Types + ( FromJSON, parseJSON, withObject, withText ) +import Data.Aeson.WarningParser ( (.:) ) +import qualified Data.IntMap.Strict as IntMap +import qualified Data.Text as T +import Data.Text.Read ( decimal ) +import Data.Time ( Day ) +import Options.Applicative ( ReadM ) +import qualified Options.Applicative.Types as OA +import Stack.Prelude + +-- | Type representing exceptions thrown by functions exported by the +-- "Stack.Types.Snapshot" module. +data TypesSnapshotException + = ParseSnapshotException !Text + | FilepathInDownloadedSnapshot !Text + deriving (Show, Typeable) + +instance Exception TypesSnapshotException where + displayException (ParseSnapshotException t) = concat + [ "Error: [S-8787]\n" + , "Invalid snapshot value: " + , T.unpack t + , ". Possible valid values include lts-2.12, nightly-YYYY-MM-DD, \ + \ghc-7.10.2, and ghcjs-0.1.0_ghc-7.10.2. See \ + \https://www.stackage.org/snapshots for a complete list." + ] + displayException (FilepathInDownloadedSnapshot url) = unlines + [ "Error: [S-4865]" + , "Downloaded snapshot specified a 'snapshot: { location: filepath }' " + , "field, but filepaths are not allowed in downloaded snapshots.\n" + , "Filepath specified: " ++ T.unpack url + ] + +-- | Either an actual snapshot value, or an abstract description of one (e.g., +-- latest nightly). +data AbstractSnapshot + = ASLatestNightly + | ASLatestLTS + | ASLatestLTSMajor !Int + | ASSnapshot !RawSnapshotLocation + | ASGlobal + +instance Show AbstractSnapshot where + show = T.unpack . utf8BuilderToText . display + +instance Display AbstractSnapshot where + display ASLatestNightly = "nightly" + display ASLatestLTS = "lts" + display (ASLatestLTSMajor x) = "lts-" <> display x + display (ASSnapshot usl) = display usl + display ASGlobal = "global" + +instance FromJSON (Unresolved AbstractSnapshot) where + parseJSON = withText "Unresolved AbstractSnapshot" $ \t -> + pure $ parseAbstractSnapshot $ T.unpack t + +readAbstractSnapshot :: ReadM (Unresolved AbstractSnapshot) +readAbstractSnapshot = parseAbstractSnapshot <$> OA.readerAsk + +parseAbstractSnapshot :: String -> Unresolved AbstractSnapshot +parseAbstractSnapshot s = case s of + "global" -> pure ASGlobal + "nightly" -> pure ASLatestNightly + "lts" -> pure ASLatestLTS + 'l':'t':'s':'-':x | Right (x', "") <- decimal $ T.pack x -> + pure $ ASLatestLTSMajor x' + _ ->ASSnapshot <$> parseRawSnapshotLocation (T.pack s) + +-- | Most recent Nightly and newest LTS version per major release. +data Snapshots = Snapshots + { nightly :: !Day + , lts :: !(IntMap Int) + } + deriving Show + +instance FromJSON Snapshots where + parseJSON = withObject "Snapshots" $ \o -> Snapshots + <$> (o .: "nightly" >>= parseNightly) + <*> fmap IntMap.unions (mapM (parseLTS . snd) + $ filter (isLTS . Key.toText . fst) + $ KeyMap.toList o) + where + parseNightly t = + case parseSnapName t of + Left e -> fail $ displayException e + Right (LTS _ _) -> fail "Unexpected LTS value" + Right (Nightly d) -> pure d + + isLTS = ("lts-" `T.isPrefixOf`) + + parseLTS = withText "LTS" $ \t -> + case parseSnapName t of + Left e -> fail $ displayException e + Right (LTS x y) -> pure $ IntMap.singleton x y + Right (Nightly _) -> fail "Unexpected nightly value"
src/Stack/Types/SourceMap.hs view
@@ -39,6 +39,7 @@ import Path ( parent, parseRelDir ) import Stack.Prelude import Stack.Types.Compiler ( ActualCompiler ) +import Stack.Types.ComponentUtils ( fromCabalName ) import Stack.Types.NamedComponent ( NamedComponent (..) ) -- | Settings common to dependency packages ('Stack.Types.SourceMap.DepPackage') @@ -191,16 +192,12 @@ gpd <- ppGPD pp pure $ Set.fromList $ concat [ maybe [] (const $ catMaybes [compType CLib]) (C.condLibrary gpd) - , go (compType . CExe) (fst <$> C.condExecutables gpd) - , go (compType . CTest) (fst <$> C.condTestSuites gpd) - , go (compType . CBench) (fst <$> C.condBenchmarks gpd) + , mapMaybe ((compType . CExe . fromCabalName) . fst) (C.condExecutables gpd) + , mapMaybe ((compType . CTest . fromCabalName) . fst) (C.condTestSuites gpd) + , mapMaybe + ((compType . CBench . fromCabalName) . fst) + (C.condBenchmarks gpd) ] - where - go :: - (T.Text -> Maybe NamedComponent) - -> [C.UnqualComponentName] - -> [NamedComponent] - go wrapper = mapMaybe (wrapper . T.pack . C.unUnqualComponentName) -- | Version for the given 'ProjectPackage ppVersion :: MonadIO m => ProjectPackage -> m Version
src/Stack/Types/StackYamlLoc.hs view
@@ -15,7 +15,7 @@ -- ^ Use a specific stack.yaml file provided | SYLNoProject ![PackageIdentifierRevision] -- ^ Do not load up a project, just user configuration. Include - -- the given extra dependencies with the resolver. + -- the given extra dependencies with the snapshot. | SYLGlobalProject -- ^ Do not look for a project configuration, and use the implicit global. deriving Show
+ src/Stack/Types/UploadOpts.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE NoFieldSelectors #-} + +-- | Types for command line options for the @stack upload@ command. +module Stack.Types.UploadOpts + ( UploadOpts (..) + , UploadVariant (..) + ) where + +import Stack.Prelude +import Stack.Types.PvpBounds (PvpBounds) + +-- | Type representing command line options for the @stack upload@ command. +data UploadOpts = UploadOpts + { itemsToWorkWith :: ![String] + -- ^ The items to work with. + , documentation :: !Bool + -- ^ Uploading documentation for packages? + , pvpBounds :: !(Maybe PvpBounds) + , check :: !Bool + , buildPackage :: !Bool + , tarPath :: !(Maybe FilePath) + , uploadVariant :: !UploadVariant + , saveHackageCreds :: !FirstTrue + -- ^ Save user's Hackage username and password in a local file? + } + +-- | Type representing variants for uploading to Hackage. +data UploadVariant + = Publishing + -- ^ Publish the package/a published package. + | Candidate + -- ^ Create a package candidate/a package candidate.
+ src/Stack/Types/WantedCompilerSetter.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE NoImplicitPrelude #-} + +module Stack.Types.WantedCompilerSetter + ( WantedCompilerSetter (..) + ) where + +import Stack.Prelude + +-- | Type representing ways that a wanted compiler is set. +data WantedCompilerSetter + = CompilerAtCommandLine + -- ^ At the command line with --compiler option. + | SnapshotAtCommandLine + -- ^ At the command line with --snapshot (or --resolver) option. + | YamlConfiguration (Maybe (Path Abs File)) + -- ^ Via a YAML configuration file. + deriving (Show, Typeable)
src/Stack/Uninstall.hs view
@@ -11,7 +11,7 @@ import Stack.Prelude import Stack.Runners ( ShouldReexec (..), withConfig ) import Stack.Types.Config - ( Config (..), configL, stackGlobalConfigL, stackRootL ) + ( Config (..), configL, stackRootL, userGlobalConfigFileL ) import Stack.Types.Runner ( Runner ) -- | Function underlying the @stack uninstall@ command. Display help for the @@ -19,12 +19,12 @@ uninstallCmd :: () -> RIO Runner () uninstallCmd () = withConfig NoReexec $ do stackRoot <- view stackRootL - globalConfig <- view stackGlobalConfigL + userGlobalConfigFile <- view userGlobalConfigFileL programsDir <- view $ configL . to (.localProgramsBase) localBinDir <- view $ configL . to (.localBin) let toStyleDoc = style Dir . fromString . toFilePath stackRoot' = toStyleDoc stackRoot - globalConfig' = toStyleDoc globalConfig + userGlobalConfigFile' = toStyleDoc userGlobalConfigFile programsDir' = toStyleDoc programsDir localBinDir' = toStyleDoc localBinDir putUtf8Builder =<< displayWithColor @@ -40,8 +40,8 @@ ] , hang 4 $ fillSep [ flow "(3) if different, the directory containing " - , flow "Stack's global YAML configuration file" - , parens globalConfig' <> ";" + , flow "Stack's user-specific global YAML configuration file" + , parens userGlobalConfigFile' <> ";" , "and" ] , hang 4 $ fillSep
src/Stack/Unpack.hs view
@@ -14,18 +14,16 @@ import Data.List.Extra ( notNull ) import Path ( SomeBase (..), (</>), parseRelDir ) import Path.IO ( doesDirExist, getCurrentDir ) -import Pantry ( loadSnapshot ) import qualified RIO.Map as Map import RIO.Process ( HasProcessContext ) import qualified RIO.Set as Set import qualified RIO.Text as T -import Stack.Config ( makeConcreteResolver ) +import Stack.Config ( getRawSnapshot ) import Stack.Constants ( relDirRoot ) import Stack.Prelude import Stack.Runners ( ShouldReexec (..), withConfig ) import Stack.Types.Config ( Config (..), HasConfig, configL ) -import Stack.Types.GlobalOpts ( GlobalOpts (..) ) -import Stack.Types.Runner ( Runner, globalOptsL ) +import Stack.Types.Runner ( Runner ) -- | Type representing \'pretty\' exceptions thrown by functions exported by the -- "Stack.Unpack" module. @@ -94,11 +92,7 @@ unpackCmd (UnpackOpts targets areCandidates (Just $ Rel relDirRoot)) unpackCmd (UnpackOpts targets areCandidates (Just dstPath)) = withConfig NoReexec $ do - mresolver <- view $ globalOptsL . to (.resolver) - mSnapshot <- forM mresolver $ \resolver -> do - concrete <- makeConcreteResolver resolver - loc <- completeSnapshotLocation concrete - loadSnapshot loc + mSnapshot <- getRawSnapshot dstPath' <- case dstPath of Abs path -> pure path Rel path -> do
src/Stack/Upgrade.hs view
@@ -39,7 +39,7 @@ -- | Type representing \'pretty\' exceptions thrown by functions in the -- "Stack.Upgrade" module. data UpgradePrettyException - = ResolverOptionInvalid + = SnapshotOptionInvalid | NeitherBinaryOrSourceSpecified | ExecutableFailure | CommitsNotFound String String @@ -48,12 +48,12 @@ deriving (Show, Typeable) instance Pretty UpgradePrettyException where - pretty ResolverOptionInvalid = + pretty SnapshotOptionInvalid = "[S-8761]" <> line <> fillSep [ "The" - , style Shell "--resolver" + , style Shell "--snapshot" , flow "option cannot be used with Stack's" , style Shell "upgrade" , "command." @@ -118,8 +118,8 @@ upgradeCmd :: UpgradeOpts -> RIO Runner () upgradeCmd upgradeOpts = do go <- view globalOptsL - case go.resolver of - Just _ -> prettyThrowIO ResolverOptionInvalid + case go.snapshot of + Just _ -> prettyThrowIO SnapshotOptionInvalid Nothing -> withGlobalProject $ upgrade maybeGitHash upgradeOpts upgrade :: @@ -283,8 +283,8 @@ pure $ Just dir let modifyGO dir go = go - { resolver = Nothing -- always use the resolver settings in the - -- stack.yaml file + { snapshot = Nothing -- always use the snapshot settings in the + -- stack.yaml file , stackYaml = SYLOverride $ dir </> stackDotYaml } boptsCLI = defaultBuildOptsCLI { targetsCLI = ["stack"] }
src/Stack/Upload.hs view
@@ -56,10 +56,11 @@ , getSDistTarball, readLocalPackage ) import Stack.Types.Config ( Config (..), configL, stackRootL ) +import qualified Stack.Types.Config as Config import Stack.Types.EnvConfig ( HasEnvConfig ) import Stack.Types.Package ( LocalPackage (..), packageIdentifier ) -import Stack.Types.PvpBounds (PvpBounds) import Stack.Types.Runner ( Runner ) +import Stack.Types.UploadOpts ( UploadOpts (..), UploadVariant (..) ) import System.Directory ( createDirectoryIfMissing, doesDirectoryExist, doesFileExist , removeFile, renameFile @@ -159,94 +160,78 @@ | DocArchive -- ^ Content in the form of an archive file of package documentation. --- | Type representing variants for uploading to Hackage. -data UploadVariant - = Publishing - -- ^ Publish the package/a published package. - | Candidate - -- ^ Create a package candidate/a package candidate. - --- | Type representing command line options for the @stack upload@ command. -data UploadOpts = UploadOpts - { itemsToWorkWith :: ![String] - -- ^ The items to work with. - , documentation :: !Bool - -- ^ Uploading documentation for packages? - , pvpBounds :: !(Maybe PvpBounds) - , check :: !Bool - , buildPackage :: !Bool - , tarPath :: !(Maybe FilePath) - , uploadVariant :: !UploadVariant - } - -- | Function underlying the @stack upload@ command. Upload to Hackage. uploadCmd :: UploadOpts -> RIO Runner () -uploadCmd (UploadOpts [] uoDocumentation _ _ _ _ _) = do +uploadCmd (UploadOpts [] uoDocumentation _ _ _ _ _ _) = do let subject = if uoDocumentation then "documentation for the current package," else "the current package," prettyThrowIO $ NoItemSpecified subject -uploadCmd uo = withConfig YesReexec $ withDefaultEnvConfig $ do - config <- view configL - let hackageUrl = T.unpack config.hackageBaseUrl - if uo.documentation - then do - (dirs, invalid) <- - liftIO $ partitionM doesDirectoryExist uo.itemsToWorkWith - unless (null invalid) $ - prettyThrowIO $ PackageDirectoryInvalid invalid - (failed, items) <- partitionEithers <$> forM dirs checkDocsTarball - unless (null failed) $ do - prettyThrowIO $ DocsTarballInvalid failed - getCreds <- memoizeRef $ loadAuth config - forM_ items $ \(pkgIdName, tarGzFile) -> do - creds <- runMemoized getCreds - upload - hackageUrl - creds - DocArchive - (Just pkgIdName) - (toFilePath tarGzFile) - uo.uploadVariant - else do - (files, nonFiles) <- - liftIO $ partitionM doesFileExist uo.itemsToWorkWith - (dirs, invalid) <- liftIO $ partitionM doesDirectoryExist nonFiles - unless (null invalid) $ do - prettyThrowIO $ ItemsInvalid invalid - let sdistOpts = SDistOpts - uo.itemsToWorkWith - uo.pvpBounds - uo.check - uo.buildPackage - uo.tarPath - getCreds <- memoizeRef $ loadAuth config - mapM_ (resolveFile' >=> checkSDistTarball sdistOpts) files - forM_ files $ \file -> do - tarFile <- resolveFile' file - creds <- runMemoized getCreds - upload - hackageUrl - creds - SDist - Nothing - (toFilePath tarFile) - uo.uploadVariant - forM_ dirs $ \dir -> do - pkgDir <- resolveDir' dir - (tarName, tarBytes, mcabalRevision) <- - getSDistTarball uo.pvpBounds pkgDir - checkSDistTarball' sdistOpts tarName tarBytes - creds <- runMemoized getCreds - uploadBytes - hackageUrl - creds - SDist - Nothing - tarName - uo.uploadVariant - tarBytes - forM_ mcabalRevision $ uncurry $ uploadRevision hackageUrl creds +uploadCmd uo = do + let setSaveHackageCreds config = + let saveHackageCreds = config.saveHackageCreds <> uo.saveHackageCreds + in config { Config.saveHackageCreds = saveHackageCreds } + withConfig YesReexec $ local setSaveHackageCreds $ withDefaultEnvConfig $ do + config <- view configL + let hackageUrl = T.unpack config.hackageBaseUrl + if uo.documentation + then do + (dirs, invalid) <- + liftIO $ partitionM doesDirectoryExist uo.itemsToWorkWith + unless (null invalid) $ + prettyThrowIO $ PackageDirectoryInvalid invalid + (failed, items) <- partitionEithers <$> forM dirs checkDocsTarball + unless (null failed) $ do + prettyThrowIO $ DocsTarballInvalid failed + getCreds <- memoizeRef $ loadAuth config + forM_ items $ \(pkgIdName, tarGzFile) -> do + creds <- runMemoized getCreds + upload + hackageUrl + creds + DocArchive + (Just pkgIdName) + (toFilePath tarGzFile) + uo.uploadVariant + else do + (files, nonFiles) <- + liftIO $ partitionM doesFileExist uo.itemsToWorkWith + (dirs, invalid) <- liftIO $ partitionM doesDirectoryExist nonFiles + unless (null invalid) $ do + prettyThrowIO $ ItemsInvalid invalid + let sdistOpts = SDistOpts + uo.itemsToWorkWith + uo.pvpBounds + uo.check + uo.buildPackage + uo.tarPath + getCreds <- memoizeRef $ loadAuth config + mapM_ (resolveFile' >=> checkSDistTarball sdistOpts) files + forM_ files $ \file -> do + tarFile <- resolveFile' file + creds <- runMemoized getCreds + upload + hackageUrl + creds + SDist + Nothing + (toFilePath tarFile) + uo.uploadVariant + forM_ dirs $ \dir -> do + pkgDir <- resolveDir' dir + (tarName, tarBytes, mcabalRevision) <- + getSDistTarball uo.pvpBounds pkgDir + checkSDistTarball' sdistOpts tarName tarBytes + creds <- runMemoized getCreds + uploadBytes + hackageUrl + creds + SDist + Nothing + tarName + uo.uploadVariant + tarBytes + forM_ mcabalRevision $ uncurry $ uploadRevision hackageUrl creds where checkDocsTarball :: HasEnvConfig env @@ -336,7 +321,7 @@ -- didn't do this writeFilePrivate fp $ lazyByteString lbs - unless config.saveHackageCreds $ do + unless (fromFirstTrue config.saveHackageCreds) $ do prettyWarnL [ flow "You've set" , style Shell "save-hackage-creds" @@ -357,7 +342,7 @@ , credsFile = fp } - when config.saveHackageCreds $ do + when (fromFirstTrue config.saveHackageCreds) $ do shouldSave <- promptBool $ T.pack $ "Save Hackage credentials to file at " ++ fp ++ " [y/n]? " prettyNoteL
src/System/Process/Pager.hs view
@@ -56,7 +56,6 @@ case exit of ExitSuccess -> pure () ExitFailure n -> throwIO (PagerExitFailure (cmdspec pager) n) - pure () Nothing -> writer stdout where cmdspecFromEnvVar = shell <$> MaybeT (lookupEnv "PAGER")
src/setup-shim/StackSetupShim.hs view
@@ -3,14 +3,14 @@ module StackSetupShim where --- | Stack no longer supports Cabal < 1.24 and, consequently, GHC versions --- before GHC 8.0 or base < 4.9.0.0. Consequently, we do not need to test for --- the existence of the MIN_VERSION_Cabal macro (provided from GHC 8.0). +-- Stack no longer supports Cabal < 2.2 and, consequently, GHC versions before +-- GHC 8.4 or base < 4.11.0.0. Consequently, we do not need to test for the +-- existence of the MIN_VERSION_Cabal macro (provided from GHC 8.0). import Data.List ( stripPrefix ) import Distribution.ReadE ( ReadE (..) ) import Distribution.Simple.Configure ( getPersistBuildConfig ) --- | Temporary, can be removed if initialBuildSteps restored to Cabal's API. +-- Temporary, can be removed if initialBuildSteps restored to Cabal's API. #if MIN_VERSION_Cabal(3,11,0) import Distribution.Simple.Build ( writeBuiltinAutogenFiles ) #else @@ -19,41 +19,29 @@ #if MIN_VERSION_Cabal(3,11,0) import Distribution.Simple.Errors ( exceptionMessage ) #endif --- | Temporary, can be removed if initialBuildSteps restored to Cabal's API. +-- Temporary, can be removed if initialBuildSteps restored to Cabal's API. #if MIN_VERSION_Cabal(3,11,0) import Distribution.Simple.LocalBuildInfo ( componentBuildDir, withAllComponentsInBuildOrder ) #endif #if MIN_VERSION_Cabal(3,8,1) import Distribution.Simple.PackageDescription ( readGenericPackageDescription ) -#elif MIN_VERSION_Cabal(2,2,0) --- Avoid confusion with Cabal-syntax module of same name. --- readGenericPackageDescription was exported from module --- Distribution.PackageDescription.Parsec in Cabal-2.2.0.0. +#else +-- Avoid confusion with Cabal-syntax module of same name import "Cabal" Distribution.PackageDescription.Parsec ( readGenericPackageDescription ) -#elif MIN_VERSION_Cabal(2,0,0) --- readPackageDescription was renamed readGenericPackageDescription in --- Cabal-2.0.0.2. -import Distribution.PackageDescription.Parse ( readGenericPackageDescription ) -#else -import Distribution.PackageDescription.Parse ( readPackageDescription ) #endif import Distribution.Simple.Utils ( createDirectoryIfMissingVerbose, findPackageDesc ) #if MIN_VERSION_Cabal(3,8,1) import Distribution.Types.GenericPackageDescription ( GenericPackageDescription (..) ) -#elif MIN_VERSION_Cabal(2,0,0) --- Avoid confusion with Cabal-syntax module of same name. --- GenericPackageDescription was exported from module --- Distribution.Types.GenericPackageDescription in Cabal-2.0.0.2. +#else +-- Avoid confusion with Cabal-syntax module of same name import "Cabal" Distribution.Types.GenericPackageDescription ( GenericPackageDescription (..) ) -#else -import Distribution.PackageDescription ( GenericPackageDescription (..) ) #endif --- | Temporary, can be removed if initialBuildSteps restored to Cabal's API. +-- Temporary, can be removed if initialBuildSteps restored to Cabal's API. #if MIN_VERSION_Cabal(3,11,0) import Distribution.Types.ComponentLocalBuildInfo ( ComponentLocalBuildInfo ) import Distribution.Types.LocalBuildInfo ( LocalBuildInfo ) @@ -62,10 +50,6 @@ #endif import Distribution.Verbosity ( flagToVerbosity ) import Main --- Before base-4.11.0.0 (GHC 8.4.1), <> was not exported by Prelude. -#if !MIN_VERSION_base(4,11,0) -import Data.Semigroup ( (<>) ) -#endif import System.Environment ( getArgs ) mainOverride :: IO () @@ -115,12 +99,7 @@ msg2 = err #endif Right fp -> do - gpd <- -#if MIN_VERSION_Cabal(2,0,0) - readGenericPackageDescription verbosity fp -#else - readPackageDescription verbosity fp -#endif + gpd <- readGenericPackageDescription verbosity fp let pd = packageDescription gpd lbi <- getPersistBuildConfig rawBuildDir initialBuildSteps rawBuildDir pd lbi verbosity
stack.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: stack-version: 2.15.7+version: 3.1.1 license: BSD3 license-file: LICENSE maintainer: manny@fpcomplete.com@@ -29,69 +29,108 @@ ChangeLog.md README.md stack.yaml- doc/azure_ci.md- doc/build_command.md doc/build_overview.md doc/ChangeLog.md- doc/CI.md- doc/clean_command.md- doc/config_command.md+ doc/commands/bench_command.md+ doc/commands/build_command.md+ doc/commands/clean_command.md+ doc/commands/config_command.md+ doc/commands/docker_command.md+ doc/commands/dot_command.md+ doc/commands/eval_command.md+ doc/commands/exec_command.md+ doc/commands/ghc_command.md+ doc/commands/ghci_command.md+ doc/commands/haddock_command.md+ doc/commands/hoogle_command.md+ doc/commands/hpc_command.md+ doc/commands/ide_command.md+ doc/commands/index.md+ doc/commands/init_command.md+ doc/commands/install_command.md+ doc/commands/list_command.md+ doc/commands/ls_command.md+ doc/commands/new_command.md+ doc/commands/path_command.md+ doc/commands/purge_command.md+ doc/commands/query_command.md+ doc/commands/repl_command.md+ doc/commands/run_command.md+ doc/commands/runghc_command.md+ doc/commands/runhaskell_command.md+ doc/commands/script_command.md+ doc/commands/sdist_command.md+ doc/commands/setup_command.md+ doc/commands/templates_command.md+ doc/commands/test_command.md+ doc/commands/uninstall_command.md+ doc/commands/unpack_command.md+ doc/commands/update_command.md+ doc/commands/upgrade_command.md+ doc/commands/upload_command.md+ doc/community/index.md+ doc/configure/customisation_scripts.md+ doc/configure/environment_variables.md+ doc/configure/global_flags.md+ doc/configure/index.md+ doc/configure/yaml/index.md+ doc/configure/yaml/non-project.md+ doc/configure/yaml/project.md doc/CONTRIBUTING.md- doc/custom_snapshot.md- doc/debugging.md doc/dev_containers.md- doc/developing_on_windows.md- doc/docker_command.md- doc/docker_integration.md- doc/dot_command.md- doc/editor_integration.md- doc/environment_variables.md- doc/eval_command.md- doc/exec_command.md doc/faq.md- doc/ghc_command.md- doc/ghci.md- doc/global_flags.md doc/glossary.md- doc/GUIDE.md- doc/GUIDE_advanced.md- doc/hoogle_command.md- doc/hpc_command.md- doc/ide_command.md- doc/init_command.md doc/install_and_upgrade.md- doc/list_command.md- doc/lock_files.md- doc/ls_command.md- doc/new_command.md- doc/nix_integration.md- doc/nonstandard_project_init.md+ doc/maintainers/7zip.md+ doc/maintainers/archive/README.md+ doc/maintainers/archive/releases.md+ doc/maintainers/docker.md+ doc/maintainers/docker_images.md+ doc/maintainers/ghc.md+ doc/maintainers/haskellstack.org.md+ doc/maintainers/msys.md+ doc/maintainers/releases.md+ doc/maintainers/self-hosted_runners.md+ doc/maintainers/stack_errors.md+ doc/maintainers/team_process.md doc/other_resources.md- doc/pantry.md- doc/path_command.md- doc/purge_command.md- doc/query_command.md doc/README.md- doc/run_command.md- doc/runghc_command.md- doc/script_command.md- doc/scripts.md- doc/sdist_command.md- doc/setup_command.md- doc/shell_autocompletion.md doc/SIGNING_KEY.md- doc/Stack_and_VS_Code.md- doc/stack_root.md- doc/stack_work.md- doc/stack_yaml_vs_cabal_package_file.md- doc/templates_command.md- doc/travis_ci.md- doc/uninstall_command.md- doc/unpack_command.md- doc/update_command.md- doc/upgrade_command.md- doc/upload_command.md- doc/yaml_configuration.md+ doc/topics/azure_ci.md+ doc/topics/CI.md+ doc/topics/custom_snapshot.md+ doc/topics/debugging.md+ doc/topics/developing_on_windows.md+ doc/topics/docker_integration.md+ doc/topics/editor_integration.md+ doc/topics/haskell_and_c_code.md+ doc/topics/index.md+ doc/topics/lock_files.md+ doc/topics/nix_integration.md+ doc/topics/nonstandard_project_init.md+ doc/topics/package_location.md+ doc/topics/scripts.md+ doc/topics/shell_autocompletion.md+ doc/topics/snapshot_location.md+ doc/topics/Stack_and_VS_Code.md+ doc/topics/stack_root.md+ doc/topics/stack_work.md+ doc/topics/stack_yaml_vs_cabal_package_file.md+ doc/topics/travis_ci.md+ doc/tutorial/building_existing_projects.md+ doc/tutorial/building_your_project.md+ doc/tutorial/cabal_flags_and_ghc_options.md+ doc/tutorial/executing_commands.md+ doc/tutorial/hello_world_example.md+ doc/tutorial/index.md+ doc/tutorial/installed_package_databases.md+ doc/tutorial/locations_used_by_stack.md+ doc/tutorial/multi-package_projects.md+ doc/tutorial/stack_build_synonyms.md+ doc/tutorial/stack_build_targets.md+ doc/tutorial/stack_configuration.md+ doc/tutorial/tutorial_conclusion.md+ doc/tutorial/using_ghc_interactively.md src/setup-shim/StackSetupShim.hs tests/unit/package-dump/ghc-7.10.txt tests/unit/package-dump/ghc-7.8.4-osx.txt@@ -159,7 +198,6 @@ library exposed-modules:- Codec.Archive.Tar.Utf8 Control.Concurrent.Execute Data.Attoparsec.Args Data.Attoparsec.Combinators@@ -244,10 +282,10 @@ Stack.Options.NixParser Stack.Options.PackageParser Stack.Options.PathParser- Stack.Options.ResolverParser Stack.Options.SDistParser Stack.Options.ScriptParser Stack.Options.SetupParser+ Stack.Options.SnapshotParser Stack.Options.TestParser Stack.Options.UnpackParser Stack.Options.UpgradeParser@@ -317,8 +355,10 @@ Stack.Types.GlobalOpts Stack.Types.GlobalOptsMonoid Stack.Types.Installed+ Stack.Types.InterfaceOpt Stack.Types.IsMutable Stack.Types.LockFileBehavior+ Stack.Types.MsysEnvironment Stack.Types.NamedComponent Stack.Types.Nix Stack.Types.Package@@ -330,17 +370,19 @@ Stack.Types.ProjectAndConfigMonoid Stack.Types.ProjectConfig Stack.Types.PvpBounds- Stack.Types.Resolver Stack.Types.Runner Stack.Types.SCM Stack.Types.SetupInfo+ Stack.Types.Snapshot Stack.Types.SourceMap Stack.Types.StackYamlLoc Stack.Types.Storage Stack.Types.TemplateName Stack.Types.UnusedFlags+ Stack.Types.UploadOpts Stack.Types.Version Stack.Types.VersionedDownloadInfo+ Stack.Types.WantedCompilerSetter Stack.Uninstall Stack.Unpack Stack.Update@@ -364,7 +406,7 @@ -optP-Wno-nonportable-include-path -Widentities build-depends:- Cabal >=3.8.1.0,+ Cabal >=3.8.1.0 && <3.12, aeson >=2.0.3.0, aeson-warning-parser >=0.1.1, ansi-terminal >=1.0.2,@@ -380,16 +422,17 @@ conduit-extra >=1.3.6, containers >=0.6.7, crypton >=0.34,- directory >=1.3.8.4,+ directory >=1.3.8.5, echo >=0.1.4, exceptions >=0.10.7,- extra >=1.7.14,+ extra >=1.7.16, file-embed >=0.0.16.0, filelock >=0.1.1.7, filepath >=1.4.300.1, fsnotify >=0.4.1, generic-deriving >=1.14.5,- ghc-boot >=9.6.5,+ ghc-boot >=9.6.6,+ hashable >=1.4.4.0, hi-file-parser >=0.1.6.0, hpack >=0.36.0, hpc >=0.6.2.0,@@ -405,9 +448,9 @@ neat-interpolation >=0.5.1.4, open-browser >=0.2.1.0, optparse-applicative >=0.18.1.0,- pantry >=0.9.3.2 && <0.10.0,+ pantry >=0.10.0, path >=0.9.5,- path-io >=1.8.1,+ path-io >=1.8.2, persistent >=2.14.0.0 && <2.15, persistent-sqlite >=2.13.3.0, pretty >=1.1.3.6,@@ -418,12 +461,12 @@ rio-prettyprint >=0.1.8.0, split >=0.2.5, stm >=2.5.1.0,- tar >=0.5.1.1,+ tar >=0.6.2.0, template-haskell >=2.20.0.0, text >=2.0.2, time >=1.12.2, transformers >=0.6.1.0,- unix-compat >=0.7.1,+ unix-compat >=0.7.2, unordered-containers >=0.2.20, vector >=0.13.1.0, yaml >=0.11.11.2,@@ -491,7 +534,7 @@ -optP-Wno-nonportable-include-path -threaded -rtsopts build-depends:- Cabal >=3.8.1.0,+ Cabal >=3.8.1.0 && <3.12, aeson >=2.0.3.0, aeson-warning-parser >=0.1.1, ansi-terminal >=1.0.2,@@ -507,16 +550,17 @@ conduit-extra >=1.3.6, containers >=0.6.7, crypton >=0.34,- directory >=1.3.8.4,+ directory >=1.3.8.5, echo >=0.1.4, exceptions >=0.10.7,- extra >=1.7.14,+ extra >=1.7.16, file-embed >=0.0.16.0, filelock >=0.1.1.7, filepath >=1.4.300.1, fsnotify >=0.4.1, generic-deriving >=1.14.5,- ghc-boot >=9.6.5,+ ghc-boot >=9.6.6,+ hashable >=1.4.4.0, hi-file-parser >=0.1.6.0, hpack >=0.36.0, hpc >=0.6.2.0,@@ -532,9 +576,9 @@ neat-interpolation >=0.5.1.4, open-browser >=0.2.1.0, optparse-applicative >=0.18.1.0,- pantry >=0.9.3.2 && <0.10.0,+ pantry >=0.10.0, path >=0.9.5,- path-io >=1.8.1,+ path-io >=1.8.2, persistent >=2.14.0.0 && <2.15, persistent-sqlite >=2.13.3.0, pretty >=1.1.3.6,@@ -546,12 +590,12 @@ split >=0.2.5, stack, stm >=2.5.1.0,- tar >=0.5.1.1,+ tar >=0.6.2.0, template-haskell >=2.20.0.0, text >=2.0.2, time >=1.12.2, transformers >=0.6.1.0,- unix-compat >=0.7.1,+ unix-compat >=0.7.2, unordered-containers >=0.2.20, vector >=0.13.1.0, yaml >=0.11.11.2,@@ -598,7 +642,7 @@ -with-rtsopts=-N build-depends:- Cabal >=3.8.1.0,+ Cabal >=3.8.1.0 && <3.12, aeson >=2.0.3.0, aeson-warning-parser >=0.1.1, ansi-terminal >=1.0.2,@@ -614,20 +658,21 @@ conduit-extra >=1.3.6, containers >=0.6.7, crypton >=0.34,- directory >=1.3.8.4,+ directory >=1.3.8.5, echo >=0.1.4, exceptions >=0.10.7,- extra >=1.7.14,+ extra >=1.7.16, file-embed >=0.0.16.0, filelock >=0.1.1.7, filepath >=1.4.300.1, fsnotify >=0.4.1, generic-deriving >=1.14.5,- ghc-boot >=9.6.5,+ ghc-boot >=9.6.6,+ hashable >=1.4.4.0, hi-file-parser >=0.1.6.0, hpack >=0.36.0, hpc >=0.6.2.0,- hspec >=2.11.8,+ hspec >=2.11.9, http-client >=0.7.17, http-client-tls >=0.3.6.2, http-conduit >=2.3.8.3,@@ -641,9 +686,9 @@ open-browser >=0.2.1.0, optparse-applicative >=0.18.1.0, optparse-generic >=1.5.2,- pantry >=0.9.3.2 && <0.10.0,+ pantry >=0.10.0, path >=0.9.5,- path-io >=1.8.1,+ path-io >=1.8.2, persistent >=2.14.0.0 && <2.15, persistent-sqlite >=2.13.3.0, pretty >=1.1.3.6,@@ -654,12 +699,12 @@ rio-prettyprint >=0.1.8.0, split >=0.2.5, stm >=2.5.1.0,- tar >=0.5.1.1,+ tar >=0.6.2.0, template-haskell >=2.20.0.0, text >=2.0.2, time >=1.12.2, transformers >=0.6.1.0,- unix-compat >=0.7.1,+ unix-compat >=0.7.2, unordered-containers >=0.2.20, vector >=0.13.1.0, yaml >=0.11.11.2,@@ -722,7 +767,7 @@ -optP-Wno-nonportable-include-path -threaded build-depends:- Cabal >=3.8.1.0,+ Cabal >=3.8.1.0 && <3.12, QuickCheck >=2.14.3, aeson >=2.0.3.0, aeson-warning-parser >=0.1.1,@@ -739,20 +784,21 @@ conduit-extra >=1.3.6, containers >=0.6.7, crypton >=0.34,- directory >=1.3.8.4,+ directory >=1.3.8.5, echo >=0.1.4, exceptions >=0.10.7,- extra >=1.7.14,+ extra >=1.7.16, file-embed >=0.0.16.0, filelock >=0.1.1.7, filepath >=1.4.300.1, fsnotify >=0.4.1, generic-deriving >=1.14.5,- ghc-boot >=9.6.5,+ ghc-boot >=9.6.6,+ hashable >=1.4.4.0, hi-file-parser >=0.1.6.0, hpack >=0.36.0, hpc >=0.6.2.0,- hspec >=2.11.8,+ hspec >=2.11.9, http-client >=0.7.17, http-client-tls >=0.3.6.2, http-conduit >=2.3.8.3,@@ -765,9 +811,9 @@ neat-interpolation >=0.5.1.4, open-browser >=0.2.1.0, optparse-applicative >=0.18.1.0,- pantry >=0.9.3.2 && <0.10.0,+ pantry >=0.10.0, path >=0.9.5,- path-io >=1.8.1,+ path-io >=1.8.2, persistent >=2.14.0.0 && <2.15, persistent-sqlite >=2.13.3.0, pretty >=1.1.3.6,@@ -780,12 +826,12 @@ split >=0.2.5, stack, stm >=2.5.1.0,- tar >=0.5.1.1,+ tar >=0.6.2.0, template-haskell >=2.20.0.0, text >=2.0.2, time >=1.12.2, transformers >=0.6.1.0,- unix-compat >=0.7.1,+ unix-compat >=0.7.2, unordered-containers >=0.2.20, vector >=0.13.1.0, yaml >=0.11.11.2,
stack.yaml view
@@ -1,8 +1,16 @@-snapshot: lts-22.21 # GHC 9.6.5 +snapshot: lts-22.28 # GHC 9.6.6 +extra-deps: +# lts-22.28 provides pantry-0.9.3.2. +- pantry-0.10.0@sha256:6f99ee8d7cfeeb0e2513638618acf80c72d018e7f10120048fa120a409b9dcd2,7864 +# lts-22.28 provides tar-0.5.1.1, which does not support Unicode filenames: +- tar-0.6.2.0@sha256:619828cae098a7b6deeb0316e12f55011101d88f756787ed024ceedb81cf1eba,4576 +# lts-22.28 provides hpack-0.36.0 +- hpack-0.37.0@sha256:b7c91b0416a55c134172a9fd9a02f3815ba68c4b92cca4e320c36906d5e970e0,5187 + docker: enable: false - repo: quay.io/benz0li/ghc-musl:9.6.5 + repo: quay.io/benz0li/ghc-musl:9.6.6 nix: # --nix on the command-line to enable.
tests/integration/IntegrationSpec.hs view
@@ -31,6 +31,7 @@ ) import qualified RIO.Set as Set import qualified RIO.Text as T +import RIO.Time ( defaultTimeLocale, diffUTCTime, formatTime, getCurrentTime ) import System.Environment ( getExecutablePath, lookupEnv ) import System.Info ( os ) import System.PosixCompat.Files ( createSymbolicLink ) @@ -43,6 +44,7 @@ logInfo "Initiating Stack integration test running" options <- getRecord "Stack integration tests" + startTime <- getCurrentTime results <- runApp options $ do logInfo "Running with the following environment" proc "env" [] runProcess_ @@ -62,10 +64,12 @@ loop (idx + 1) rest' (res <> accum) loop (1 :: Int) (Set.toList tests) mempty - + finalTime <- getCurrentTime let (successes, failures) = partition ((== ExitSuccess) . snd) $ Map.toList results - + let timeDiff = diffUTCTime finalTime startTime + let timeDiffStr = formatTime defaultTimeLocale "%H:%M:%S - total %s seconds" timeDiff + logInfo $ "Integration tests ran in : " <> fromString timeDiffStr unless (null successes) $ do logInfo "Successful tests:" for_ successes $ \(x, _) -> logInfo $ "- " <> display x @@ -77,6 +81,7 @@ logInfo "Failed tests:" for_ failures $ \(x, ec) -> logInfo $ "- " <> display x <> " - " <> displayShow ec exitFailure + data Options = Options { optSpeed :: Maybe Speed
tests/integration/lib/StackTest.hs view
@@ -41,7 +41,7 @@ , isARM , isAarch64 , isMacOSX - , defaultResolverArg + , defaultSnapshotArg , removeFileIgnore , removeDirIgnore , withCwd @@ -163,8 +163,7 @@ if c == '>' then do -- Skip next character - _ <- liftIO $ hGetChar replStdoutHandle - pure () + void $ liftIO $ hGetChar replStdoutHandle else nextPrompt replCommand :: String -> Repl () @@ -362,8 +361,8 @@ -- a global context. The LTS major version here should match that of -- the main @stack.yaml@. -- -defaultResolverArg :: String -defaultResolverArg = "--snapshot=lts-22.21" +defaultSnapshotArg :: String +defaultSnapshotArg = "--snapshot=lts-22.28" -- | Remove a file and ignore any warnings about missing files. removeFileIgnore :: HasCallStack => FilePath -> IO ()
tests/unit/Stack/Config/DockerSpec.hs view
@@ -5,11 +5,11 @@ ( spec ) where -import Test.Hspec -import Stack.Prelude -import Stack.Types.Resolver -import RIO.Time (fromGregorian) -import Stack.Config.Docker (addDefaultTag) +import RIO.Time ( fromGregorian ) +import Stack.Config.Docker ( addDefaultTag ) +import Stack.Prelude +import Stack.Types.Snapshot ( AbstractSnapshot (..) ) +import Test.Hspec ( Spec, describe, it, shouldBe ) spec :: Spec spec = do @@ -19,11 +19,11 @@ addDefaultTag "foo/bar" Nothing - (Just $ ARResolver $ RSLSynonym $ LTS 1 2) + (Just $ ASSnapshot $ RSLSynonym $ LTS 1 2) `shouldBe` Just "foo/bar:lts-1.2" it "fails on nightly" $ addDefaultTag "foo/bar" Nothing - (Just $ ARResolver $ RSLSynonym $ Nightly $ fromGregorian 2018 1 1) + (Just $ ASSnapshot $ RSLSynonym $ Nightly $ fromGregorian 2018 1 1) `shouldBe` Nothing
tests/unit/Stack/ConfigSpec.hs view
@@ -27,7 +27,7 @@ import Stack.Options.GlobalParser ( globalOptsFromMonoid ) import Stack.Prelude import Stack.Runners ( withBuildConfig, withRunnerGlobal ) -import Stack.Types.BuildConfig ( BuildConfig (..), projectRootL ) +import Stack.Types.BuildConfig ( BuildConfig (..), configFileRootL ) import Stack.Types.BuildOpts ( BenchmarkOpts (..), BuildOpts (..), HaddockOpts (..) , TestOpts (..) @@ -53,12 +53,12 @@ sampleConfig :: String sampleConfig = - "snapshot: lts-22.21\n" ++ + "snapshot: lts-22.28\n" ++ "packages: ['.']\n" buildOptsConfig :: String buildOptsConfig = - "snapshot: lts-22.21\n" ++ + "snapshot: lts-22.28\n" ++ "packages: ['.']\n" ++ "build:\n" ++ " library-profiling: true\n" ++ @@ -71,6 +71,9 @@ " - \"--css=/home/user/my-css\"\n" ++ " open-haddocks: true\n" ++ " haddock-deps: true\n" ++ + " haddock-executables: true\n" ++ + " haddock-tests: true\n" ++ + " haddock-benchmarks: true\n" ++ " haddock-internal: true\n" ++ " haddock-hyperlink-source: false\n" ++ " haddock-for-hackage: false\n" ++ @@ -101,12 +104,15 @@ buildOptsHaddockForHackageConfig :: String buildOptsHaddockForHackageConfig = - "snapshot: lts-22.21\n" ++ + "snapshot: lts-22.28\n" ++ "packages: ['.']\n" ++ "build:\n" ++ " haddock: true\n" ++ " open-haddocks: true\n" ++ " haddock-deps: true\n" ++ + " haddock-executables: true\n" ++ + " haddock-tests: true\n" ++ + " haddock-benchmarks: true\n" ++ " haddock-internal: true\n" ++ " haddock-hyperlink-source: false\n" ++ " haddock-for-hackage: true\n" ++ @@ -114,24 +120,24 @@ hpackConfig :: String hpackConfig = - "snapshot: lts-22.21\n" ++ + "snapshot: lts-22.28\n" ++ "with-hpack: /usr/local/bin/hpack\n" ++ "packages: ['.']\n" resolverConfig :: String resolverConfig = - "resolver: lts-22.21\n" ++ + "resolver: lts-22.28\n" ++ "packages: ['.']\n" snapshotConfig :: String snapshotConfig = - "snapshot: lts-22.21\n" ++ + "snapshot: lts-22.28\n" ++ "packages: ['.']\n" resolverSnapshotConfig :: String resolverSnapshotConfig = - "resolver: lts-22.21\n" ++ - "snapshot: lts-22.21\n" ++ + "resolver: lts-22.28\n" ++ + "snapshot: lts-22.28\n" ++ "packages: ['.']\n" stackDotYaml :: Path Rel File @@ -181,11 +187,11 @@ it "parses snapshot using 'resolver'" $ inTempDir $ do loadProject resolverConfig $ \project -> - project.resolver `shouldBe` RSLSynonym (LTS 22 21) + project.snapshot `shouldBe` RSLSynonym (LTS 22 28) it "parses snapshot using 'snapshot'" $ inTempDir $ do loadProject snapshotConfig $ \project -> - project.resolver `shouldBe` RSLSynonym (LTS 22 21) + project.snapshot `shouldBe` RSLSynonym (LTS 22 28) it "throws if both 'resolver' and 'snapshot' are present" $ inTempDir $ do loadProject resolverSnapshotConfig (const (pure ())) @@ -232,6 +238,9 @@ } bopts.openHaddocks `shouldBe` True bopts.haddockDeps `shouldBe` Just True + bopts.haddockExecutables `shouldBe` True + bopts.haddockTests `shouldBe` True + bopts.haddockBenchmarks `shouldBe` True bopts.haddockInternal `shouldBe` True bopts.haddockHyperlinkSource `shouldBe` False bopts.haddockForHackage `shouldBe` False @@ -284,7 +293,7 @@ setCurrentDirectory childDir loadConfig' $ \config -> liftIO $ do bc <- runRIO config $ withBuildConfig ask - view projectRootL bc `shouldBe` parentDir + view configFileRootL bc `shouldBe` parentDir it "respects the STACK_YAML env variable" $ inTempDir $ do withSystemTempDir "config-is-here" $ \dir -> do @@ -294,8 +303,7 @@ withEnvVar "STACK_YAML" stackYamlFp $ loadConfig' $ \config -> liftIO $ do bc <- runRIO config $ withBuildConfig ask - bc.stackYaml `shouldBe` dir </> stackDotYaml - parent bc.stackYaml `shouldBe` dir + bc.configFile `shouldBe` Right (dir </> stackDotYaml) it "STACK_YAML can be relative" $ inTempDir $ do parentDir <- getCurrentDirectory >>= parseAbsDir @@ -306,12 +314,12 @@ packageYaml = childRel </> either impureThrow id (parseRelFile "package.yaml") createDirectoryIfMissing True $ toFilePath $ parent yamlAbs - writeFile (toFilePath yamlAbs) "snapshot: ghc-9.6.5" + writeFile (toFilePath yamlAbs) "snapshot: ghc-9.6.6" writeFile (toFilePath packageYaml) "name: foo" withEnvVar "STACK_YAML" (toFilePath yamlRel) $ loadConfig' $ \config -> liftIO $ do bc <- runRIO config $ withBuildConfig ask - bc.stackYaml `shouldBe` yamlAbs + bc.configFile `shouldBe` Right yamlAbs describe "defaultConfigYaml" $ it "is parseable" $ \_ -> do