Opened 5 years ago

Last modified 20 months ago

#3472 new bug

Porting through .hc files broken

Reported by: pumpkin Owned by:
Priority: high Milestone: 7.8.3
Component: Build System Version: 6.12.1 RC1
Keywords: Cc: filcab+ghc@…, barsoap@…, marco.comini@…, pho@…, khaelin@…, CBa, ngwese@…, dbkirk@…, sudish@…, slyfox@…, middleton.ted@…, g@…, brian.bloniarz@…, karel.gardas@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By: #7463
Blocking: Related Tickets:

Description (last modified by simonmar)

I've been trying repeatedly over the past week or two to get an x86_64 build of GHC for OS X, by going through the procedure described at http://hackage.haskell.org/trac/ghc/wiki/Building/Porting.

I've encountered several problems, and the process is huge and daunting so it's hard to say exactly what's a real error and what causes the breakage, but I'll try to describe what I've seen so far.

I've been treating the x86_64 unregistered build as a .hc port, so I effectively partitioned my box into two machines, one with a gcc that compiles to i386 by default and the other with one for x86_64. I follow the instructions on the page above and first generate the headers describing the 64-bit machine with the 64-bit compiler, then I copy them into another ghc tree, switch the gcc to i386 default, and do a build that keeps its .hc files. Most of it goes fine, and then I start getting massive errors about the assembly output being incorrect (which should be fine because all I want are the .hc files). So I follow the make -k and ignore the errors (although this is rather nerve-wracking as instructions saying "just ignore any errors" seem rather fragile). I then build the tarball with all the .hc files in it and unpack it in the other tree.

Now, I switch the gcc back to default x86_64, and go through the rest of the process described. My first issue is that the FB_ macro is inserting --- BEGIN --- explicitly into my assembly. This feels odd, as I'm doing an unregistered build. It seems that somehow the MINI_INTERPRETER macro and NO_REGS aren't getting defined, so the pre-mangler stuff is getting inserted into my assembly. I add -Ds for those to my build.mk and resume.

This goes smoothly for a while, and then I encounter an error:

make[1]: *** No rule to make target `rts/dist/build/Apply.o', needed by `rts/dist/build/libHSrts.a'.  Stop.

I check the rts directory and indeed there is an Apply.hc file in there. So I guess the build system forgot that .hc files produce .o files in the case of the rts. Maybe it's missing a .hc.o rule or something, so I tried to figure out the build system files but wasn't able to convince it to build the .hc files. I then emulated the gcc parameters used for other rts .c and .s files and compiled all the .hc files in the RTS myself. So I resume the make and it seems satisfied until it tries to build the rts in a different way (v, instead of l). Again, I compile all the .hc files by hand, and set the make on its merry way again.

Now I run into my real problem. It goes to build genprimopcode and doesn't know how to do it. I check utils/genprimopcode and indeed there are no .hc files in there. I jump back to my other tree (the one that produced the .hc files) and manually (guessing on the ghc command-line) ask it to produce all the .hc files for me, first calling alex and happy for the grammar. I copy these .hc files over and resume the build. It happily accepts my .hc files, but then when it goes to link genprimopcode, I get a massive list of missing symbols. These included things like:

_base_GHCziShow_showSignedInt1_closure
_stg_CAF_BLACKHOLE_info
_integerzmgmp_GHCziIntegerziType_Szh_static_info

So this seems to imply that it's trying to build an executable for genprimopcode, and it wants the rts (surprise), base, and integer-gmp linked to it. However, the command-line used to link genprimopcode is:

"gcc" -o utils/genprimopcode/dist/build/tmp/genprimopcode  -O -m64 -g -O0 -DNO_REGS -DUSE_MINIINTERPRETER            utils/genprimopcode/dist/build/Lexer.o utils/genprimopcode/dist/build/Main.o utils/genprimopcode/dist/build/ParserM.o utils/genprimopcode/dist/build/Parser.o utils/genprimopcode/dist/build/Syntax.o 

... no linker flags at all, beyond the .o files! I'm not sure how this is supposed to ever link correctly with no rts or libraries. So I take that command-line for gcc and add to it from my 64-bit build tree until I get it to link (it ended up being a massive command-line, so I won't include it here). My built genprimopcode seemed to work, and displayed the help message when I ran it, but when I actually piped real primop specs into it, it segfaulted (in iconv, somehow).

I gave up on making my own genprimopcode, and under the assumption that it wasn't excessively platform-dependent, I asked someone to give me the various genprimopcode from their linux x86_64 platform. This may have been misguided but I don't know enough about the process to know better. Anyway, with these files, it gave up on trying to build genprimopcode and went along happily through the build.

