Ticket #7405 (closed bug: wontfix)

Opened 6 months ago

Last modified 6 months ago

use of -no-hs-main causes TH compiles to fail

Reported by: MtnViewMark Owned by:
Priority: normal Milestone: 7.8.1
Component: Template Haskell Version: 7.4.2
Keywords: Cc:
Operating System: MacOS X Architecture: x86
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

If you compile a project with -no-hs-main, so that you can (for example) have a c based main that runs first, then you can't use template haskell, as during compilation, the template haskell code fails to link and run.

What appears to happen is that the .c file with the "real main" gets loaded (in order to have a main), but it fails to find the function it will call as it is (directly, or transitively) dependent on the very template haskell enabled .hs file being compiled.

The attached tar ball is a simple cabal based project that builds three executables:

  • plain-main - plain HS main, using a TH value
  • c-no-th-main - c based main, calling into a HS function, no TH
  • c-main - c based main, calling into a HS function that uses TH

The c-main program will fail to build, while the other two work (demonstrating that the TH code is reasonable, and that the c main function is reasonable.)

Attachments

main-th-test.tgz Download (1.3 KB) - added by MtnViewMark 6 months ago.
small project (four files) that demonstrate the issue
cabal-out.txt Download (5.1 KB) - added by MtnViewMark 6 months ago.

Change History

Changed 6 months ago by MtnViewMark

small project (four files) that demonstrate the issue

Changed 6 months ago by MtnViewMark

Changed 6 months ago by MtnViewMark

tl;dr: If you have any .c files in a project, they can't depend (even transitively) on any .hs modules that use TH - since all .o files are loaded during the TH expansions. If you have a .c file for an alternate main (hence using -no-hs-main), then the whole program is a transitive dependency, and hence can't use TH anywhere!

cabal-out.txt shows a somewhat re-formatted output of build from cabal -v -v.

You can see that in the case that fails to build (the third executable) the ghc --make command includes the real-main.o file (from the C compilation), as one would expect. The problem is that this .o file is getting loaded during the TH execution... presumably GHC can't tell if the .o files will be needed or not by TH code being run, and so just includes it to be safe.

The problem is that that .o file depends, in this case directly, on the module being spliced by TH.

It turns out that the -no-hs-main flag is a red herring - it is just that when you compile with -no-hs-main, you usually include a .c file that depends on some Haskell main-like entry point.... which by design transitively depends on the rest of the program. Hence, none of the program can use TH - since the .o file compiled from the .c file will be loaded into all TH runs.

Changed 6 months ago by simonmar

  • difficulty set to Unknown
  • milestone set to 7.8.1

I understand the problem (thanks for a good analysis), but I don't see an easy way to fix it. GHC can't know, for a given .o file, whether it is needed by the transitive dependencies of the current .hs file. I'm all out of bright ideas on this one. Anyone else?

Changed 6 months ago by igloo

  • status changed from new to closed
  • resolution set to wontfix

I agree, this isn't something we can/should fix.

Mark, you could work around the problem by moving the TH module and everything below it into a library. Or even moving all the Haskell code into a library, and just having the C main as an executable. Cabal packages can contain both a library and an executable, so as long as there is only one cut point it won't have too much overhead.

Note: See TracTickets for help on using tickets.