r/haskell•
deech

[Announce] cabal-auto-expose: a build time library that auto detects modules & signatures with cabal2nix integration

Happy to announce cabal-auto-expose, a small Cabal build time library that detects and auto exposes modules and Backpack signatures in your project source so you get the convenience of (and a couple of advantages over) Stack and hpack but with both pure Cabal and Stack projects.

It also has cabal2nix integration and a fully worked demo.

The project README and API docs have a lot more detail.

As always let me know if you have any issues and enjoy!

Posted Sep 8, 2020, 10:15 PM UTC · edited

4610
george_____t•

I assume this was inspired by the recent poll?

Anyway, I'd consider using this if I weren't generally wary of custom Setup.hss. They seem to be responsible for the majority of the Cabal issues I currently have an eye on. And u/phadej calling them "evil" doesn't encourage me...

8
deechOP•

I've used Custom builds for years for other utilities without much of an issue except for breaking Cabal API changes. It's evil in the sense that everything is in IO and he's right a lot of that code is pretty crufty but it works and gives the user a pretty turn-key way of transparently kicking off complicated polyglot Haskell builds across platforms.

1
patrick_thomson•

This rules. We appreciate you, deech!

4
tom-md•

OK, as someone who has used Cabal a lot and wanted to get in to nix via cabal2nix, I gave this a try.

First I cloned the example:

% git remote -v
origin  https://github.com/deech/cabal-auto-expose (fetch)
origin  https://github.com/deech/cabal-auto-expose (push)
% git rev-parse HEAD
57ca8217f92162f3ec00920d6a8743620e9c770c

And replaced the setup file:

% git diff
diff --git a/auto-expose-example-project/Setup.hs b/auto-expose-example-project/Setup.hs
index 47f53fd..aed7e87 100644
--- a/auto-expose-example-project/Setup.hs
+++ b/auto-expose-example-project/Setup.hs
@@ -1,4 +1,4 @@
 import Distribution.Simple.AutoExpose as AutoExpose

 main :: IO ()
-main = AutoExpose.defaultMain
+main = AutoExpose.defaultMainGenerateCabal

Now I cabal configure and cabal build then look for Writing generated Cabal file:, ok. Here:

% cabal configure auto-expose-example-project
% cabal build auto-expose-example-project
/var/folders/m7/_2kqsz4n4c3ck8050glq4ggr0000gn/T/auto-expose-example-project-0.1.0.0-generated.cabal

Ok, this seemed odd. I wanted to use nix but to get the nix information I need to build once already. I guess that's the price I pay for the translation from cabal to a nix derivation. It need only be paid when the file structure changes, but that's pretty often and needs automated.

Now time to use cabal2nix to get a derivation. I think this means copy the generated cabal file over, replacing the current cabal file, and run cabal2nix .. At least, that's what is implied in the cabal2nix readme.

% cd auto-expose-example-project
% cp /var/folders/m7/_2kqsz4n4c3ck8050glq4ggr0000gn/T/auto-expose-example-project-0.1.0.0-generated.cabal auto-expose-test-project.cabal
% cabal2nix .
{ mkDerivation, base, Cabal, cabal-auto-expose, stdenv }:
mkDerivation {
  pname = "auto-expose-example-project";
  version = "0.1.0.0";
  src = ./.;
  isLibrary = true;
  isExecutable = true;
  setupHaskellDepends = [ base Cabal cabal-auto-expose ];
  libraryHaskellDepends = [ base ];
  executableHaskellDepends = [ base ];
  testHaskellDepends = [ base ];
  benchmarkHaskellDepends = [ base ];
  homepage = "https://github.com/deech/cabal-auto-expose#readme";
  license = stdenv.lib.licenses.mit;
}

Ok... but that .nix file looks odd. It doesn't have any of the discovered modules listed.

2
deechOP•

When the structure changes you need to do:

cabal build --only-reconfigure && cabal build

The build process should tell you where there generated Cabal file was written, I don't think specifying a path at the command line does anything as you did with:

cabal build /path/to/file.cabal

Can you verify that the generated Cabal file contains the discovered modules? If so is it possible that cabal2nix ignores them for custom build types?

I didn't document it in the README because (I thought) it's a less common use-case but you can also specify where the Cabal file is generated by providing your own FilePath.

2
tom-md•
% cabal build --only-reconfigure
cabal: unrecognized 'build' option `--only-reconfigure'
% cabal --version
cabal-install version 3.4.0.0
compiled using version 3.4.0.0 of the Cabal library

So with cabal 3.2 and 3.4 that doesn't work. Needs HEAD? Sorry, your docs probably say.

Regardless, the generated cabal does include the custom modules so it is probably as you say or at the very least an issue between me an cabal2nix.

1
deechOP•

Oops, sorry a typo on my part I meant:

cabal build --only-configure

followed by:

cabal build
2
tom-md•

Ah thanks. And I see this does not compile, but does generate a suitable cabal file. cabal2nix still misbehaves but that is a separate issue for when I have time to learn nix and upgrade the entire product build system.

1
codygman•

This is awesome, I'll be trying it out soon. Hugely appreciate the full example btw!

1