Building examples with Cabal

Is there a way to build examples in a Haskell package with Cabal without actually running them? "cabal test" and "cabal benchmark" don't really do what I want, I just want to check if e.g. all GLUT examples in https://github.com/haskell-opengl/GLUT/tree/master/examples still build after some API changes. Another requirement would be parallel builds, I want to actually use the 32 cores I have under my desk. ;-) Currently I use a recursive "make" infrastructure (https://github.com/haskell-opengl/GLUT/blob/master/examples/Makefile), which works OK, but it is quite a hack, is partly incorrect and, well, needs "make".

Sven Panne wrote:
Is there a way to build examples in a Haskell package with Cabal without actually running them? "cabal test" and "cabal benchmark" don't really do what I want, I just want to check if e.g. all GLUT examples in https://github.com/haskell-opengl/GLUT/tree/master/examples still build after some API changes. Another requirement would be parallel builds, I want to actually use the 32 cores I have under my desk. ;-) Currently I use a recursive "make" infrastructure (https://github.com/haskell-opengl/GLUT/blob/master/examples/Makefile), which works OK, but it is quite a hack, is partly incorrect and, well, needs "make".
I usually declare an "Executable" for each example and add a flag "buildExamples" that controls whether the examples are built or not. Here an example .cabal file. http://hackage.haskell.org/package/threepenny-gui-0.3.0.0/threepenny-gui.cab... Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

2013/10/16 Heinrich Apfelmus
I usually declare an "Executable" for each example and add a flag "buildExamples" that controls whether the examples are built or not. Here an example .cabal file.
http://hackage.haskell.org/package/threepenny-gui-0.3.0.0/threepenny-gui.cab...
I tried something similar in the past, but that didn't really work out: * Things get *extremely* verbose and repetitive in the .cabal file. Currently there are roughly 90 GLUT examples, and I expect to have much more in the future. This would lead to more than 1000 lines of boilerplate .cabal stuff. OK, Emacs macros and copy-n-paste are your friends, but... :-P * Can Cabal build the executables in parallel? Doing a parallel build of all examples via my make hack takes about 5 seconds, a non-parallel build takes 75 seconds, and I expect that gap to widen even more when I add more examples. * How does one handle common parts in the examples? (e.g. https://github.com/haskell-opengl/GLUT/tree/master/examples/RedBook8/common, more to come there) Conditionally build helper libraries just for the examples? I can't believe that I'm the only package maintainer who has such a problem, so I really hope that there is some hidden solution out there I simply can't see...

Hi Sven,
Maybe your examples can be imported into a single module that cabal
can build/run with cabal test? I mean something like:
examples/Ex1.hs:
module Ex1 (main) where main = ...
examples/importAll.hs:
module Main where
import Ex1
import Ex2
...
main = return ()
Then in the cabal file have something like:
test-suite build_examples
type: exitcode-stdio-1.0
main-is: examples/importAll.hs
hs-source-dirs: examples
<those other settings repeated once only>
--
Adam
On Wed, Oct 16, 2013 at 10:23 AM, Sven Panne
2013/10/16 Heinrich Apfelmus
: I usually declare an "Executable" for each example and add a flag "buildExamples" that controls whether the examples are built or not. Here an example .cabal file.
http://hackage.haskell.org/package/threepenny-gui-0.3.0.0/threepenny-gui.cab...
I tried something similar in the past, but that didn't really work out:
* Things get *extremely* verbose and repetitive in the .cabal file. Currently there are roughly 90 GLUT examples, and I expect to have much more in the future. This would lead to more than 1000 lines of boilerplate .cabal stuff. OK, Emacs macros and copy-n-paste are your friends, but... :-P
* Can Cabal build the executables in parallel? Doing a parallel build of all examples via my make hack takes about 5 seconds, a non-parallel build takes 75 seconds, and I expect that gap to widen even more when I add more examples.
* How does one handle common parts in the examples? (e.g. https://github.com/haskell-opengl/GLUT/tree/master/examples/RedBook8/common, more to come there) Conditionally build helper libraries just for the examples?
I can't believe that I'm the only package maintainer who has such a problem, so I really hope that there is some hidden solution out there I simply can't see... _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

2013/10/16 adam vogt
Maybe your examples can be imported into a single module that cabal can build/run with cabal test? I mean something like: [...]
Nice idea. :-) I think this might work if one really only need to check if compilation succeeds, but this is not enough for my use case. I was a bit unclear about that in my previous description, so let's try to describe my usual workflow: * Decide to work on OpenGL feature X. * Make the relevant changes in the OpenGLRaw and/or OpenGL packages. * If there are any API changes, see how they affect the >90 examples in the GLUT package. * Fix the examples if needed. * Run a few examples by hand which are related to feature X. Incrementally rebuilding OpenGLRaw/OpenGL/GLUT works nicely, and it would work even better when/if Cabal uses GHC's new -j flag. (How? When? :-) The only missing part is some way to build tons of executables in parallel without writing a .cabal file of roughly the same size as "The Lord of the Rings" or a typical Stephen King novel... Currently I am seriously considering generating the .cabal file somehow automatically, but I think this is only a workaround for a missing feature.

