Ticket #1452 (closed bug: invalid)

Opened 6 years ago

Last modified 4 years ago

Modules omitted from a .cabal file are not reported, but result in a non-functional library

Reported by: guest Owned by: guest
Priority: normal Milestone: Not GHC
Component: libraries (other) Version: 6.6.1
Keywords: Cabal Cc: pho@…
Operating System: Linux Architecture: x86
Type of failure: Difficulty: Moderate (less than a day)
Test Case: Blocked By:
Blocking: Related Tickets:

Change History

Changed 6 years ago by mechvel@…

  • keywords cyclic import added
  • difficulty changed from Unknown to Moderate (1 day)

The bug is easy to find. 18 .hs modules, each value (except 1 small function) is trivially defined as (\ _ _ ... -> error ""). Its complexity is only in many imported types and many imported values, with a bit of cyclic import.

Changed 6 years ago by guest

  • owner set to mechvel@…

Changed 6 years ago by guest

  • owner changed from mechvel@… to guest
  • status changed from new to assigned

Changed 6 years ago by simonpj

Serge writes (in separate email)

Recently I submitted a bug report #1452 for ghc-6.6.1 of undefined references at the stage of linking executable, and also of ignoring un-existing module import.

Now I discovered the following strange effect (see the report source modules) which, probably, explains much.

1. (minor note) The file Match.hs-boot is not needed. All the effects preserve after its removal.

2. The name Match must be in the list `other-modules:' in the file dm.cabal, which describes the package.

But it is not in dm.cabal ! Because I have forgotten to put it there. Further, make build still finds and compiles Match.hs. The only point where Match is needed is Reduce.hs: it imports `Match'. But why GHC finds Match.hs ? Probably, because it is in the current source directory. Then,

make install

succeeds. And further, the command

ghc $dmCpOpt --make Main

succeeds or not -- depending on whether `Match' is in dm.cabal or not!

First, I think that there is my oversight here. But the GHC + Cabal system behaves strange in this example. Must not it give a plain report of what is wrong with modules or package setting ? Say,

"Error:  `Match' is not in the package but is imported by  Reduce.hs."

Probably, this is the matter of Cabal.

Further, if GHC still finds Match.hs and builds the package, why this "undefined reference" appears while linking executable ?

Changed 6 years ago by simonpj

Duncan adds

Currently Cabal uses ghc --make to build packages. It starts from all the modules listed in the exposed-modules but ghc --make will find any other modules that are imported, even if they are not listed in the .cabal file in the exposed-modules or other-modules fields.

That's the current system. The right system I think is for Cabal to do the dependency analysis itself (it needs to do that for proper support of pre-processors anyway). That would allow Cabal to notice when modules are imported but not listed in either the exposed-modules or other-modules fields. It could issue a warning or an error.

Changed 6 years ago by simonpj

Just to make this 100% explicit:

  • Cabal uses ghc --make to build a bunch of .o files (including Match.o)
  • Cabal then links the .o files that are listed in dm.cabal (as exposed or other) to make a .a file. This list accidentally excludes Match.o
  • Cabal copies the .a file and the .hi files listed in dm.cabal (as exposed or other) to the install place, and registers them. Again, this list excludes Match.o

As a result, a client of the package compiles all right (so long as it does not import Match) but fails at the link stage, lacking symbols in Match.

This seems like a bug in Cabal, because it allows you to build and install an unusable package. Possible solutions I can think of:

  • Cabal does its own dependency analysis and calls GHC one module at a time
  • GHC gets a flag which prevents it finding any module other than those listed on the command line (although it may still do dependency analysis to figure out which order to compile them in)
  • The .cabal file is no longer reqd to list non-exposed modules. Instead Cabal works out what the non-exposed modules are (perhaps by calling GHC -M or something similar).

Changed 6 years ago by ross

Another possible solution:

  • Cabal currently puts preprocessor output in another directory, which it adds to the search path for ghc --make. If modules that don't require preprocessing were treated as having an identity preprocessor, and just copied into that directory (if they're listed in the .cabal file), then only that directory need be on the search path for ghc --make, and unlisted modules would generate compile errors.

Changed 6 years ago by ross

  • keywords Cabal added; cyclic import removed
  • summary changed from "undefined reference" while linking executable (for cyclic import project) in ghc-6.6.1 to Modules omitted from a .cabal file are not reported, but result in a non-functional library
  • component changed from Compiler to libraries (other)
  • milestone set to Not GHC

Changed 5 years ago by PHO

  • cc pho@… added

Changed 5 years ago by igloo

  • status changed from assigned to closed
  • resolution set to invalid

Changed 4 years ago by simonmar

  • difficulty changed from Moderate (1 day) to Moderate (less than a day)
Note: See TracTickets for help on using tickets.