I've been looking into this, and the weird line I mentioned before in
hadrian/src/Rules/Program.hs was to blame.

Make the following change and Hadrian will actually attempt to build a
stage 2 aarch64 compiler instead of simply copying the amd64 one from
the stage 1 directory (though I haven't tried running that stage 2
compiler yet).

diff --git a/hadrian/src/Rules/Program.hs b/hadrian/src/Rules/Program.hs
index 2490bffbd2..1ef88b0624 100644
--- a/hadrian/src/Rules/Program.hs
+++ b/hadrian/src/Rules/Program.hs
@@ -97,13 +97,7 @@ buildProgram bin ctx@(Context{..}) rs = do
   -- so we use pkgRegisteredLibraryFile instead.
   registerPackages =<< contextDependencies ctx
 -  cross <- flag CrossCompiling
-  -- For cross compiler, copy @stage0/bin/<pgm>@ to @stage1/bin/@.
-  case (cross, stage) of
-    (True, s) | s > stage0InTree -> do
-        srcDir <- buildRoot <&> (-/- (stageString stage0InTree -/- "bin"))
-        copyFile (srcDir -/- takeFileName bin) bin
-    _ -> buildBinary rs bin ctx
+  buildBinary rs bin ctx
  buildBinary :: [(Resource, Int)] -> FilePath -> Context -> Action ()
 buildBinary rs bin context@Context {..} = do

Making such a change brings up some errors about --host= not being a
valid argument, and I fixed those with the following change, which will
make the aforementioned attempt to build a compiler that runs on aarch64
actually succeed:

diff --git a/cross-build.ksh b/cross-build.ksh
index c7c1234a4f..d95d47d977 100644
--- a/cross-build.ksh
+++ b/cross-build.ksh
@@ -116,26 +116,22 @@ env \
   "stage1.*.cabal.configure.opts += \
     --configure-option=CPPFLAGS=--sysroot=$SYSROOT \
     --ghc-option=-optc--target=aarch64-unknown-openbsd \
-    --ghc-option=-optl--host=aarch64-unknown-openbsd \
     --ghc-option=-optl--target=aarch64-unknown-openbsd \
     --ghc-option=-opta--target=aarch64-unknown-openbsd" \
   "stage1.*.ghc.hs.opts += \
     -optc--target=aarch64-unknown-openbsd \
     -opta--target=aarch64-unknown-openbsd \
-    -optl--host=aarch64-unknown-openbsd \
     -optl--target=aarch64-unknown-openbsd \
     -optl--sysroot=$SYSROOT" \
   "stage1.*.ghc.c.opts += \
     -optc--target=aarch64-unknown-openbsd \
     -optc-fno-ret-protector \
-    -optl--host=aarch64-unknown-openbsd \
     -optl--target=aarch64-unknown-openbsd \
     -opta--target=aarch64-unknown-openbsd \
     -optl--sysroot=$SYSROOT \
     -optP--sysroot=$SYSROOT" \
   "stage1.*.ghc.link.opts += \
     -optc--target=aarch64-unknown-openbsd \
-    -optl--host=aarch64-unknown-openbsd \
     -optl--target=aarch64-unknown-openbsd \
     -opta--target=aarch64-unknown-openbsd \
     -optl--sysroot=$SYSROOT" \

So I guess those were part of the unnecessary flags (or no longer
necessary, --host definitely fixed some errors at the time for me). And
that's it in terms of the stage2:exe:ghc-bin target.

The issue comes in when you try to make the binary-dist target; it
starts off well, but at some point, it attempts to call the ghc-pkg in
the bindist directory before the tarball is actually created, and it
fails presumably because the ghc-pkg is an aarch64 binary. A catch-22.

That said, the error is a complaint about syntax error and snitches
on the ghc-pkg file, but when I open it, it's an aarch64 binary. I
suspect it's failing to launch for that reason and reporting that fact
to whatever's calling it, and that caller is not expecting that output
and complains about a syntax error.

I can try to manually copy the bindist directory over to my
OpenBSD/arm64 VM and see if it works, but might have to manually run
some steps that'd normally be run on the build machine instead of the
install machine. I guess the fix here is to move those steps to the
$ ./configure --prefix=… && gmake install part of the process.

Anyway, if I don't get round to it today, I'll hopefully try that
tomorrow and let you know how it goes.

It does seem to be a known issue since at least a year ago. See
https://gitlab.haskell.org/ghc/ghc/-/issues/23975#note_526549:

> The resulting binary under _build/stage2/bin is still a stage1 
> cross-compiler, that runs on the x86_64 platform.


> Hmm yes, that is not currently tested and I would imagine is broken with 
> hadrian.

By the way, I was able to build the aarch64 hello world and run it
without issues without the last commit on your fork which adds $PATH and
$LD_LIBRARY_PATH to the cc shim.

I wanted to see what errors you were getting without that change as it
should be inherited from the cross-build.ksh script, but I got none the
whole way through. That could be because I had an existing stage 1 or
something, but I'll rerun a fresh build and let you know about that,
too.

Cheers,
Habib

Reply via email to