Skip to content
This repository has been archived by the owner on Oct 7, 2020. It is now read-only.

Various improvements and fixes over shake install #1452

Merged
merged 29 commits into from
Nov 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6a8f89c
Use explicit list of ghc supported versions
jneira Nov 12, 2019
78fdd5b
Add lastest, change default to it add warn about build-all
jneira Nov 12, 2019
0e2646b
Fix getGhcPathOf for windows
jneira Nov 13, 2019
16be8e7
Sort installed ghcs to fix the lastest target
jneira Nov 13, 2019
bb61dd1
Fix error in splitPaths
jneira Nov 13, 2019
9e70be8
Fix ghc version used to install hie
jneira Nov 13, 2019
36fa815
Formatting options list of cabal build
jneira Nov 13, 2019
6831562
Merge branch 'improve-install' of https://github.com/jneira/haskell-i…
jneira Nov 14, 2019
6e0cf21
Use cabal options consistently
jneira Nov 14, 2019
bf7d4b4
Update documentation about build system
jneira Nov 14, 2019
8e909e8
Mention cabal issue about set custom project file
jneira Nov 14, 2019
0f72de0
Use TargetDescription to print targets
jneira Nov 14, 2019
2140a5a
Remove unnecessary catch over lookupEnv
jneira Nov 14, 2019
15cf8ad
Run stack-install-cabal in azure ci
jneira Nov 14, 2019
7d99319
Change macos STACK_ROOT to avoid permission issues
jneira Nov 14, 2019
6f18dca
Correct suggestion of lastest target
jneira Nov 14, 2019
1876ab5
replace last by lastest
jneira Nov 14, 2019
2c82368
Replace lastest by latest
jneira Nov 15, 2019
72de08b
Use v2 prefix intead new
jneira Nov 15, 2019
e270032
Rephrasing alternative to build-all
jneira Nov 15, 2019
118525d
Replace cabal command suffix and fix installing steps
jneira Nov 15, 2019
db23fa5
Correct typo
jneira Nov 15, 2019
27fb514
Use existing exe function from Shake
jneira Nov 15, 2019
c63d0be
Test build-latest target
jneira Nov 15, 2019
ab1dde8
Remove build-all target
jneira Nov 15, 2019
0ae6936
Use builtin splitSearchPath
jneira Nov 17, 2019
f37b987
Make clear requirements for cabal
jneira Nov 18, 2019
756d51d
Use ghc versions from stack-*.yaml files
jneira Nov 19, 2019
cd27b1e
Correct per-os bashrc in win and macos
jneira Nov 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .azure/linux-installhs-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,12 @@ jobs:
- bash: |
source .azure/linux.bashrc
stack install.hs help
displayName: Run help of `instal.hs`
displayName: Run help of `install.hs`
- bash: |
source .azure/linux.bashrc
stack install.hs stack-install-cabal
displayName: Run stack-install-cabal target of `install.hs`
- bash: |
source .azure/linux.bashrc
stack install.hs build-latest
displayName: Run build-latest target of `install.hs`
10 changes: 9 additions & 1 deletion .azure/macos-installhs-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,12 @@ jobs:
- bash: |
source .azure/macos.bashrc
stack install.hs help
displayName: Run help of `instal.hs`
displayName: Run help of `install.hs`
- bash: |
source .azure/macos.bashrc
stack install.hs stack-install-cabal
displayName: Run stack-install-cabal target of `install.hs`
- bash: |
source .azure/macos.bashrc
stack install.hs build-latest
displayName: Run build-latest target of `install.hs`
2 changes: 1 addition & 1 deletion .azure/macos-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
stack-8.4.2:
YAML_FILE: stack-8.4.2.yaml
variables:
STACK_ROOT: /Users/vsts/.stack
STACK_ROOT: $(Build.SourcesDirectory)/.stack
steps:
- task: CacheBeta@0
inputs:
Expand Down
10 changes: 9 additions & 1 deletion .azure/windows-installhs-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@ jobs:
- bash: |
source .azure/windows.bashrc
stack install.hs help
displayName: Run help of `instal.hs`
displayName: Run help of `install.hs`
- bash: |
source .azure/windows.bashrc
stack install.hs stack-install-cabal
displayName: Run stack-install-cabal target of `install.hs`
- bash: |
source .azure/windows.bashrc
stack install.hs build-latest
displayName: Run build-latest target of `install.hs`
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ cabal v2-run ./install.hs --project-file install/shake.project <target>

