
Hi, Suppose I have some kind of analysis tool that I want to run on a Cabal project. The analysis tool only deals with Haskell files, so I need Cabal to generate Haskell files from CPP-enabled Haskell files, .hsc files, alex and happy files etc. I see two possible ways to do that: use Cabal as a library, or my tool to be run by Cabal as a compiler. Cabal as a library doesn't seem friendly to this kind of usage: for example, Distribution.Simple does not export things like 'configureAction'. Besides, this wouldn't work with packages that use other build-types. Extending Cabal with a new compiler is not a simple thing, either (see https://github.com/haskell/cabal/issues/57). So, any advice how to proceed? I can volunteer to improve things if someone gives directions (I'm a Cabal noob). Roman

Hi,
On Fri, Nov 9, 2012 at 8:06 AM, Roman Cheplyaka
Hi,
Suppose I have some kind of analysis tool that I want to run on a Cabal project.
The analysis tool only deals with Haskell files, so I need Cabal to generate Haskell files from CPP-enabled Haskell files, .hsc files, alex and happy files etc.
I see two possible ways to do that: use Cabal as a library, or my tool to be run by Cabal as a compiler.
I think that the path of least resistance is to make your analysis tool command-line compatible with ghc. Then you can use it like this: $ cabal configure --with-compiler=/path/to/my-ghc $ cabal build Since 'cabal build' usually just calls 'ghc --make Main.hs', you'll need to do dependency chasing, but this can be implemented by parsing the output of 'ghc -M'. -- () ascii ribbon campaign - against html e-mail /\ www.asciiribbon.org - against proprietary attachments

Thanks for the suggestion.
Is the "protocol" between Cabal and ghc described anywhere, or do I need
to read the sources for that?
Also, is there a way to write a program that would be equivalent to
"cabal configure && cabal build" without relying on cabal-install or ghc
being installed, just by using the Cabal library? I realise that it
would only work for build-type: Simple, but it might be still useful.
* Mikhail Glushenkov
Hi,
On Fri, Nov 9, 2012 at 8:06 AM, Roman Cheplyaka
wrote: Hi,
Suppose I have some kind of analysis tool that I want to run on a Cabal project.
The analysis tool only deals with Haskell files, so I need Cabal to generate Haskell files from CPP-enabled Haskell files, .hsc files, alex and happy files etc.
I see two possible ways to do that: use Cabal as a library, or my tool to be run by Cabal as a compiler.
I think that the path of least resistance is to make your analysis tool command-line compatible with ghc. Then you can use it like this:
$ cabal configure --with-compiler=/path/to/my-ghc $ cabal build
Since 'cabal build' usually just calls 'ghc --make Main.hs', you'll need to do dependency chasing, but this can be implemented by parsing the output of 'ghc -M'.
-- () ascii ribbon campaign - against html e-mail /\ www.asciiribbon.org - against proprietary attachments

Hi Roman,
On Fri, Nov 9, 2012 at 9:10 AM, Roman Cheplyaka
Thanks for the suggestion.
Is the "protocol" between Cabal and ghc described anywhere, or do I need to read the sources for that?
No, I don't think that it's documented separately. The code is not very complicated, though - see buildLib/buildExe in Distribution.Simple.GHC.
Also, is there a way to write a program that would be equivalent to "cabal configure && cabal build" without relying on cabal-install or ghc being installed, just by using the Cabal library? I realise that it would only work for build-type: Simple, but it might be still useful.
'cabal build' is equivalent to 'runhaskell Setup.hs build' 'cabal configure' is mostly equivalent to 'runhaskell Setup.hs configure --user', but uses preferences from ~/.cabal/config. So I think that you can just ship a compiled Setup.hs with your analyser, but you will have to trick 'configure' into thinking that you have all dependencies for the packages that you're compiling installed (basically you'll have to provide a fake 'ghc-pkg' that supports the 'dump' command - with ghc installed, you can just invoke the real ghc-pkg).
I tried this, and one problem I ran into is that Cabal invokes the linker on the files that it expects my tool to produce. 'ld' fails, and the build aborts.
So you're building a library. Looking at buildLib in Distribution.Simple.GHC I don't see a way to stop the build before the linking phase. But your tool should have already processed all the source files at this stage. Maybe you can produce some dud .o files to placate ld or just print a message that says something like "Analysis complete. Don't worry about the link failure."? -- () ascii ribbon campaign - against html e-mail /\ www.asciiribbon.org - against proprietary attachments

