Haskell & AppVeyor Chocolatey Introduction
July 22, 2018
For those who are unaware, Windows has had quite a push lately to provide script-able
ways to install packages. One such attempt that has gained quite a lot of traction is
Chocolatey https://chocolatey.org/.
Chocolatey also contains some of my own packages for installing GHC and cabal
(along with packages to fully automate setting up a GHC dev environment etc, more on these
at a later date).
The GHC package https://chocolatey.org/packages/ghc goes all the way back to GHC 6.10.1
and the cabal-install package https://chocolatey.org/packages/cabal to cabal-install 0.6.0.
These are quite handy for those who use the cabal+ghc workflow like myself and like to switch
compiler versions easy, or script environment setups.
After installing Chocolatey
one can install GHC simply using the command
choco install ghc
refreshenv
which will install and reconfigure the latest released GHC along with the latest
cabal-install. The refreshenv is needed in order to reload the PATH variables which
an install of the package changes. This is normally not needed for a Chocolatey package
but for GHC it is needed to preserve an assumption the GHC bindists make about their layout.
For older packages this dependencies on cabal isn’t specified so one way that works
with all versions is:
choco install cabal ghc
refreshenv
You can also use chocolatey to install the latest GHC Alpha, Beta and RC simply by adding
-pre to the install command. e.g.:
choco install cabal ghc -pre
refreshenv
An existing install can be upgraded using the upgrade command
choco upgrade ghc
refreshenv
and specific versions can be installed using --version:
choco install ghc --version 8.4.1
refreshenv
The chocolatey packages are self contained, which means you can also install multiple GHC
versions side-by-side and switch between them using the full versioned form. e.g.
choco install ghc --version 8.4.1
choco install ghc --version 8.2.2 -m
refreshenv
Will install both GHC 8.4.1 and 8.2.2 at once, with GHC 8.4.1 being accessible
by the un-suffixed ghc command. The -m option means allow multiple which won’t
force only one version to be installed. Using cabal new-build’s -w flag you can
easily switch between the two versions:
cabal new-build -w ghc-8.4.1.exe
cabal new-build -w ghc-8.2.2.exe
So take a look at the Chocolatey based distributions, which can also be used to install a full
Haskell dev environment using e.g. vscode.
choco install ghc vscode
Update-SessionEnvironment
code --install-extension justusadam.language-haskell
For those who like to test their packages against the bleeding edge, just like Hvr’s
excellent PPA for Ubuntu I provide nightlies
for both GHC and
cabal-install under my NuGet feed.
The current build frequency for both is Nightly, but depending on popularity/activity I may scale them
to weekly or longer. Builds are retained for a year before they are deleted, just as before I may extend or
shorten the period in the future depending on feedback. GHC builds are currently 64 bit ONLY.
To use them first add my NuGet feed as a Chocolatey source and that will give you access to the
packages cabal-head and ghc-head.
choco source add -n mistuke -s https://www.myget.org/F/mistuke/api/v2
choco install ghc-head cabal-head -pre
refreshenv
ghc-head will always install cabal-head, this is because newer GHC may require a bleeding edge
Cabal. If you have them already installed you can just upgrade existing nightlies or downgrade
as long as the build is still around. These are unsupported builds, If you do feel like you’ve found
a genuine bug, when reporting them my package feed can tell you which commit the build was made from.
In the future I will also be providing some of my own internal builds for wider testing before they get
merged into upstream master.
AppVeyor Continuous Integration
AppVeyor comes with Chocolatey pre-installed. Which means you can use the exact same commands
as above to set up a CI script for your project using AppVeyor. For instance the Win32 library
I maintain uses the following AppVeyor script for Windows testing:
clone_folder: "c:\\WORK"
environment:
global:
CABOPTS: "--store-dir=C:\\SR --http-transport=plain-http"
matrix:
# 64 bit builds
- GHCVER: "8.4.2"
CHOCOPTS:
- GHCVER: "8.2.2"
CHOCOPTS:
- GHCVER: "8.0.2"
CHOCOPTS:
- GHCVER: "7.10.3.2"
CHOCOPTS:
- GHCVER: "7.8.4.1"
CHOCOPTS:
# 32 bit builds
- GHCVER: "8.4.2"
CHOCOPTS: --forcex86
- GHCVER: "8.2.2"
CHOCOPTS: --forcex86
- GHCVER: "8.0.2"
CHOCOPTS: --forcex86
- GHCVER: "7.10.3.2"
CHOCOPTS: --forcex86
- GHCVER: "7.8.4.1"
CHOCOPTS: --forcex86
cache:
- "C:\\SR"
install:
- "choco install -y ghc --version %GHCVER% %CHOCOPTS%"
- "choco install -y cabal %CHOCOPTS%"
- "refreshenv"
- "set PATH=C:\\ghc\\ghc-%GHCVER%:C:\\msys64\\mingw64\\bin;C:\\msys64\\usr\\bin;%PATH%"
- "cabal --version"
- "ghc --version"
- "cabal %CABOPTS% update -v"
build: off
test_script:
- IF EXIST configure.ac bash -c "autoreconf -i"
- "echo packages:. > cabal.project"
- "cabal %CABOPTS% new-build -j1 all"
This tests both x86_64 and x86 versions of the last 5 GHC against any pull requests to Win32.
To point out some important bits:
global:
CABOPTS: "--store-dir=C:\\SR --http-transport=plain-http"
The --store-dir flag is used to shorten the path of the new-build nix style package store folder so
it doesn’t hit MAX_PATH as easily. (NOTE: GHC 8.6 and newer no longer have this limitation for
end user programs. So in the future once cabal is compiled with GHC 8.6 this won’t be needed, but for
backwards compatibility should still be used for now.)
The http-transport is unimportant, it can be omitted but I prefer to not have it use curl from msys2
just because it’s an emulated binary and will be slower than the plain http-transport or powershell
transport options.
cache:
- "C:\\SR"
This caches the nix style package cache so that dependencies don’t get built over and over again. This can
save a significant amount of time when building your project. AppVeyor has an hour build limit.
- IF EXIST configure.ac bash -c "autoreconf -i"
This allows packages like network to be used from the repo where there is no final configure script yet.
- "choco install -y ghc --version %GHCVER% %CHOCOPTS%"
- "choco install -y cabal %CHOCOPTS%"
This command installs the compiler and the latest cabal-install which is backward compatible with older GHCs.
The explicit cabal install is for older packages which didn’t have a dependency on cabal. For newer GHC this
would be a no-op. The -y makes Chocolatey suppress the script execution question with a default answer of yes.
- "refreshenv"
- "set PATH=C:\\ghc\\ghc-%GHCVER%:C:\\msys64\\mingw64\\bin;C:\\msys64\\usr\\bin;%PATH%"
As before we reload the environment variables, which unfortunately also clears the custom ones AppVeyor sets.
To restore the ones we need we modify the PATH to contain msys2 and where we expect older GHCs to have been installed.
NOTE: If you actually intend to use pacman packages, please set the appropriate mingw for the architecture you intend
to use. The above examples all set the 64 bit paths.
If you want to report a bug against the packaging (the chocolatey packages and not the binaries themselves) please do so on my GitHub project for the packages. Cabal and GHC.
I do plan on adding a Haskell Platform package in the near future. Happy hacking.
– Tamar