In the final linkage step for stage2, producing the final ghc binary, I got another massive linker error. Again, I tinkered with its command-line until I got it to link correctly (lots of strange things missing there too, including the PrelIOUtils.o which I had to link in myself for some reason, and something defining __hscore_long_path_size, which I wrote a simple c file for).

So anyway, the resulting ghc, somewhat unsurprisingly, segfaulted immediately (in Data.List.last, for what it's worth). ghc +RTS --info did work however, and printed out the expected stuff, so not everything was broken.

So anyway, I'm sorry for this rambling "bug report" but I'm not sure what to do, and I've been through the above process (with minor variations and experiments) about 5 times so far, so I'm pretty sure I'm following the instructions correctly.

Change History (32)

comment:1 Changed 5 years ago by simonmar

  • Component changed from Compiler to Build System
  • Description modified (diff)
  • Difficulty set to Unknown
  • Milestone set to 6.12 branch

regarding the NO_REGS/MINI_INTERPRETER problem, I think I know what went wrong there. We still have some old cruft in the build system that confused me when I made a change to the conditional surrounding the SRC_CC_OPTS setting in ghc.mk. I'll commit a fix.

comment:2 Changed 4 years ago by ksf

  • Summary changed from Porting through .hc files seems broken (seems general but parts of it may be osx-specific) to Porting through .hc files broken
  • Version changed from 6.11 to 6.12.1 RC1

make[1]: *** No rule to make target `rts/dist/build/Apply.o', needed by `rts/dist/build/libHSrts.a'. Stop.

I've encountered the same, I moved all .hc files to .c files, including AutoApply?.hc, which lives in dist. Seems to work out fine.

the NO_REGS/MINI_INTERPRETER issue is fixed in 6.12.0-rc1.

the primopcodes are copied over from the host according to the port process docs, but the build system doesn't get that they're already there and tries to build genprimopcode, anyway. I nuked the respective make rules, and stuff seems to work out fine (that is, it compiles).

I've also encountered various linker issues (and missing symbols beforehand, as haiku e.g. doesn't come with siginfo_t), but I guess these are quite normal while porting to a new platform. A stub for getlocale won't hurt the system, too.

I've also experienced segfaults in Data.List.last, but can say that ghc would have failed differently, anyway, due to wrong args etc.

However, there's two very, very important bits missing to the porting process:

1) Hs*Config.h (those for the libraries) aren't taken from the target system, but the host while generating .hc's (I'm looking into making the build system eat them, the naive approach didn't work (made make error out due to looping))

2) the intermediate .c files generated from .hsc files are compiled with the host's headers (which leads to fun bugs like ghc being confused about what consists a directory and what not, due to struct stat having a different layout). This can either be fixed by moving the intermediate files onto the target and compile+run them there (which is awkward), or pre-processing them on the host using the target's headers, then compiling+running them on the host (which is convenient, and should be safe to do). Another possibility, of course, is to switch to c2hs, which knows of cross-compiling.

I've also had issues with too big constants in .hc files, but instead of investigating the source, I switched to a 32-bit chroot for my host.

I'm going to flag my other bug as a duplicate of this.

comment:3 follow-up: Changed 4 years ago by ksf

  • Cc barsoap@… added