Hi.
On 18 October 2013 08:07, Sven Panne
The only missing part is some way to build tons of executables in parallel without writing a .cabal file of roughly the same size as "The Lord of the Rings" or a typical Stephen King novel...
If you have so many tests, why wouldn't you generate a single executable which takes the name of the test as an argument and runs that test? Something like the following, with additional error checking and etc. data Test = Foo | Bar | ... runTest :: Test -> IO () main = do (t:_) <- getArgs runTest (read t) This is a pretty simple idea, just wanted to know why you don't go down this path instead. HTH, Ozgur

I think the parallel build requirement was a concern in the initial
mail, if it is a single executable I assume it's going to be trickier.
On Fri, Oct 18, 2013 at 11:28 AM, Ozgur Akgun
Hi.
On 18 October 2013 08:07, Sven Panne
wrote: The only missing part is some way to build tons of executables in parallel without writing a .cabal file of roughly the same size as "The Lord of the Rings" or a typical Stephen King novel...
If you have so many tests, why wouldn't you generate a single executable which takes the name of the test as an argument and runs that test?
Something like the following, with additional error checking and etc.
data Test = Foo | Bar | ... runTest :: Test -> IO () main = do (t:_) <- getArgs runTest (read t)
This is a pretty simple idea, just wanted to know why you don't go down this path instead.
HTH, Ozgur
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

2013/10/18 Gauthier Segay
I think the parallel build requirement was a concern in the initial mail, if it is a single executable I assume it's going to be trickier.
If I understood things correctly, Cabal will be able to make use of GHC's -j flag, so this problem will go away. Hopefully this feature will make it into the next Haskell Platform release and into the Travis CI VMs soon.

2013/10/18 Ozgur Akgun
If you have so many tests, why wouldn't you generate a single executable which takes the name of the test as an argument and runs that test? [...]
I think that this might actually work. It is slightly complicated by the fact that some of the tests load resources from the file system, so I somehow have to handle paths correctly, but this seems doable relatively easily.
This is a pretty simple idea, just wanted to know why you don't go down this path instead.
Perhaps because I didn't think of it? :-) The word "test" might be a bit misleading, each such "test" is a complete program doing some OpenGL stuff, ranging from drawing a simple rectangle to doing more complicated things via various shaders. It is not totally intuitive to throw 100 such unrelated programs together into a sumo executable and dispatch by hand to the correct "main", so it might do what I want, but I still consider this a hack.

Hi Sven,
Sven Panne
* Can Cabal build the executables in parallel? Doing a parallel build of all examples via my make hack takes about 5 seconds, a non-parallel build takes 75 seconds, and I expect that gap to widen even more when I add more examples.
This feature will likely be in the next version: https://github.com/haskell/cabal/pull/1540

Sven Panne wrote:
2013/10/16 Heinrich Apfelmus
: I usually declare an "Executable" for each example and add a flag "buildExamples" that controls whether the examples are built or not. Here an example .cabal file.
http://hackage.haskell.org/package/threepenny-gui-0.3.0.0/threepenny-gui.cab...
I tried something similar in the past, but that didn't really work out:
* Things get *extremely* verbose and repetitive in the .cabal file. Currently there are roughly 90 GLUT examples, and I expect to have much more in the future. This would lead to more than 1000 lines of boilerplate .cabal stuff. OK, Emacs macros and copy-n-paste are your friends, but... :-P
Ah, I see. I'm lucky in that the number of examples I need to maintain is still in the one digit range.
* Can Cabal build the executables in parallel? Doing a parallel build of all examples via my make hack takes about 5 seconds, a non-parallel build takes 75 seconds, and I expect that gap to widen even more when I add more examples.
* How does one handle common parts in the examples? (e.g. https://github.com/haskell-opengl/GLUT/tree/master/examples/RedBook8/common, more to come there) Conditionally build helper libraries just for the examples?
Building a single helper library where you put all shared modules into seems like a reasonable idea to me.
I can't believe that I'm the only package maintainer who has such a problem, so I really hope that there is some hidden solution out there I simply can't see...
It's not very pressing for me yet, but if you do find a solution, please let me know as well. :) Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

On Wed, Oct 16, 2013 at 02:17:04PM +0200, Sven Panne wrote:
Is there a way to build examples in a Haskell package with Cabal without actually running them? [...] I just want to check if e.g. all GLUT examples in https://github.com/haskell-opengl/GLUT/tree/master/examples still build after some API changes.
If you just want to check whether they *would* build correctly, is -fno-code of any help? It will type check but not actually build. It's also very quick. Tom

2013/10/18 Tom Ellis
On Wed, Oct 16, 2013 at 02:17:04PM +0200, Sven Panne wrote: If you just want to check whether they *would* build correctly, is -fno-code of any help? It will type check but not actually build. It's also very quick.
As explained above, my initial description of the use case was incomplete: I don't want Cabal to run all the executables, but I want to compile them all and selectively run a few of them later by hand.
participants (7)
-
adam vogt
-
Gauthier Segay
-
Heinrich Apfelmus
-
Mikhail Glushenkov
-
Ozgur Akgun
-
Sven Panne
-
Tom Ellis