* Mikhail Glushenkov
Also, is there a way to write a program that would be equivalent to "cabal configure && cabal build" without relying on cabal-install or ghc being installed, just by using the Cabal library? I realise that it would only work for build-type: Simple, but it might be still useful.
'cabal build' is equivalent to 'runhaskell Setup.hs build' 'cabal configure' is mostly equivalent to 'runhaskell Setup.hs configure --user', but uses preferences from ~/.cabal/config. So I think that you can just ship a compiled Setup.hs with your analyser
Thanks — this makes sense.
but you will have to trick 'configure' into thinking that you have all dependencies for the packages that you're compiling installed (basically you'll have to provide a fake 'ghc-pkg' that supports the 'dump' command - with ghc installed, you can just invoke the real ghc-pkg).
That's not a problem, I have to maintain my own package database anyway.
I tried this, and one problem I ran into is that Cabal invokes the linker on the files that it expects my tool to produce. 'ld' fails, and the build aborts.
So you're building a library. Looking at buildLib in Distribution.Simple.GHC I don't see a way to stop the build before the linking phase. But your tool should have already processed all the source files at this stage. Maybe you can produce some dud .o files to placate ld or just print a message that says something like "Analysis complete. Don't worry about the link failure."?
Sorry, I forgot to mention — that actually happens during the configure phase! My command looks like this: runghc Setup -v3 configure --ghc --with-compiler=gen-iface --with-hc-pkg=gen-iface ... and the relevant output from Cabal is searching for ld in path. found ld at /usr/bin/ld ("/home/feuerbach/bin/gen-iface",["-c","/tmp/17368.c","-o","/tmp/17368.o"]) ("/usr/bin/ld",["-x","-r","/tmp/17368.o","-o","/tmp/17369.o"]) /usr/bin/ld returned ExitFailure 1 with error message: /tmp/17368.o: file not recognized: File truncated Setup: /tmp/17369.o: does not exist I guess I can fake it by invoking gcc on '-c', but at this stage it becomes too dirty for my taste. Roman

Hi,
On Fri, Nov 9, 2012 at 6:25 PM, Roman Cheplyaka
searching for ld in path. found ld at /usr/bin/ld ("/home/feuerbach/bin/gen-iface",["-c","/tmp/17368.c","-o","/tmp/17368.o"]) ("/usr/bin/ld",["-x","-r","/tmp/17368.o","-o","/tmp/17369.o"]) /usr/bin/ld returned ExitFailure 1 with error message: /tmp/17368.o: file not recognized: File truncated Setup: /tmp/17369.o: does not exist
I looked into this - this is caused by configureLd' in Distribution.Simple.GHC. This function tries to determine whether ld supports the -x flag by compiling a short C program ("int foo() {}") with ghc (apparently ghc supports .c files as input). Since ghc just invokes gcc when given .c files, and you're trying to mimic ghc, I think it makes sense to support this behaviour. If you think that this is ugly, you can put all such hacky code into a separate driver program, and leave your analyser unmodified. -- () ascii ribbon campaign - against html e-mail /\ www.asciiribbon.org - against proprietary attachments

* Mikhail Glushenkov
Hi,
On Fri, Nov 9, 2012 at 6:25 PM, Roman Cheplyaka
wrote: searching for ld in path. found ld at /usr/bin/ld ("/home/feuerbach/bin/gen-iface",["-c","/tmp/17368.c","-o","/tmp/17368.o"]) ("/usr/bin/ld",["-x","-r","/tmp/17368.o","-o","/tmp/17369.o"]) /usr/bin/ld returned ExitFailure 1 with error message: /tmp/17368.o: file not recognized: File truncated Setup: /tmp/17369.o: does not exist
I looked into this - this is caused by configureLd' in Distribution.Simple.GHC. This function tries to determine whether ld supports the -x flag by compiling a short C program ("int foo() {}") with ghc (apparently ghc supports .c files as input).
Since ghc just invokes gcc when given .c files, and you're trying to mimic ghc, I think it makes sense to support this behaviour. If you think that this is ugly, you can put all such hacky code into a separate driver program, and leave your analyser unmodified.
At this point I'd rather work on a separate module in spirit of Distribution.Simple.*HC and hope that Cabal devs wouldn't mind to accept it. This will be essentially Cabal support for haskell-suite[1]. [1]: http://www.nbroberg.se/haskell-suite/ Of course, fixing #57 would be ideal, but given the complexity of existing modules I guess we're going to live with this for quite some time. Roman

* Mikhail Glushenkov
I think that the path of least resistance is to make your analysis tool command-line compatible with ghc. Then you can use it like this:
$ cabal configure --with-compiler=/path/to/my-ghc $ cabal build
I tried this, and one problem I ran into is that Cabal invokes the linker on the files that it expects my tool to produce. 'ld' fails, and the build aborts. I haven't found any way to disable or configure the linker. Any suggestions? Roman
participants (2)
-
Mikhail Glushenkov
-
Roman Cheplyaka