Solution 2 to issue 2 (running hsc2hs with the target's headers on the host) needs a cross-compiler, at least if the system's bytesizes differ. Otherwise, offsetof is going to return borkage, even if given the right headers.

comment:4 in reply to: ↑ 3 Changed 4 years ago by simonmar

Replying to ksf:

Solution 2 to issue 2 (running hsc2hs with the target's headers on the host) needs a cross-compiler, at least if the system's bytesizes differ. Otherwise, offsetof is going to return borkage, even if given the right headers.

In the past we've avoided using hsc2hs in parts of the libraries that are required by the bootstrap for exactly this reason. I think we recently regressed in this area since I started using System.Posix stuff to implement System.Directory; my humble apologies. It was fragile to start with though.

We either have to come up with a solution for using hsc2hs (take the intermediate C files to the target and compile/run them?) or convert .hsc files to autoconf + CPP (yeuch).

comment:5 Changed 4 years ago by ksf

We either have to come up with a solution for using hsc2hs (take the intermediate C files to the target and compile/run them?) or convert .hsc files to autoconf + CPP (yeuch).

It's quite straight-forward to split up the %.hsc->%.hs rule in two, the first one generating %_hsc_make with a cross-compiler, the second one moving the binary over to the target, executing it and piping the result into %.hs. Compiling on the target is certainly feasible, too, but I happen to have a working cross-compiler.

I am, however, stuck with make, in the area of separating the build directories into stage1/stage2 for the libraries as well as transferring ./configure output over from the target to the build platform, without having that trigger recompilation of stage1 (and the package info being a bit messed up wrt. -l flags, but that's a minor concern)

Compiling the stage2 libraries with actual target info also opens up the issue that we can't use the native gcc as it's quite likely to fail, not so much while compiling (at least .hc), but linking: My linux doesn't come with libutil, for example. Both using a cross-gcc and replacing gcc with touch should work, I've not had much time to investigate this.

The main issue, however, is that we're infecting perfectly cross-platform .hc with platform-specific information by preprocessing Haskell instead of C: It might be feasible to generate C stubs for all hsc2hs macros and calling them via the ffi, leaving resolving of platform-specific things until later. The whole build-process depending on .o s being generated even when all you want to have are .hc s isn't helping things.

And then there's David's LLVM work... I'm currently slurping his thesis because porting via LLVM looks very, very, elegant and painless, at least from afar.

comment:6 Changed 4 years ago by igloo

I'm not sure I follow; why do you need to have stage1 and stage2 library build directories?

comment:7 Changed 4 years ago by ksf

Both the stage1 and stage2 compilers need the same libraries, stage1 needs .o files native to the build platform, stage2 ones native to the target platform, and make likes to re-built the stage1 compiler as soon as I've built a library for the target because it just depends on the resulting .a . I would compile them with -C, but that breaks make's notion of dependencies. The current build system, iirc, just compiles those libraries once and uses them for both stages.

comment:8 Changed 4 years ago by igloo

stage1 should not need .o files native to the build platform (except for those built in dist-boot directories, which do not need to be used on the target platform).

comment:9 Changed 4 years ago by kili

For the primop stuff (and some other minor problems), please have a look at the documentation changes I did a few feeks ago:

http://hackage.haskell.org/trac/ghc/wiki/Building/Porting?action=diff&version=45&old_version=39

For some of the build problems on the target machine, I'll send some patches to cvs-ghc@ this day (actually the first one already sent).

For the hsc2hs problem: no idea (yet), I'm still waiting for my testbuild to fail (or finish) at some point.

comment:10 Changed 4 years ago by marco.comini

  • Cc marco.comini@… added

comment:11 Changed 4 years ago by donn

  • Type of failure set to None/Unknown

I just built and installed 6.12.0.20091121 on Haiku, using vaguely similar NetBSD-i386 as a donor. ksf already discussed the principle issues with the .hc build. Also:

package-depend.mk are infected with external library references from the donor host - e.g., if on NetBSD, openpty needs -lutil, then this library will be required on the target host.
Target host build directory must conform to absolute paths from the donor host.
compiler/main/Config.hs uses the donor host's absolute path for cGCC.

I dealt with the main issues by swapping in HsBaseConfig?.h from the target host, before stage2 ghc was built on the donor, and hacked in my own stat struct with the target's layout.

comment:12 Changed 4 years ago by PHO

  • Cc pho@… added

comment:13 Changed 4 years ago by filcab

  • Cc filcab+ghc@… added

comment:14 Changed 4 years ago by galdor

  • Cc khaelin@… added

comment:15 Changed 4 years ago by CBa

  • Cc CBa added

comment:16 Changed 4 years ago by igloo

  • Milestone changed from 6.12 branch to 6.12.3

comment:17 Changed 4 years ago by ngwese

  • Cc ngwese@… added

comment:18 Changed 4 years ago by igloo

  • Milestone changed from 6.12.3 to 6.14.1
  • Priority changed from normal to low

comment:19 follow-up: Changed 4 years ago by igloo

  • Priority changed from low to high

Many CCs, so high priority

comment:20 in reply to: ↑ 19 Changed 4 years ago by kili

Replying to igloo:

Many CCs, so high priority

Well, but as Simon (Marlow) told me several times, it will be still very difficult to use .hc files for porting GHC to another platform.

(Just to let the CCs know)

comment:21 Changed 4 years ago by dkirk

  • Cc dbkirk@… added

comment:22 Changed 4 years ago by sudish

  • Cc sudish@… added

comment:23 Changed 4 years ago by slyfox

  • Cc slyfox@… added

comment:24 Changed 4 years ago by igloo

  • Milestone changed from 6.14.1 to 6.14.2

No plans to work on this before 6.14.1.

comment:25 Changed 4 years ago by tedm

  • Cc middleton.ted@… added

comment:26 Changed 3 years ago by gbrewster

  • Cc g@… added

comment:27 Changed 3 years ago by phunge0

  • Cc brian.bloniarz@… added

comment:28 Changed 3 years ago by kgardas

  • Cc karel.gardas@… added

comment:29 Changed 3 years ago by simonmar

  • Milestone changed from 7.0.2 to 7.2.1

comment:30 Changed 3 years ago by igloo

  • Milestone changed from 7.4.1 to 7.6.1

Punting

comment:31 Changed 20 months ago by igloo

  • Milestone changed from 7.6.1 to 7.8.1

comment:32 Changed 17 months ago by PHO

  • Blocked By 7463 added
Note: See TracTickets for help on using tickets.