Is it possible to have a truly portable Haskell installation on Windows so everything Haskell related happens under a single directory. I want to be able to have Haskell installation on a USB stick so I can use it on any other Windows computer just by plugging it in.
That would mean when I say cabal install somePackage
everything happens locally and relative to that single directory (n.b. for different computers there might be a different drive letter assigned to the USB drive). I would like to be able to run that cabal install somePackage
on any Windows computer. Also, it would be nice if I could copy the contents of the USB stick to a local hard disk and it still works from there (on some Windows machines USB sticks are mounted read only).
I am aware of the following related StackOverflow questions here and here. Can I setup cabal's config file in such a way it uses relative paths? What about other Haskell tools (e.g. winghci)?
So, how should I do it? Install Haskell Platform in a portable mode and then do what?
Follow the process as described below:
Use portable install to install Haskell Platform in e.g. h:\dev\hp
. Select Do not create shortcuts. For Haskell Stack Setup, choose h:\dev\hp\local\bin
as the destination folder. Deselect Add to user %PATH%.
You should get the following (first level) directory structure:
dev
hp
8.0.1
local
bin (this where stack.exe gets installed)
Create additional subfolders:
mkdir projects
mkdir user
cd user
mkdir AppData
mkdir AppData\Roaming
dev
hp
projects
user
AppData
Roaming
Download and extract junction utility in the user
folder. Create user\create-symlink.bat
with the following contents. Then run it.
%~dp0junction -nobanner -accepteula -d "%~dp0Application Data"
%~dp0junction -nobanner -accepteula "%~dp0Application Data" %~dp0AppData\Roaming
junction "Application Data" AppData\Roaming
Create haskell.bat
in the h:\dev\hp
folder with the following contents:
@ECHO OFF
set HSROOT=%~dp08.0.1
SET USERPROFILE=%~dp0user
SET Path=%HSROOT%\bin;%HSROOT%\winghci;%~dp0local\bin;%HSROOT%\mingw\bin;%HSROOT%\msys\usr\bin;%HSROOT%\lib;%HSROOT%\lib\extralibs\bin;%Path%
CMD /k "cd %~dp0projects"
Run haskell.bat
and in the command line type these commands. This should create additional folder structure under user\AppData\Roaming
cabal update
cabal user-config init
stack setup
To make cabal's config file (user\AppData\Roaming\cabal\config
) relocatable, edit it and change the tags as follows:
remote-repo-cache: $prefix\..\..\user\AppData\Roaming\cabal\packages
world-file: $prefix\..\..\user\AppData\Roaming\cabal\world
extra-prog-path: $prefix\..\msys\usr\bin
extra-lib-dirs: $prefix\..\mingw\lib
extra-include-dirs: $prefix\..\mingw\include
build-summary: $prefix\..\..\user\AppData\Roaming\cabal\logs\build.log
Using your favourite text editor do multi-file search and replace on the following files: user\AppData\Roaming\ghc\i386-mingw32-8.0.1\package.conf.d\*.conf
$topdir
(It evaluates to a directory under 8.0.1
, I think it is h:\dev\hp\8.0.1\lib
). So, for example if you see h:\\dev\\hp\user\\Application Data
replace it with $topdir\\..\\..\\user\\AppData\\Roaming
. Or, if you see h:\dev\hp\8.0.1
, then replace it with $topdir\..
.Do the same search and replace process in the stack's snapshot folders, e.g. user\AppData\Roaming\stack\snapshots\XXX\pkgdb
:
Update the global and user and stack package cache:
`ghc-pkg recache --global`
`ghc-pkg recache --user`
`ghc-pkg recache --package-db="h:\dev\hp\user\AppData\Roaming\stack\snapshots\XXX\pkgdb"`
If you install new packages, you might need to repeat the search&replace step. Or you can try cabal install --enable-relocatable <package>
and see if that works instead.
You should be able to rename the installation folder, copy it to new location on the same machine, or on the different machine altogether and it should all work. Just use the haskell.bat
to set up the environment and get a command prompt from which you should be able to run ghc
, cabal
, stack
, winghci
, etc.
There is one issue still remaining. If you try to install a package that requires gcc
to be built, you might get the following error:
Configuring network-2.6.3.1...
bash.exe: warning: could not find /tmp, please create!
configure: WARNING: unrecognized options: --with-compiler
checking build system type... bash.exe: warning: could not find /tmp, please create!
bash.exe: warning: could not find /tmp, please create!
i686-pc-mingw32
checking host system type... i686-pc-mingw32
checking for gcc... h:\dev\hp\80227D~1.1Ăé´ÉŐĂőýŽÇ┬ćýŁŻ┬îŃąÇĂéňżö┬łŃŽ«ĂéŃąÇĂéň庤ťO
checking whether the C compiler works... no
configure: error: in `/cygdrive/c/DOCUME~1/UserName/LOCALS~1/Temp/stack4268/network-2.6.3.1':
configure: error: C compiler cannot create executables
See `config.log' for more details
The reason is that configure
script gets passed the wrong path to gcc
(h:\dev\hp\80227D~1.1Ăé´ÉŐĂőýŽÇ┬ćýŁŻ┬îŃąÇĂéňżö┬łŃŽ«ĂéŃąÇĂéň庤ťO
). I know how to build the offending package manually, but don't know how to install it:
stack unpack network-2.6.3.1
cd network-2.6.3.1
stack init
# edit `configure` script and put `CC=` on the first line to kill system supplied path to `gcc`
stack build
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With