Hi,

The stuff in this email has already been discussed on IRC with Simon M
so this email is mostly to record rationale and give other people the
opportunity to point out our mistakes.

So...

Various packages compile .c files as part of their build process (which
usually get linked with Haskell code). Some packages use ghc to compile
the C code, eg darcs and cabal apparently does this too so it will
become more common.

However ghc does not quite behave as a drop in replacement for gcc. Here
is an example problem:

When compiling darcs on a sparc with the CFLAGS="-mcpu=ultrasparc" we
get a compile failure when we get to compiling the C files. ghc is being
called like: ghc -c foo.c -o foo.o -optc-mcpu=ultrasparc
What goes wrong is that ghc calls gcc to compile the .c file to a .S
file and passes the -mcpu=ultrasparc option on to gcc but when it calls
gcc again to assemble the .S file to the .o file it does not pass the
-mcpu=ultrasparc option. This causes the assembler to fall back to sparc
v7 mode and therefore complain about the v8 instructions that gcc
emitted (since when gcc generated the assembly it was told that it was
ok to use the newer instructions).

So there is an obvious workaround to pass the CFLAGS options to ghc with
-opta as well as with -optc. In this case that works. You may also
object that I have no right to be passing flags like -mcpu=ultrasparc
and if I do I should know what I'm doing. This may be so, but in that
case it's hard to claim that ghc is a drop in replacement for gcc which
is how people are using it.

It turns out that ghc cannot simply pass all -optc options to the
assembler (which is again gcc) since it does not work. For example,
Simon M found that passing -g to the assembler generates odd results in
some case, but calling gcc to do the whole .c -> .S -> .o process with
-g works fine.

So this seems to be the solution (though it requires more changes in the
ghc driver code), that is for ghc to use gcc to go straight from .c
to .o rather than invoking gcc twice and going via a .S file.

So we think the rule should be: (in Make syntax)

          gcc -c foo.c -o foo.o $(CFLAGS) -I`ghc --print-libdir`/include
        = ghc -c foo.c -o foo.o $(addprefix -optc,$(CFLAGS))

where the version of gcc invoked is the one that ghc was told to use at
configure time (or is overridden by another ghc flag)

Exactly what happens when the user specifies -opta options under this
scheme is less clear, presumably these -opta flags are actually gcc
flags and not genuine assembler flags so they must be passed to gcc
direct and not given to gcc as assembler pass-through commands. If the
assembler commands mean nothing to the .c -> .S phase then it'd be ok to
just pass them to gcc anyway, but presumably this is not the case in
general in which case we'd have to fall back to invoking gcc twice with
the -opta commands the second time. And then what about the -optc ones
when it comes to the second phase? We already know we cannot pass all
-optc commands to gcc in the assembly phase.

Maybe that does make some sort of sense, if you specify any -opta
commands then ghc will invoke gcc in two phases and the -optc commands
will only apply to the first phase, but if you don't specify any -opta
commands then ghc will invoke gcc in one phase and gcc will work out
which options it has to pass on to the assembly phase. So just like if
you invoke gcc yourself twice (going via a .S file) then you are
responsible for figuring out which options are applicable to the
assembly phase. Unfortunately it's a bit less obvious when using ghc
since it is ghc that is invoking gcc twice on your behalf. So this
behaviour would need documenting clearly.

Still, I think it's worth it if people are going to be using ghc as if
it were gcc.

Duncan

_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to