在Windows上真正便携的Haskell安装

6
有没有可能在Windows上拥有一个真正便携的Haskell安装,使所有与Haskell相关的操作都发生在单个目录下。我希望能够在USB闪存驱动器上安装Haskell,这样只需将其插入任何其他Windows计算机即可使用。
这意味着当我执行 cabal install somePackage时,所有操作都是本地且相对于该单个目录进行的(注意:对于不同的计算机,USB闪存驱动器可能会被分配不同的驱动器号)。我希望能够在任何Windows计算机上运行cabal install somePackage。此外,如果我可以将USB闪存驱动器的内容复制到本地硬盘并仍然从那里工作(在某些Windows机器上,USB闪存驱动器被挂载为只读),那就太好了。
我知道以下相关的StackOverflow问题herehere。我是否可以设置cabal的配置文件,以便它使用相对路径?其他Haskell工具(例如winghci)呢?
那么,我该怎么做?在便携模式下安装Haskell平台,然后做什么?

3
你最好的选择可能是使用stack,这似乎非常适合这种情况。但我不了解足够多的信息告诉你如何使用。 - dfeuer
2
我同意@dfeuers的建议。如果没有找到全局项目配置,stack将检查环境中的STACK_ROOT并将其所有内容放在该目录中。您可以编写一个简单的shell脚本来定位脚本的目录并适当设置STACK_ROOT。由于这是Windows,我想你必须使用批处理(这就是我的专业知识的尽头)。理论上,复制该脚本仍然可以工作,如果它正在寻找实际所在的目录。虽然我所知道的没有任何Haskell安装会这样做。 - user2407038
@user2407038和dfeuer的计划听起来很明智。根据这篇博客文章的建议,似乎可以通过cabal-install沙盒实现类似的效果,而不是使用stack。虽然我从未尝试过这样做或类似的事情。 - duplode
1
@duplode,我认为堆栈可能更适合将Haskell的其他内容(如GHC本身)放入同一箱中。 - dfeuer
@dfeuer 是的,那很可能。 - duplode
2个回答

3

请按照以下步骤操作:

  1. 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%.

  2. You should get the following (first level) directory structure:

    dev
      hp
        8.0.1
        local
          bin (this where stack.exe gets installed)
    
  3. Create additional subfolders:

    mkdir projects
    mkdir user
    cd user
    mkdir AppData
    mkdir AppData\Roaming
    
    dev
      hp
        projects
        user
          AppData
            Roaming
    
  4. 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
    
  5. 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"
    
  6. 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
    
  7. 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
    
  8. 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

    • Search for absolute paths and replace them using $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\...
  9. Do the same search and replace process in the stack's snapshot folders, e.g. user\AppData\Roaming\stack\snapshots\XXX\pkgdb:

  10. 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"`
    
  11. 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.

  12. 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.

  13. 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
    

-3

尝试:

penultimo :: [Int] -> Int
penultimo l = head(tail(reverse l))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接