michaelAdam
michaelAdam

Reputation: 1137

How do I import a text file in a cabal project?

In app/Main.hs, I want to open a text file, "foo.txt". I know how to open a text file in a plain Haskell program. In my cabal project,

import System.IO

Main = do
    contents <- readFile "foo.txt"
    print $ Main.lex contents
    return contents


type Keyword = String
lex :: String -> [Keyword]
lex "" = []
lex x = words x

gives the error

openFile: does not exist (No such file or directory)

What do I need to change in my cabal file, or the file path or location to be able to open the file? I've tried putting it next to the output binary, and that doesn't work either.

This is my cabal file:

-- This file has been generated from package.yaml by hpack version 0.28.2.
--
-- see: https://github.com/sol/hpack
--
-- hash: baf2fc7e230f4b4937dfd918a13fefb55b66c7a4468b24d0e3e90cad675b26d5

name:           CCompiler
version:        0.1.0.0
description:    Please see the README on GitHub at <https://github.com/githubuser/CCompiler#readme>
homepage:       https://github.com/githubuser/CCompiler#readme
bug-reports:    https://github.com/githubuser/CCompiler/issues
author:         Author name here
maintainer:     [email protected]
copyright:      2018 Author name here
license:        BSD3
license-file:   LICENSE
build-type:     Simple
cabal-version:  >= 1.10
extra-source-files:
    ChangeLog.md
    README.md

source-repository head
  type: git
  location: https://github.com/githubuser/CCompiler

library
  exposed-modules:
      Lib
  other-modules:
      Paths_CCompiler
  hs-source-dirs:
      src
  build-depends:
      base >=4.7 && <5
  default-language: Haskell2010

executable CCompiler-exe
  main-is: Main.hs
  other-modules:
      Paths_CCompiler
  hs-source-dirs:
      app
  ghc-options: -threaded -rtsopts -with-rtsopts=-N
  build-depends:
      CCompiler
    , base >=4.7 && <5
  default-language: Haskell2010

test-suite CCompiler-test
  type: exitcode-stdio-1.0
  main-is: Spec.hs
  other-modules:
      Paths_CCompiler
  hs-source-dirs:
      test
  ghc-options: -threaded -rtsopts -with-rtsopts=-N
  build-depends:
      CCompiler
    , base >=4.7 && <5
  default-language: Haskell2010

Upvotes: 5

Views: 1058

Answers (2)

typetetris
typetetris

Reputation: 4867

I understand your question to be about finding files at runtime, which you want to process and aren't packaged with your package.

Where are severals ways, how you could find files at runtime, which aren't packaged.

Either add an command line flag and call your executable with the absolute path of the file you want to process.

Or implement a file chooser dialog, with e.g. gi-gtk.

Or hard coding relative paths which isn't advisable, as they are interpreted relative to the current working directory of your process, which can be different, depending on how the program did get started.

If you want to determine, which current working directory your program runs in, if started with cabal run, just do a litte test project with the following cabal file:

name: test2
build-type: Simple
cabal-version: >= 1.10
version: 0.0.0.1

executable test2
  hs-source-dirs: .
  main-is: test2.hs
  build-depends:
      base
    , directory

and the following test2.hs:

module Main where

import System.Directory

main :: IO ()
main = do
  cwd <- getCurrentDirectory
  putStrLn cwd

Upvotes: 0

michaelAdam
michaelAdam

Reputation: 1137

add

data-dir: data

in the top section of the cabal file.

create the directory 'data' next to src and app, and put all files in there.

Make sure your cabal file also has this line

other-modules:
  Paths_CCompiler

with your project's name instead of CCompiler.

My main function is now this

module Main where

import Lib
import System.IO
import Paths_CCompiler

main = do
    filepath <- getDataFileName "return_2.c"
    contents <- readFile filepath
    print $ Lib.lex contents
    return contents

Thanks to this blog post.

Upvotes: 7

Related Questions