how do cabal internal libraries work?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

how do cabal internal libraries work?

Evan Laforge
The example at https://www.haskell.org/cabal/users-guide/developing-packages.html#library doesn't seem to work as I expect.  The doc for the library field is out of date, but if you scroll down it mentions "internal libraries".  But depending on the internal library doesn't seem to have any effect, in that cabal still complains I didn't mention Foo.Internal, and doesn't see the build-depends from it.  Am I misinterpreting how the feature is supposed to work?

This is with Cabal 2.2.0.1 and cabal-install 2.2.0.0, ghc 8.4.1:

% cat testing.cabal
name:           foo
version:        1.0
license:        BSD3
cabal-version:  >= 1.23
build-type:     Simple

library foo-internal
    exposed-modules: Foo.Internal
    build-depends: base, text

library
    exposed-modules: Foo.Public
    build-depends: foo-internal, base

% cat Foo/Internal.hs
module Foo.Internal where
import Data.Text

% cat Foo/Public.hs
module Foo.Public where
import Foo.Internal

% cabal build
Resolving dependencies...
Configuring foo-1.0...
Warning: Packages using 'cabal-version: >= 1.10' must specify the
'default-language' field for each component (e.g. Haskell98 or Haskell2010).
If a component uses different languages in different modules then list the
other ones in the 'other-languages' field.
Preprocessing library 'foo-internal' for foo-1.0..
Building library 'foo-internal' for foo-1.0..
[1 of 1] Compiling Foo.Internal     ( Foo/Internal.hs, dist/build/foo-internal/Foo/Internal.o )
[1 of 1] Compiling Foo.Internal     ( Foo/Internal.hs, dist/build/foo-internal/Foo/Internal.p_o )
Preprocessing library for foo-1.0..
Building library for foo-1.0..

<no location info>: warning: [-Wmissing-home-modules]
    These modules are needed for compilation but not listed in your .cabal file's other-modules: Foo.Internal
[1 of 2] Compiling Foo.Internal     ( Foo/Internal.hs, dist/build/Foo/Internal.o )

Foo/Internal.hs:2:1: error:
    Could not find module ‘Data.Text’
    Use -v to see a list of the files searched for.
  |
2 | import Data.Text
  | ^^^^^^^^^^^^^^^^

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how do cabal internal libraries work?

Ben Kolera
Do you get the same error if you give each library a different hs-source-dir ?

I don't know the actual reason, but I would guess that maybe something funny is happening with all of the modules being in the same folder.

Just a guess which is probably wrong! Hope it helps! :)

On Thu, 24 May 2018, 08:10 Evan Laforge, <[hidden email]> wrote:
The example at https://www.haskell.org/cabal/users-guide/developing-packages.html#library doesn't seem to work as I expect.  The doc for the library field is out of date, but if you scroll down it mentions "internal libraries".  But depending on the internal library doesn't seem to have any effect, in that cabal still complains I didn't mention Foo.Internal, and doesn't see the build-depends from it.  Am I misinterpreting how the feature is supposed to work?

This is with Cabal 2.2.0.1 and cabal-install 2.2.0.0, ghc 8.4.1:

% cat testing.cabal
name:           foo
version:        1.0
license:        BSD3
cabal-version:  >= 1.23
build-type:     Simple

library foo-internal
    exposed-modules: Foo.Internal
    build-depends: base, text

library
    exposed-modules: Foo.Public
    build-depends: foo-internal, base

% cat Foo/Internal.hs
module Foo.Internal where
import Data.Text

% cat Foo/Public.hs
module Foo.Public where
import Foo.Internal

% cabal build
Resolving dependencies...
Configuring foo-1.0...
Warning: Packages using 'cabal-version: >= 1.10' must specify the
'default-language' field for each component (e.g. Haskell98 or Haskell2010).
If a component uses different languages in different modules then list the
other ones in the 'other-languages' field.
Preprocessing library 'foo-internal' for foo-1.0..
Building library 'foo-internal' for foo-1.0..
[1 of 1] Compiling Foo.Internal     ( Foo/Internal.hs, dist/build/foo-internal/Foo/Internal.o )
[1 of 1] Compiling Foo.Internal     ( Foo/Internal.hs, dist/build/foo-internal/Foo/Internal.p_o )
Preprocessing library for foo-1.0..
Building library for foo-1.0..

<no location info>: warning: [-Wmissing-home-modules]
    These modules are needed for compilation but not listed in your .cabal file's other-modules: Foo.Internal
[1 of 2] Compiling Foo.Internal     ( Foo/Internal.hs, dist/build/Foo/Internal.o )

