Haskell GHCI not loading compiled object file - haskell

I would like GHCI to load the compiled object code for a module which when compiled is significantly faster than the none compiled version. This was working well when all of the files were in the same directory (no module hierarchies). However, they do not work when the files are in module hierarchies.
Working version MyFile.hs:
import Basic
import Histogram
where Basic.o and Histogram.o are in the same directory as MyFile.hs
Not Working version MyFile.hs:
import Util.Basic
import Util.Histogram
where Basic.o and Histogram.o are in a subdirectory Util. With this version I get the following when loading MyFile.hs:
[1 of 2] Compiling Util.Basic ( Util/Basic.hs, interpreted )
[2 of 2] Compiling Util.Histogram ( Util/Histogram.hs, interpreted )
Ok, modules loaded: Util.Basic, Util.Histogram.
I would like to be able to organize my code in modules but still receive the benefits from using the compiled o files.
Also, it should be noted that the source files have not been changed since the o files were compiled.
Edits:
Here are the contents of each file:
MyFile.hs
import Util.Basic
import Util.Histogram
Util/Basic.hs
module Util.Basic () where
Util/Histogram.hs
module Util.Histogram () where
Files / Compilation:
$:~/programming/haskell/example-error$ ls
MyFile.hs MyFile.hs~ Util
$:~/programming/haskell/example-error$ cd Util
$:~/programming/haskell/example-error/Util$ ls
Basic.hs Basic.hs~ Histogram.hs Histogram.hs~
$:~/programming/haskell/example-error/Util$ ghc *.hs
[1 of 2] Compiling Util.Histogram ( Histogram.hs, Histogram.o )
[2 of 2] Compiling Util.Basic ( Basic.hs, Basic.o )
$:~/programming/haskell/example-error/Util$ ls
Basic.hi Basic.hs~ Histogram.hi Histogram.hs~
Basic.hs Basic.o Histogram.hs Histogram.o
$:~/programming/haskell/example-error/Util$ cd ../
$:~/programming/haskell/example-error$ ghci -ignore-dot-ghci MyFile.hs
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 3] Compiling Util.Histogram ( Util/Histogram.hs, interpreted )
[2 of 3] Compiling Util.Basic ( Util/Basic.hs, interpreted )
[3 of 3] Compiling Main ( MyFile.hs, interpreted )
Ok, modules loaded: Util.Basic, Util.Histogram, Main.
*Main>
The Solution that worked as suggested by Daniel:
The fix is to compile the importing file, and the files in the
subdirectory only as a consequence of that, not directly.

The issue is the same as discussed below, the flags changed:
~/.../Util> ghc Other.hs
[1 of 1] Compiling Util.Other ( Other.hs, Other.o )
~/.../Util> cd ..
~/.../src> ghc MyFile.hs
[1 of 2] Compiling Util.Other ( Util/Other.hs, Util/Other.o ) [flags changed]
[2 of 2] Compiling MyFile ( MyFile.hs, MyFile.o )
I haven't found out which flags in particular, or why the flags passed during separate compilation are different than the ones that are passed when compiling as a module chased from the importing module, but they do change, and hence a recompilation is necessary (Specifically, the flag-hash value in the .hi file changes).
The fix is therefore to not compile the modules separately, but to compile them as dependencies of the top-level importer.
Original almost correct guesswork:
I can only partly reproduce that. After compiling and then touching MyFile.hs,
$ ghci-7.4.2 MyFile.hs
-- snip
[1 of 2] Compiling Util.Other ( Util/Other.hs, interpreted )
[2 of 2] Compiling MyFile ( MyFile.hs, interpreted )
Ok, modules loaded: MyFile, Util.Other.
it looks the same as for you, but with 7.6.1, we get a hint (compiling and touching):
$ ghci MyFile.hs
-- snip
[1 of 2] Compiling Util.Other ( Util/Other.hs, interpreted ) [flags changed]
[2 of 2] Compiling MyFile ( MyFile.hs, interpreted )
Ok, modules loaded: MyFile, Util.Other.
The flags changed. I have :set -XNoMonomorphismRestriction in my .ghci file, and the change of flags causes the recompilation.
$ ghci -ignore-dot-ghci MyFile.hs
GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[2 of 2] Compiling MyFile ( MyFile.hs, interpreted )
Ok, modules loaded: MyFile, Util.Other.
Ignoring the offending .ghci with the flag that wasn't given for the compilation, the unchanged Util.Other is not interpreted, the compiled code is used. (With GHC < 7.4, ignoring the .ghci file isn't even necessary.)
If you have a .ghci file in which you set language options (NoMonomorphismRestriction, TypeFamilies, ...) and ghc >= 7.4, you need to ignore the .ghci file when loading the modules.
If that is not the case, the recompilation is not the expected behaviour. Then more information would be necessary to diagnose the problem and find a fix.
A semi-work-around would then be the -fobject-code flag for ghci.

