Warm tip: This article is reproduced from serverfault.com, please click

How to run a haskell executable (cabal project) without having cabal or ghc installed

发布于 2020-11-30 20:03:08

I have built an application in haskell with cabal. I can run the executable by typing into the command prompt "cabal run [cabal file]". Now I want to share this application to my friends, and preferably not having to install cabal on their machines. I can locate the .exe file for the project in the build directory, but it does not load a .txt file that comes with the program. The .exe file also opens the terminal at runtime which it does not do when I run it with cabal (like it should do). That tells me that stuff is missing and therefore I can't share the .exe by itself. What is the solution for running my application without having cabal or ghc installed?

Questioner
Johannes Green
Viewed
1
Jon Purdy 2020-12-01 04:34:00

There are a few possible solutions here.

By default when you open a file from your program using a relative path, it’s relative to the current working directory of the program, which is not where the executable file lives, but where the executable was executed from. If you want to find a file relative to the executable path or installation directory, you need to do so explicitly. There are two basic ways to do that: manually use System.Environment.getExecutablePath to get the program directory, and combine it with the path to your file:

import System.Environment (getExecutablePath)
import System.FilePath ((</>))

installRelative :: FilePath -> IO FilePath
installRelative relative = do
  absolute <- getExecutablePath
  pure (absolute </> relative)

readInstalledFile :: FilePath -> IO String
readInstalledFile path = readFile =<< installRelative path

You can also use the data-files field in your Cabal file to add the file to your project; this will generate a Paths_projectName module which exports a few functions like getDataFileName :: FilePath -> IO FilePath which performs the same function as the installRelative action I defined above. Then if you install a project with cabal install, it will copy the data files to the install directory and your program will be able to find them at runtime. However, this depends on installing the program using Cabal, since it generates absolute paths with the installation directory baked in.

If you use cabal install to install the program in a standard location on your machine, such as the “program files” directory, then it won’t matter that the path is hardcoded, and you can simply copy the executable and supporting files into an archive and have users unzip it in their program files directory.

Instead of a ZIP archive, you can build a Windows installer instead. Alternatively, you can avoid having to load anything at runtime by embedding the files in the executable directly using the file-embed package.

As for how to prevent the terminal from opening, see my answer to your question specifically about this.