Running the script with cabal on windows requires a cabal version greater or equal to `3.0.0.0`.

Unfortunately, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected.
Unfortunately, it is still required to have `stack` installed so that the install-script can locate the `local-bin` directory (on Linux `~/.local/bin`) and copy the `hie` binaries to `hie-x.y.z`, which is required for the `hie-wrapper` to function as expected. There are plans to remove this requirement and let users build hie only with one build tool or another.

For brevity, only the `stack`-based commands are presented in the following sections.

Expand Down Expand Up @@ -244,13 +244,12 @@ stack ./install.hs hie-8.4.4
stack ./install.hs build-data
```

The Haskell IDE Engine can also be built with `cabal new-build` instead of `stack build`.
The Haskell IDE Engine can also be built with `cabal v2-build` instead of `stack build`.
This has the advantage that you can decide how the GHC versions have been installed.
However, this approach does currently not work for windows due to a missing feature upstream.
To see what GHC versions are available, the command `stack install.hs cabal-ghcs` can be used.
It will list all GHC versions that are on the path and their respective installation directory.
If you think, this list is incomplete, you can try to modify the PATH variable, such that the executables can be found.
Note, that the targets `cabal-build`, `cabal-build-data` and `cabal-build-all` depend on the found GHC versions.
Note, that the targets `cabal-build` and `cabal-build-data` depend on the found GHC versions.
They install Haskell IDE Engine only for the found GHC versions.

An example output is:
Expand All @@ -272,12 +271,6 @@ stack install.hs cabal-hie-8.4.4
stack install.hs cabal-build-data
```

To install HIE for all GHC versions that are present on your system, use:

```bash
stack ./install.hs cabal-build-all
```

In general, targets that use `cabal` instead of `stack` are prefixed with `cabal-*` and are identical to their counterpart, except they do not install a GHC if it is missing but fail.

##### Multiple versions of HIE (optional)
Expand Down
25 changes: 11 additions & 14 deletions docs/Build.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ The design of the build system has the following main goals:
- `stack`
- `git`
* is completely functional right after a simple `git clone` and after every `git pull`
* one-stop-shop for building and naming all executables required for using `hie` in IDEs.
* prevents certain build failures by either identifying a failed precondition (such as wrong `stack` version) or by performing the necessary steps so users can't forget them (such as invoking `git` to update submodules)


Expand All @@ -28,8 +27,9 @@ See the project's `README` for detailed information about installing `hie`.
The build script `install.hs` defines several targets using the `shake` build system. The targets are roughly:

* `hie-*`: builds and installs the `hie` binaries. Also renames the binaries to contain the correct version-number.
* `build`: builds and installs `hie` binaries for all supported `ghc` versions.
* `build-latest`: builds and installs `hie` for the latest available and supported `ghc` version.
* `build-data`: builds the hoogle-db required by `hie`
* `build`: builds and installs `hie` for the latest supported `ghc` version (like `build-latest`) and the hoogle-db (like `build-data`)
* `cabal-*`: execute the same task as the original target, but with `cabal` instead of `stack`