Related

GHC compiles to .o and .hi but no executable

I've been working on a small file which I've been compiling and running as I go. My directory contains Log.hs and LogAnalysis.hs.
LogAnalysis.hs looks like this:
{-# OPTIONS_GHC -Wall #-}
module LogAnalysis where
import Log
parseMessage :: String -> LogMessage
--some code...
main :: IO ()
main = do
putStrLn (show (parseMessage ("Some log message text")))
When I compile the LogAnalysis.hs with GHC I was getting an executable, along with some other binary files:
$ ll
Log.hi
Log.hs
Log.o
LogAnalysis <-- this is the executable which has disappeared
LogAnalysis.hi
LogAnalysis.hs
LogAnalysis.o
I made some small changes and now when I run ghc LogAnalysis.hs I get only the .hi and .o files but no executable. The output is:
[1 of 2] Compiling Log ( Log.hs, Log.o )
[2 of 2] Compiling LogAnalysis ( LogAnalysis.hs, LogAnalysis.o )
I'm not even sure what I changed, but it wasn't anything major. Any idea what could be triggering this? Is there some way to force GHC to produce an executable?
Specs: GHC 8.8.3, macOS 10.15.5
Since I was declaring the file as a module not named Main, GHC by default doesn't create an executable. In order to compile this module into an executable, we can use GHC's main-is flag. (Thanks to Krantz in the comments and Willem Van Onsem's answer here for this.) So compiling with
ghc -main-is LogAnalysis LogAnalysis.hs
gives the output
[2 of 2] Compiling LogAnalysis ( LogAnalysis.hs, LogAnalysis.o )
Linking LogAnalysis ...
So GHC has linked the executable LogAnalysis which is the desired result.
There is an easier way to fix it, delete the second line:
module LogAnalysis where
I believe that when you define it as a module, ghc understands that it is just a module that will be imported in another file so it doesn't create an executable.

How do I get `cabal repl` to read `.ghci` *after* compiling my project's modules?

I have
:m +Control.Monad System.Random.MWC NW.Affix
in my .ghci file in my project's root directory. I want to load in NW.Affix (a module in my project) with cabal repl, but it fails immediately like this:
Preprocessing executable 'netherworld' for netherworld-0.0.0.0...
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package array-0.5.0.0 ... linking ... done.
Loading package deepseq-1.3.0.2 ... linking ... done.
Loading package bytestring-0.10.4.0 ... linking ... done.
Loading package transformers-0.3.0.0 ... linking ... done.
Loading package mtl-2.1.3.1 ... linking ... done.
Loading package text-1.1.1.3 ... linking ... done.
Loading package parsec-3.1.5 ... linking ... done.
Loading package primitive-0.5.3.0 ... linking ... done.
Loading package old-locale-1.0.0.6 ... linking ... done.
Loading package time-1.4.2 ... linking ... done.
Loading package vector-0.10.11.0 ... linking ... done.
Loading package mwc-random-0.13.1.2 ... linking ... done.
Loading package monads-tf-0.1.0.2 ... linking ... done.
Loading package filepath-1.3.0.2 ... linking ... done.
Loading package byteable-0.1.1 ... linking ... done.
Loading package cryptohash-0.11.6 ... linking ... done.
Loading package containers-0.5.5.1 ... linking ... done.
<no location info>:
Could not find module ‘NW.Affix’
It is not a module in the current program, or in any known package.
After failing like this, it happily compiles my modules, like so:
[ 1 of 14] Compiling NW.Util ( src/NW/Util.hs, interpreted )
[ 2 of 14] Compiling NW.Stats ( src/NW/Stats.hs, interpreted )
[ 3 of 14] Compiling NW.Monster ( src/NW/Monster.hs, interpreted )
[ 4 of 14] Compiling NW.Random ( src/NW/Random.hs, interpreted )
[ 5 of 14] Compiling NW.Map ( src/NW/Map.hs, interpreted )
[ 6 of 14] Compiling NW.Player ( src/NW/Player.hs, interpreted )
[ 7 of 14] Compiling NW.Error ( src/NW/Error.hs, interpreted )
[ 8 of 14] Compiling NW.Effect ( src/NW/Effect.hs, interpreted )
[ 9 of 14] Compiling NW.Config ( src/NW/Config.hs, interpreted )
[10 of 14] Compiling NW.Affix ( src/NW/Affix.hs, interpreted )
[11 of 14] Compiling NW.Item ( src/NW/Item.hs, interpreted )
[12 of 14] Compiling NW.State ( src/NW/State.hs, interpreted )
[13 of 14] Compiling NW.Battle ( src/NW/Battle.hs, interpreted )
[14 of 14] Compiling Main ( src/main.hs, interpreted )
Ok, modules loaded: NW.Affix, Main, NW.Battle, NW.Config, NW.Item, NW.Error, NW.Map, NW.Player, NW.Random, NW.State, NW.Stats, NW.Monster, NW.Effect, NW.Util.
The current workaraound is to just copy-paste my .ghci stuff into cabal repl after it's done initializing. Still, is there a way to delay cabal repl from reading in my .ghci file until after it finishes compiling my project's modules?
OK, well I don't really understand it yet, but a "workaround" (if you can call it that) is to break up the :m line into :m for cabal-installed packages and :l for your own ones.
So in my case, I just changed
:m +Control.Monad System.Random.MWC NW.Affix
to
:l NW.Item
:m +Control.Monad System.Random.MWC
in my .ghci and cabal repl works as expected. But it seems a bit roundabout... I mean, if copy/pasting the .ghci after it loads makes it work anyway, why is there a need for this :m and :l distinction?

GHC compilation bug?

Some time ago I devised a little system to make compilation and testing of my Haskell programs a bit more comfortable. My project root looks as follows:
./bin/
./bin/myMain
./bin/test
./interfaces/
./obj/
./src/
./src/makefile
./src/MyLib.hs
./src/myMain.hs
./src/testSuite.hs
myMain is the main module, whose imports are like those:
import MyLib
-- irrelevant content follows
testSuite is similar:
import System.Exit
import Test.HUnit
import MyLib
-- irrelevant content follows
I compile those with two simple commands:
ghc testSuite.hs -o ../bin/test -odir ../obj -hidir ../interfaces
ghc myMain.hs -o ../bin/myMain -odir ../obj -hidir ../interfaces
Now, as I run the first, whole test suite compiles and executes perfectly fine, even if there are any object or intereface files present. However when I run the second to compile main executable, it compiles test binary again unless I run remove object and interface files.
The reason is, as far as I found, that main module produces Main.o and Main.hi, no matter what its name is. Therefore while compiling myMain, GHC sees those files present, so does not recompile main module. The strange part is this is not the case when I compile test suite - in such a case Main is recompiled even if there are objects and interfaces present.
$ ghc testSuite.hs -o ../bin/test -odir ../obj -hidir ../interfaces
[1 of 2] Compiling MyLib ( MyLib.hs, ../obj/MyLib.o )
[2 of 2] Compiling Main ( testSuite.hs, ../obj/Main.o )
Linking ../bin/test ...
$ ghc myMain.hs -o ../bin/myMain -odir ../obj -hidir ../interfaces
Linking ../bin/myMain ...
But when I run main compilation first:
$ ghc myMain.hs -o ../bin/myMain -odir ../obj -hidir ../interfaces
[1 of 2] Compiling MyLib ( MyLib.hs, ../obj/MyLib.o )
[2 of 2] Compiling Main ( myMain.hs, ../obj/Main.o )
Linking ../bin/myMain ...
$ ghc testSuite.hs -o ../bin/test -odir ../obj -hidir ../interfaces
[2 of 2] Compiling Main ( testSuite.hs, ../obj/Main.o ) [Test.HUnit changed]
Linking ../bin/test ...
What's even stranger, the problem disappears when I put aside -odir and -hidir GHC parameters and compile everything in the same directory. Why?
[NOTE:]
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.6.3

Typeclass instance is not resolved after module installed with Cabal

I created simple project to demonstrate the issue: https://github.com/jdevelop/testcabal
If I compile and install the module with 'cabal install', I can not serialize TestData with Binary:
> ghci
GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
ghci> :m +TestBinary.Test Data.Binary
ghci> randomData . decode $ encode emptyTest
<interactive>:1:24:
No instance for (Binary TTestData)
arising from a use of `encode'
Possible fix: add an instance declaration for (Binary TTestData)
In the second argument of `($)', namely `encode emptyTest'
In the expression: randomData . decode $ encode emptyTest
In an equation for `it':
it = randomData . decode $ encode emptyTest
If I load the Test.hs into ghci directly - everything works as expected,
> ghci TestBinary/Test.hs
GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 1] Compiling TestBinary.Test ( TestBinary/Test.hs, interpreted )
Ok, modules loaded: TestBinary.Test.
ghci> randomData . decode $ encode emptyTest
Loading package array-0.3.0.2 ... linking ... done.
Loading package bytestring-0.9.1.10 ... linking ... done.
Loading package containers-0.4.0.0 ... linking ... done.
Loading package binary-0.5.1.0 ... linking ... done.
"123456"
Version of Haskell compiler:
> ghci --version
The Glorious Glasgow Haskell Compilation System, version 7.0.4
In your .cabal file, you have
Build-depends: base < 5, ghc-binary >= 0.5, bytestring >= 0.9.1
Usually, ghc-binary is not exposed, and it is not intended to be used except by GHC itself. When you load Data.Binary into ghci, it loads the module from the binary package, and the Binary class from that package is a different one than the one from ghc-binary, hence TTestData has no instance.
If you load the file from source, ghci doesn't care about the .cabal file and uses the class from binary directly, hence it works.
You should change the dependency to the binary package.

Haskell : loading ALL files in current directory path

The command (in GHCi)
:load abc
Loads the functions in the file abc (which must exist in the current directory path). How would I load all the files in the current directory path? Thanks
----------------------------------------------------------------------------------
[RESPONSE TO POST BELOW]
Hi Rotskoff, thanks I tried your suggestion but I could not get it to work, so I think I must have misunderstood something.
I created 3 files test.hs, test1.hs, and test2.hs as follows :
->
--test.hs
import NecessaryModule
->
--test1.hs
module NecessaryModule where
addNumber1 :: Int -> Int -> Int
addNumber1 a b = a + b
->
--test2.hs
module NecessaryModule where
addNumber2 :: Int -> Int -> Int
addNumber2 a b = a + b
Then when I did :
:load test
I got the error message :
test.hs:1:8:
Could not find module `NecessaryModule':
Use -v to see a list of the files searched for.
Thanks
---------------------------------------------------------------------------------
Thanks. This is what I did to get it to work (following Rotskoff's suggestion) :
->
--test.hs
import NecessaryModule1
import NecessaryModule2
->
--NecessaryModule1.hs
addNumber1 :: Int -> Int -> Int
addNumber1 a b = a + b
->
--NecessaryModule2.hs
addNumber2 :: Int -> Int -> Int
addNumber2 a b = a + b
Presumably you mean Haskell source files, because you can't use the :load command in GHCi for anything else.
At the top of the source file that you load, include the line:
import NecessaryModule
For each of the source files, make sure to name the modules, e.g.,
module NecessaryModule where
should appear. GHCi will automatically link all the files.
If you're trying to import data, take a look at System.Directory in the documentation.
It's better if the filenames and the names of the modules will be the same:
➤ mv test1.hs NecessaryModule.hs
➤ ghci
GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> :load test
[1 of 2] Compiling NecessaryModule ( NecessaryModule.hs, interpreted )
[2 of 2] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: NecessaryModule, Main.
since the :load command load module(s) (by filenames) and their dependents (as you can read by typing :help or :? in the GHCi prompt).
Also the :load command erase all previous declarations which was defined in the current GHCi session, so for loading all files in the current directory you can do something like this:
Prelude> :q
Leaving GHCi.
➤ ghci *.hs
GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
<no location info>:
module `main:NecessaryModule' is defined in multiple files: NecessaryModule.hs
test2.hs
Failed, modules loaded: none.
Prelude> :q
Leaving GHCi.
➤ rm test2.hs
➤ ghci *.hs
GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 2] Compiling NecessaryModule ( NecessaryModule.hs, interpreted )
[2 of 2] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: NecessaryModule, Main.
*NecessaryModule>

Resources