Skip to content

Commit 719d635

Browse files
committed
Improve online documentation
1 parent a4f53d9 commit 719d635

File tree

1 file changed

+187
-45
lines changed

1 file changed

+187
-45
lines changed

doc/script_command.md

+187-45
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
~~~text
66
stack script [--package PACKAGE] FILE
7-
[-- ARGUMENT(S) (e.g. stack script X.hs -- argument(s) to program)]
7+
[-- ARGUMENT(S) (e.g. stack script X.hs -- argument(s) to program).]
88
[--compile | --optimize] [--[no-]use-root] [--ghc-options OPTIONS]
99
[--extra-dep PACKAGE-VERSION] [--no-run]
1010
~~~
@@ -13,64 +13,132 @@ The `stack script` command either runs a specified Haskell source file (using
1313
GHC's `runghc`) or, optionally, compiles such a file (using GHC) and, by
1414
default, runs it.
1515

16-
Unlike the [`stack ghc`](ghc_command.md) and [`stack runghc`](runghc_command.md)
17-
commands, the command ignores any project-level configuration file
18-
(`stack.yaml`, by default) (including in the `global-project` directory in the
19-
Stack root). Consequently, a snapshot must be specified on the command line
20-
(with the `--snapshot` option). For example:
16+
## Global configuration files
2117

22-
~~~text
23-
stack script --snapshot lts-22.21 MyScript.hs
24-
~~~
18+
Non-project level configuration options in global configuration files
19+
(`config.yaml`) are not ignored by the `stack script` command.
2520

2621
!!! info
2722

28-
Non-project level configuration options in global configuration files
29-
(`config.yaml`), are not ignored by the `stack script` command. Such options
30-
may be useful if [`allow-newer`](yaml_configuration.md#allow-newer) and/or
23+
Non-project level configuration options may be useful if
24+
[`allow-newer`](yaml_configuration.md#allow-newer) and/or
3125
[`allow-newer-deps`](yaml_configuration.md#allow-newer-deps) are required.
3226

33-
The `stack script` command behaves as if the `--install-ghc` flag had been
34-
passed at the command line.
27+
## Project-level configuration file
3528

36-
Everything after `--` on the command line is interpreted as a command line
37-
argument to be passed to what is run.
29+
The `stack script` command ignores any project-level configuration file
30+
(`stack.yaml`, by default), including in the `global-project` directory in the
31+
Stack root.
32+
33+
!!! info
34+
35+
The `stack script` command can be contrasted with the
36+
[`stack ghc`](ghc_command.md) and [`stack runghc`](runghc_command.md)
37+
commands, which do not ignore any project-level configuration file.
38+
39+
## GHC
40+
41+
The `stack script` command behaves as if the
42+
[`--install-ghc`](global_flags.md#--no-install-ghc-flag) flag had been passed at
43+
the command line.
3844

39-
A package can be added to the snapshot on the command line with the
45+
## Snapshot and extra-deps
46+
47+
A snapshot must be specified on the command line, using the `--snapshot` option.
48+
For example:
49+
50+
~~~text
51+
stack script --snapshot lts-22.21 MyScript.hs
52+
~~~
53+
54+
A package version can be added to the snapshot on the command line with the
4055
`--extra-dep` option (which can be specified multiple times).
4156

42-
Each required package can be specified by name on the command line with the
43-
`--package` option (which can be specified multiple times). A single `--package`
44-
option can also refer to a list of package names, separated by a space or comma
45-
character. If the package is not in the snapshot, the most recent version in the
46-
package index (e.g. Hackage) will be obtained.
57+
GHC boot packages that have been 'replaced' (see further below) can be specified
58+
as an `--extra-dep`.
59+
60+
## Required packages
61+
62+
The names of required packages can be either deduced or specified.
63+
64+
The `base` package associated with the version of GHC specified by the snapshot
65+
is always available.
66+
67+
If no packages are specified, all the required packages that are in the snapshot
68+
or are a GHC boot package (packages that come with GHC and are included in GHC's
69+
global package database), will be deduced by reference to the `import`
70+
statements in the source file. In that regard, Stack assumes that:
4771

48-
If no packages are specified in that way, all the required packages that are in
49-
the snapshot or are a GHC boot package (packages that come with GHC and are
50-
included in GHC's global package database) will be deduced by reference to the
51-
`import` statements in the source file. The `base` package associated with the
52-
version of GHC specified by the snapshot is always available.
72+
* a line that begins `import` is an `import` statement;
73+
* `import` may be followed by `qualified` on the same line;
74+
* consistent with GHC's
75+
[`PackageImports`](https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/package_qualified_imports.html)
76+
language extension, that if `import` or `import qualified` is followed by
77+
`"<name>"` on the same line, that `<name>` is the name of a required package;
78+
* otherwise, `import` or `import qualified` is followed by the module name on
79+
the same line. Stack will not deduce the names of hidden packages from
80+
module names or the names of blacklisted packages.
81+
82+
!!! note
83+
84+
The first time that Stack deduces package names from module names can take
85+
some time. Use the `--verbose` option to understand Stack's progress.
86+
87+
!!! info
88+
89+
Certain packages are blacklisted because they expose one or more modules
90+
with names that are the same as modules exposed by more popular packages.
91+
The blacklisted packages are `Glob`, `HTF`, `async-dejafu`,
92+
`binary-ieee754`, `cipher-aes`, `cipher-blowfish`, `cipher-camellia`,
93+
`cipher-des`, `cipher-rc4`, `control-monad-free`, `courier`, `crypto-api`,
94+
`crypto-cipher-types`, `crypto-numbers`, `crypto-pubkey`, `crypto-random`,
95+
`cryptohash`, `cryptohash-conduit`, `cryptohash-md5`, `cryptohash-sha1`,
96+
`cryptohash-sha256`, `fay-base`, `gl`, `gtk3`, `hashmap`, `hledger-web`,
97+
`hxt-unicode`, `kawhi`, `language-c`, `log`, `monad-extras`, `monads-tf`,
98+
`nanospec`, `newtype-generics`, `objective`, `plot-gtk3`, `prompt`,
99+
`regex-compat-tdfa`, `regex-pcre-builtin`, `rerebase`, `svg-tree` and `zip`.
100+
101+
Alternatively, each required package can be specified by name on the command
102+
line with the `--package` option (which can be specified multiple times). A
103+
single `--package` option can also refer to a list of package names, separated
104+
by a space or comma character. If the package is not in the snapshot, the most
105+
recent version in the package index (e.g. Hackage) will be obtained.
53106

54107
If a required package is a GHC boot package, the behaviour can be complex. If
55108
the boot package has not been 'replaced', then it will be used in Stack's build
56109
plan. However, if the boot package has been 'replaced', the latest version of
57110
that package in the package index will be used in Stack's build plan, which may
58111
differ from the version provided by the version of GHC specified by the
59-
snapshot. A boot package will be treated as 'replaced' if the package i
112+
snapshot. A boot package will be treated as 'replaced' if the package is
60113
included directly in the Stackage snapshot or it depends on a package included
61114
directly in the snapshot. Stackage snapshots do not include directly most boot
62115
packages but some snapshots may include directly some boot packages. In
63116
particular, some snapshots include directly `Win32` (which is a boot package on
64-
Windows) while others do not. For example, if `Cabal` (a boot package) is a
65-
required package then, with Stackage snapshot LTS Haskell 20.25, Stack will:
66-
67-
* on Windows, try to construct a build plan based on the latest version of
68-
`Cabal` in the package index (because that snapshot includes `Win32` directly,
69-
and `Cabal` depends on `Win32` and so is treated as 'replaced'); and
70-
* on non-Windows, use the boot package in the build plan (because `Cabal` is not
71-
'replaced').
72-
73-
Boot packages that have been 'replaced' can be specified as an `--extra-dep`.
117+
Windows) while others do not.
118+
119+
!!! warning
120+
121+
GHC has the concept of 'installed packages' (which differ from 'Cabal
122+
packages') in package databases. An installed package has a name. An
123+
installed package corresponding to the main (unnamed) library of a Cabal
124+
package has the same name as the Cabal package. An installed package
125+
corresponding to a sub-library of a Cabal package has a 'munged' name that
126+
reflects the name of the Cabal package and the name of the sub-library. An
127+
installed package corresponding to a sub-library also has a `package-name`,
128+
which is the name of the Cabal package.
129+
130+
The `--package` option of `stack script` makes use of GHC's `-package`
131+
option to expose an installed package. Unfortunately, the latter treats
132+
`package-name` (if it exists) as if it were also the name of the installed
133+
package. That means, for a Cabal package with one or more sub-libraries, the
134+
GHC option `-package=<name>` cannot distinguish between (a) the installed
135+
package `<name>` corresponding to the main library of Cabal package `<name>`
136+
and (b) an installed package corresponding to a sub-library of that Cabal
137+
package. The installed package that GHC picks to expose is indeterminate.
138+
This can cause GHC to pick the wrong installed package and to report that it
139+
cannot load a module because it is a member of a hidden package.
140+
141+
## Compilation
74142

75143
The source file can be compiled by passing either the `--compile` flag (no
76144
optimization) or the `--optimize` flag (compilation with optimization). If the
@@ -83,11 +151,20 @@ outputs to a script-specific location in the `scripts` directory of the Stack
83151
root. The location reflects the absolute path to the source file, but ignoring
84152
the drive. This can avoid clutter in the source file directory.
85153

154+
## GHC options
155+
86156
Additional options can be passed to GHC using the `--ghc-options` option.
87157

158+
## Script arguments
159+
160+
Everything after `--` on the command line is interpreted as a command line
161+
argument to be passed to what is run.
162+
88163
## Examples
89164

90-
For example, Haskell source file `MyScript.hs` at location
165+
### Example 1
166+
167+
A Haskell source file `MyScript.hs` at location
91168
`<drive>Users/jane/my-project` (where `<drive>` could be `/` on Unix-like
92169
operating systems or `C:/` or similar on Windows):
93170

@@ -112,24 +189,64 @@ can be compiled and run, with arguments, with:
112189
stack --snapshot lts-22.21 script --package acme-missiles --compile MyScript.hs -- "Don't panic!" "Duck and cover!"
113190
~~~
114191

192+
`acme-missiles-0.3` (the most recent version in the package index) will be used.
193+
115194
All the compilation outputs (like `Main.hi`, `Main.o`, and the executable
116195
`MyScript`) will be written to the `my-project` directory.
117196

118197
If compiled and run with the additional flag `--use-root`, all the compilation
119198
outputs will be written to a directory named `MyScript.hs` at
120199
`Users/jane/my-project/` in the `scripts` directory of the Stack root.
121200

122-
For example, consider the following script extract, based on snapshot Stackage
123-
LTS Haskell 20.25, where considerations on Windows differ from non-Windows. The
201+
### Example 2
202+
203+
As for Example 1, but `acme-missiles-0.2` is specified by adding it to the
204+
snapshot as an extra-dep. The `stack script` command is specified using Stack's
205+
[script interpreter](scripts.md).
206+
207+
~~~haskell
208+
{- stack script
209+
-- snapshot lts-22.21
210+
-- extra-dep acme-missiles-0.2
211+
-- package acme-missiles
212+
-}
213+
module Main (main) where
214+
215+
import Data.List (intercalate)
216+
import System.Environment (getArgs)
217+
218+
import Acme.Missiles (launchMissiles)
219+
220+
main :: IO ()
221+
main = do
222+
advices <- getArgs
223+
launchMissiles
224+
putStrLn $ intercalate "\n" advices
225+
~~~
226+
227+
~~~text
228+
stack MyScript.hs "Don't panic!" "Duck and cover!"
229+
~~~
230+
231+
### Example 3
232+
233+
Stackage snapshot LTS Haskell 20.25 includes GHC boot package `Win32` directly.
234+
On Windows only, GHC boot packages `Cabal`, `directory`, `process` and `time`
235+
all depend on `Win32` and, consequently, are all treated as 'replaced'.
236+
Consequently, for example, Stack will:
237+
238+
* on Windows, try to construct a build plan based on the latest version of
239+
`Cabal` in the package index; and
240+
* on non-Windows, use the boot package in the build plan (because `Cabal` is not
241+
'replaced').
242+
243+
Consider also the following script extract, based on snapshot Stackage
244+
LTS Haskell 20.25, where considerations on Windows differ from non-Windows. The
124245
`stack script` command is specified using Stack's
125246
[script interpreter](scripts.md).
126247

127248
=== "Windows"
128249

129-
The snapshot includes `Win32` directly. As a consequence, GHC boot packages
130-
`directory`, `process` and `time` (which depend on `Win32`) are all treated
131-
as 'replaced'.
132-
133250
~~~haskell
134251
{- stack script
135252
--snapshot lts-20.25
@@ -184,3 +301,28 @@ LTS Haskell 20.25, where considerations on Windows differ from non-Windows. The
184301

185302
All the other dependencies required are either GHC boot packages (which have
186303
not been 'replaced') or in the snapshot.
304+
305+
### Example 4
306+
307+
A Haskell source file `MyScript.hs`, as follows:
308+
309+
~~~haskell
310+
{- stack script
311+
--snapshot lts-22.21
312+
-}
313+
314+
{-# LANGUAGE OverloadedStrings #-}
315+
{-# LANGUAGE PackageImports #-}
316+
317+
module Main (main) where
318+
319+
import "text" Data.Text (Text (..), unpack)
320+
321+
main :: IO ()
322+
main = putStrLn $ unpack "This is text."
323+
~~~
324+
325+
As module `Data.Text` is exposed by a number of packages that are included,
326+
directly or indirectly, in the specified snapshot (`incipit-base`,
327+
`incipit-core`, `relude` and `text`), `PackageImports` and `"text"` are required
328+
to specify which module is being imported.

0 commit comments

Comments
 (0)