Each `stack-*.yaml` contains references to packages in the submodules. Calling `stack` with one of those causes the build to fail if the submodules have not been initialized already. The file `shake.yaml` solves this issue invoking the `git` binary itself to update the submodules. Moreover, it specifies the correct version of `shake` and is used for installing all run-time dependencies such as `cabal` and `hoogle` if necessary.
Expand All @@ -38,7 +38,7 @@ Each `stack-*.yaml` contains references to packages in the submodules. Calling `

`hie` depends on a correct environment in order to function properly:

* `cabal-install`: If no `cabal` executable can be found or has an outdated version, `cabal-install` is installed via `stack`.
* `cabal-install`: This dependency is required by `hie` to handle correctly projects that are not `stack` based (without `stack.yaml`). You can install an appropiate version using `stack` with the `stack-install-cabal` target.
jneira marked this conversation as resolved.
Show resolved Hide resolved
* The `hoogle` database: `hoogle generate` needs to be called with the most-recent `hoogle` version.

### Steps to build `hie`
Expand All @@ -47,16 +47,15 @@ Installing `hie` is a multi-step process:

1. `git submodule sync && git submodule update --init`
2. `hoogle generate` (`hoogle>=5.0.17` to be safe)
3. ensure that `cabal-install` is installed in the correct version
4. `stack --stack-yaml=stack-<X>.yaml install` or `cabal new-install -w ghc-<X>`
5. rename `hie` binary to `hie-<X>` in `$HOME/.local/bin`, where `<X>` is the GHC version used
6. repeat step 4 and 5 for all desired GHC versions
3. `stack --stack-yaml=stack-<X>.yaml install` or `cabal v2-install -w ghc-<X>`
4. rename `hie` binary to `hie-<X>` in `$HOME/.local/bin`, where `<X>` is the GHC version used
5. repeat step 3 and 4 for all desired GHC versions

This ensures that a complete install is always possible after each `git pull` or a `git clone`.

#### Building `hie` with profiling support

To build `hie` with profiling enabled `cabal new-install` needs to be used instead of `stack`.
To build `hie` with profiling enabled `cabal v2-install` needs to be used instead of `stack`.

Configure `cabal` to enable profiling by setting `profiling: True` in `cabal.project.local` for all packages. If that file does not already exist, create it as follows:

Expand All @@ -71,7 +70,7 @@ Then `hie` can be compiled for a specific GHC version:

```bash
export GHCP=<path-to-ghc-binary>
cabal new-install exe:hie -w $GHCP \
cabal v2-install exe:hie -w $GHCP \
--write-ghc-environment-files=never --symlink-bindir=$HOME/.local/bin \
--overwrite-policy=always --reinstall
```
Expand All @@ -90,19 +89,17 @@ The final step is to configure the `hie` client to use a custom `hie-wrapper` sc
The `install.hs` script performs some checks to ensure that a correct installation is possible and provide meaningful error messages for known issues.

* `stack` needs to be up-to-date. Version `1.9.3` is required
* `cabal` needs to be up-to-date. Version `2.4.1.0` is required to *use* haskell-ide-engine until the pull request #1126 is merged. Unfortunately cabal version `3.0.0.0` is needed to *install* hie in windows systems but that inconsistence will be fixed by the mentioned pull request.
* `ghc-8.6.3` is broken on windows. Trying to install `hie-8.6.3` on windows is not possible.
* `cabal new-build` does not work on windows at the moment. All `cabal-*` targets exit with an error message about that.
* When the build fails, an error message, that suggests to remove `.stack-work` directory, is displayed.

### Tradeoffs

#### `stack` is a build dependency

Currently, it is not possible to build all `hie-*` executables automatically without `stack`, since the `install.hs` script is executed by `stack`.
Currently, `stack` is needed even if you run the script with `cabal` to get the path where install the binaries but there are plans to remove that dependency (see #1380).

We are open to suggestions of other build systems that honor the requirements above, but are executable without `stack`.

#### `install.hs` installs a GHC before running
#### run `install.hs` with `stack` installs a GHC before running

Before the code in `install.hs` can be executed, `stack` installs a `GHC`, depending on the `resolver` field in `shake.yaml`. This is necessary if `install.hs` should be completely functional right after a fresh `git clone` without further configuration.

Expand Down
1 change: 1 addition & 0 deletions install.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ build-depends:
-- * `stack install.hs <target>`

-- TODO: set `shake.project` in cabal-config above, when supported
-- (see https://github.com/haskell/cabal/issues/6353)

import HieInstall (defaultMain)

Expand Down
20 changes: 15 additions & 5 deletions install/src/Cabal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,29 @@ cabalBuildData = do
execCabal_ ["v2-build", "hoogle"]
execCabal_ ["v2-exec", "hoogle", "generate"]

cabalBuildHie :: VersionNumber -> Action ()
cabalBuildHie versionNumber = do
ghcPath <- getGhcPathOf versionNumber >>= \case
getGhcPathOfOrThrowError :: VersionNumber -> Action GhcPath
getGhcPathOfOrThrowError versionNumber =
getGhcPathOf versionNumber >>= \case
Nothing -> do
printInStars $ ghcVersionNotFoundFailMsg versionNumber
error (ghcVersionNotFoundFailMsg versionNumber)
Just p -> return p

cabalBuildHie :: VersionNumber -> Action ()
cabalBuildHie versionNumber = do
ghcPath <- getGhcPathOfOrThrowError versionNumber
execCabal_
["v2-build", "-w", ghcPath, "--write-ghc-environment-files=never", "--max-backjumps=5000", "--disable-tests"]
[ "v2-build"
, "-w", ghcPath
, "--write-ghc-environment-files=never"
, "--max-backjumps=5000"
, "--disable-tests"]

cabalInstallHie :: VersionNumber -> Action ()
cabalInstallHie versionNumber = do
localBin <- getLocalBin
cabalVersion <- getCabalVersion
ghcPath <- getGhcPathOfOrThrowError versionNumber

let isCabal3 = checkVersion [3,0,0,0] cabalVersion
installDirOpt | isCabal3 = "--installdir"
Expand All @@ -53,8 +62,9 @@ cabalInstallHie versionNumber = do
| otherwise = []
execCabal_ $
[ "v2-install"
, "-w", ghcPath
, "--write-ghc-environment-files=never"
, installDirOpt ++ "=" ++ localBin
, installDirOpt, localBin
, "exe:hie"
, "--overwrite-policy=always"
]
Expand Down
25 changes: 15 additions & 10 deletions install/src/Env.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import Development.Shake.FilePath
import System.Info ( os
, arch
)
import Data.Maybe ( isJust )
import Data.Maybe ( isJust
, isNothing
, mapMaybe
)
import System.Directory ( findExecutable
, findExecutables
, listDirectory
Expand All @@ -17,13 +20,13 @@ import Data.Function ( (&)
, on
)
import Data.List ( sort
, sortBy
, isInfixOf
, nubBy
)
import Data.Ord ( comparing )
import Control.Monad.Extra ( mapMaybeM )
import Data.Maybe ( isNothing
, mapMaybe
)

import qualified Data.Text as T

import Version
Expand All @@ -45,15 +48,18 @@ findInstalledGhcs = do
hieVersions <- getHieVersions :: IO [VersionNumber]
knownGhcs <- mapMaybeM
(\version -> getGhcPathOf version >>= \case
Nothing -> return Nothing
Just p -> return $ Just (version, p)
Nothing -> return Nothing
Just p -> return $ Just (version, p)
)
(reverse hieVersions)
availableGhcs <- getGhcPaths
-- filter out not supported ghc versions
availableGhcs <- filter ((`elem` hieVersions) . fst) <$> getGhcPaths
return
-- sort by version to make it coherent with getHieVersions
$ sortBy (comparing fst)
-- nub by version. knownGhcs takes precedence.
$ nubBy ((==) `on` fst)
-- filter out stack provided GHCs
-- filter out stack provided GHCs (assuming that stack programs path is the default one in linux)
$ filter (not . isInfixOf ".stack" . snd) (knownGhcs ++ availableGhcs)

-- | Get the path to a GHC that has the version specified by `VersionNumber`
Expand All @@ -63,7 +69,7 @@ findInstalledGhcs = do
-- command fits to the desired version.
getGhcPathOf :: MonadIO m => VersionNumber -> m (Maybe GhcPath)
getGhcPathOf ghcVersion =
liftIO $ findExecutable ("ghc-" ++ ghcVersion) >>= \case
liftIO $ findExecutable ("ghc-" ++ ghcVersion <.> exe) >>= \case
Nothing -> lookup ghcVersion <$> getGhcPaths
path -> return path

Expand All @@ -87,7 +93,6 @@ ghcVersionNotFoundFailMsg versionNumber =
-- | Defines all different hie versions that are buildable.
--
-- The current directory is scanned for `stack-*.yaml` files.
-- On windows, `8.6.3` is excluded as this version of ghc does not work there
getHieVersions :: MonadIO m => m [VersionNumber]
getHieVersions = do
let stackYamlPrefix = T.pack "stack-"
Expand Down
Loading