Foo/Internal.hs:2:1: error:
    Could not find module ‘Data.Text’
    Use -v to see a list of the files searched for.
  |
2 | import Data.Text
  | ^^^^^^^^^^^^^^^^
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: how do cabal internal libraries work?

Oleg Grenrus
In reply to this post by Evan Laforge
Hi Evan,

the cure to your problem is to put source files of different components
into different directories. i.e.

testing.cabal:

library foo-internal
    hs-source-dirs: internal
    exposed-modules: Foo.Internal
    build-depends: base, text

library
    hs-source-dirs: public
    exposed-modules: Foo.Public
    build-depends: foo-internal, base

and file layout:

public/Foo/Public.hs
internal/Foo/Internal.hs

Even Cabal tells GHC that "Foo.Public" is the only module it need to
compile, GHC "discovers" ./Foo/Internal.hs and happily uses it.
There are other similar interactions because of that implicitness, I'd
advice to avoid having current directory "." (the default) in the
hs-source-dirs.

Hopefully this helps,

P.S. try "cabal check", it will tell you (among possible other things),
that to use internal libraries you need to specify "cabal-version: 2.0",
and there's actually an open ticket to add a check for you exact problem
(if components depend on each other *and* share a hs-source-dirs, it's a
bad idea - you will end up recompiling modules).

On 24.05.2018 01:09, Evan Laforge wrote:

> The example at
> https://www.haskell.org/cabal/users-guide/developing-packages.html#library
> doesn't seem to work as I expect.  The doc for the library field is
> out of date, but if you scroll down it mentions "internal libraries". 
> But depending on the internal library doesn't seem to have any effect,
> in that cabal still complains I didn't mention Foo.Internal, and
> doesn't see the build-depends from it.  Am I misinterpreting how the
> feature is supposed to work?
>
> This is with Cabal 2.2.0.1 and cabal-install 2.2.0.0, ghc 8.4.1:
>
> % cat testing.cabal
> name:           foo
> version:        1.0
> license:        BSD3
> cabal-version:  >= 1.23
> build-type:     Simple
>
> library foo-internal
>     exposed-modules: Foo.Internal
>     build-depends: base, text
>
> library
>     exposed-modules: Foo.Public
>     build-depends: foo-internal, base
>
> % cat Foo/Internal.hs
> module Foo.Internal where
> import Data.Text
>
> % cat Foo/Public.hs
> module Foo.Public where
> import Foo.Internal
>
> % cabal build
> Resolving dependencies...
> Configuring foo-1.0...
> Warning: Packages using 'cabal-version: >= 1.10' must specify the
> 'default-language' field for each component (e.g. Haskell98 or
> Haskell2010).
> If a component uses different languages in different modules then list the
> other ones in the 'other-languages' field.
> Preprocessing library 'foo-internal' for foo-1.0..
> Building library 'foo-internal' for foo-1.0..
> [1 of 1] Compiling Foo.Internal     ( Foo/Internal.hs,
> dist/build/foo-internal/Foo/Internal.o )
> [1 of 1] Compiling Foo.Internal     ( Foo/Internal.hs,
> dist/build/foo-internal/Foo/Internal.p_o )
> Preprocessing library for foo-1.0..
> Building library for foo-1.0..
>
> <no location info>: warning: [-Wmissing-home-modules]
>     These modules are needed for compilation but not listed in your
> .cabal file's other-modules: Foo.Internal
> [1 of 2] Compiling Foo.Internal     ( Foo/Internal.hs,
> dist/build/Foo/Internal.o )
>
> Foo/Internal.hs:2:1: error:
>     Could not find module ‘Data.Text’
>     Use -v to see a list of the files searched for.
>   |
> 2 | import Data.Text
>   | ^^^^^^^^^^^^^^^^
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: how do cabal internal libraries work?

Evan Laforge
On Wed, May 23, 2018 at 3:50 PM, Oleg Grenrus <[hidden email]> wrote:
> Hi Evan,
>
> the cure to your problem is to put source files of different components
> into different directories. i.e.

Yes, that's exactly it!  Thanks for the explanation.

> Even Cabal tells GHC that "Foo.Public" is the only module it need to
> compile, GHC "discovers" ./Foo/Internal.hs and happily uses it.
> There are other similar interactions because of that implicitness, I'd
> advice to avoid having current directory "." (the default) in the
> hs-source-dirs.

Indeed, though it's an awkward and surprising limitation, to me at
least.  I would think ghc would be looking for
dist/build/library/Foo/Internal.hi, and not find it.  I assume it has
to do with ghc --make is sort of a build system, and cabal is sort of
a build system, and they sort of cooperate with each other :)
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.