Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

cabal test with build-dep on self has surprising source directory behavior #1084

Open
ezyang opened this Issue · 5 comments

3 participants

@ezyang
Collaborator

A common situation is to setup a Cabal package with a library and a test-suite for the library, e.g. for package 'foo', one might try:

library
  exposed-modules:     Foo

test-suite tests
  type: exitcode-stdio-1.0
  main-is: Foo/Test.hs
  build-depends: foo

This will not do what you want: in particular, when Foo/Test.hs is compiled, it will automatically pick up the source directory of the library (which is by default '.') and compile against Foo.hs directly, rather than pick up the Foo exported by the inplace installed 'foo' library.

Now, this might not be so bad, except occasionally you'll get mysterious type errors like:

    Couldn't match expected type `foo-0.1.0.0:Foo.Program'
                with actual type `Foo.Program'

or

Test.hs:4:13:
    Ambiguous occurrence `F'
    It could refer to either `Foo.F',
                             imported from `Foo' at Test.hs:1:1-10
                             (and originally defined in `Bar')
                          or `Bar.F', imported from `Bar' at Test.hs:2:1-10

What's going on here? One way to make the bug manifest is when you depend on any source files which need a preprocessor run to generate the actual HS file (for example, a Happy or Alex file, or an hsc or c2hs file). Because those modules are not listed as "other-modules", Cabal will not build them, and then when GHC actually tries to build the original file, it will pick up the inplace installed library. You can probably also get this bug to show up in other cases too.

The workaround is to force the test-suite to use a different source directory, so it doesn't pick up library sources; Cabal should warn about that at least. But maybe there's a way to mask out exposed-modules from the test-suite compilation so we can have both of the source directories be the same.

A sample package which displays this problem is available here: http://web.mit.edu/~ezyang/Public/libtest-0.1.0.0.tar.gz

@tibbe
Owner

I've fixed the preprocessor issue for test suites and benchmarks in #1087.

@tibbe
Owner

I believe the issue is that when we compile using --make (which we do) GHC happily picks up any dependencies it can find on its search path. I can see us going one of two ways:

  • Require that all modules that should be compiled are listed in either exposed-modules or other-modules. We could enforce this by symlinking those modules into another directory and running the build there.
  • Get rid of other-modules entirely and always chase dependencies using the import statements in the files listed in exposed-modules or main-is.
@ezyang
Collaborator

Duncan and I talked about this a little, and I think Duncan claimed that (2) (tracing the dependencies manually) would be highly nontrivial and also inefficient, and it would just be better to keep asking people to explicitly specify modules in the Cabal file.

@tibbe
Owner

I'm fine with that. We should then try to design a mechanism that enforces that all dependencies are listed. Here's a strawman: symlink copy all the source files to a new directory before building. It would be nice to do this in such a way that we don't trigger unnecessary recompilation by GHC. A nice side-effect of this is that doing distributed compiles will be easier, as building outside the source tree will make sure that packages fully specify their dependencies (and are thus hermetic).

@ghost

As it happens, I just hit this with Alex + Happy, and happily (hee), using the suggested workaround (forcing the test-suite into a different directory) solved it.

Thanks!

@ttuegel ttuegel added this to the _|_ milestone
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.