~sircmpwn/hare-dev

5 3

Hare driver quirks cross-compiling for aarch64

Details
Message ID
<CRJ7V078I4FZ.2ESAI62MO1N8F@bookchin>
DKIM signature
missing
Download raw message
Hi,

I've encountered some behavior surprising to me while playing around 
with some basic mixing of hare, C, and cross-compilation. I'm writing to
ask for each of these two surprises:
	1. Have I done something wrong / missed something in a man page?
	2. Does this look like a hare issue, gcc issue, or qbe issue?

# Setup
I'm on x86_64 Alpine Edge with the master branches of harec, hare, and 
qbe. The only interesting difference is: I'm using aarch64-none-elf-gcc
for cross compiling. I have edited config.mk to reflect this:

```Makefile
aarch64=aarch64-none-elf
AARCH64_AS=$(aarch64)-as
AARCH64_AR=$(aarch64)-ar
AARCH64_CC=$(aarch64)-gcc
AARCH64_LD=$(aarch64)-ld
```

With this setup, `hare build -t aarch64` works as expected. However once
I try linking with C, a couple strange things happen.

I've written a very basic uppercase function in C that uses no includes. 
And I'm calling this function from a very basic main.ha file. I compile
the c file with the -nostd* flags to get an object file:

```sh
aarch64-none-elf-gcc -v -Wall -Wextra -c \
    -static --static -nostdlib -nostdinc \
    -fno-builtin -fno-builtin-function \
    -o str_upper.o str_upper.c
```

And I pass the object file to hare:

```sh
hare build -v \
    -t aarch64 \
    -L$(pwd) -l:str_upper.o \
    -o out.bin main.ha \
```

You can find the exact setup+code to reproduce in
this repo[1], specifically this directory [2].

[1]: https://git.sr.ht/~roselandgoose/hare_and_c
[2]: https://git.sr.ht/~roselandgoose/hare_and_c/tree/main/item/cc_hare_calling_c

# Outcome
## 1: Incorrect linker invocation

The error is ($ld_path resolves to /usr/aarch64-none-elf/bin):

```sh
$ld_path/ld: cannot find crt0.o: No such file or directory
$ld_path/ld: cannot find -lc: No such file or directory
```

I'm able to fix this with: `env LD=aarch64-none-elf-ld hare build ...`

Even though I specified AARCH64_LD when I compiled the hare driver,
unless I specify LD here, hare build seems to invoke ld incorrectly.

This looks to me like an error constructing or parsing commandline
arguments, possibly related to startup code (crt0.o). Interestingly
once I have applied the fix, the log does not reference crt0 at all!

## 2: Trying (unneccessarily) to link with libc

I get a bunch of linker errors like
```
in function `rt.start_linux':
	temp.rt.1.s:12106: undefined reference to `environ'
... temp.rt.1.s:52308: undefined reference to `malloc'
... : undefined reference to `exit'
```

This can be fixed by adding the option "-T -libc" to exclude the libc
build tag.

So even though I'm quite intentionally avoiding libc, hare adds the libc
tag and so uses the `stdlib/rt/hare+libc.sc` linker script. I assume
this is the intended behavior, for some reason related to the challenges
of developing a simple compiler?

# Conslusion
I've really enjoyed using hare, and neither of these quirks are in any
way show-stopping, so thanks for such a fun and grok-able language (for
me anyways)!

If either of these might be bugs in the hare driver, and you have any 
hunches as to where, I'm happy to help look into this further!

Cheers,
Rosie Keith Languet
Details
Message ID
<CRJIQLSE2MB9.AAAIYXRMY9YH@taiga>
In-Reply-To
<CRJ7V078I4FZ.2ESAI62MO1N8F@bookchin> (view parent)
DKIM signature
missing
Download raw message
Cross-compiling with -lc presents some issues which have not yet been
addressed. You need to work out things like sysroots. It's not currently
possible without a great deal of fuss.
Details
Message ID
<20230330070922.54C8A1FAB7@pulk.fi>
In-Reply-To
<CRJ7V078I4FZ.2ESAI62MO1N8F@bookchin> (view parent)
DKIM signature
missing
Download raw message
Relevant excerpts from the build driver source:

// plan.ha:109
	ld_tool.0 = if (len(libs) > 0) {
		yield target.cc_cmd;
	} else {
		yield target.ld_cmd;
	};

// subcmds.ha:152
	if (len(libs) > 0) {
		append(tags, module::tag {
			mode = module::tag_mode::INCLUSIVE,
			name = strings::dup("libc"),
		});
	};

So, this is not a bug -- the presence of -l flags is used as a heuristic
to select which linker and tags to use. It would probably make sense to
add a flag to disable this behavior, or maybe only enable it when -lc is
used, so that freestanding C code could be linked to with less hassle.

As a side note, the *_tool globals really look like they should be moved
into the plan struct.
Details
Message ID
<CRJXB7KD8BXA.2FIJTD73P8WVF@bookchin>
In-Reply-To
<20230330070922.54C8A1FAB7@pulk.fi> (view parent)
DKIM signature
missing
Download raw message
Lassi: thanks for the thorough response!

> the presence of -l flags is used as a heuristic to select which linker
> and tags to use.
That makes enough sense. This probably fixes more builds than it breaks
at this point.

> It would probably make sense to add a flag to disable this behavior,
> or maybe only enable it when -lc is used

Or maybe a notice about this in the man page section for the -l flag?
I'm happy to submit a patch for that!

Drew: yeah I've steered clear of linking with libc (-lc, -l:libc.a, etc)

> It's not currently possible without a great deal of fuss.

My understanding was that I could avoid the sysroot issue (and so 
hopefully most of the fuss) by using only freestanding C code, and I
sent this mail in part to see if that usecase was one y'all would be
interested in discussing, receiving patches for, etc.

Reading between the lines a little - would you say that cross-compiling
with even freestanding C code is a 'youre on your own for now' business?
That's cool too! Things seem to work plenty well enough for me to still
move forward on the projects/experiments I've got in mind.

To both Lassi and Drew:

While I think I understand the implications of this code fairly well:
> // subcmds.ha:152

I'm less confident in my understanding of:
> // plan.ha:109
> 	ld_tool.0 = if (len(libs) > 0) {
> 		yield target.cc_cmd;
> 	} else {
> 		yield target.ld_cmd;
> 	};
While I've got a sense of what this is doing / why, I'm wondering if it
might be related to the first quirk I encountered. Since I get that
error (cannot find crt0.o, -lc) even when I specified -T -libc (and did
_Not_ pass '-lc' myself), there's got to be some other codepath that's
sending the '-lc' flag to ld. Perhaps gcc is adding "-l:crt0.o -lc" when
it calls ld (after having been called as ld_tool.0)? *shrug*

Should I look into this further or let this wait, since the sysroot task
will probably change a lot of relevant things anyways?

<3
RKL
Details
Message ID
<CRJY82AC85FV.2J7VKN99O3M1D@taiga>
In-Reply-To
<CRJXB7KD8BXA.2FIJTD73P8WVF@bookchin> (view parent)
DKIM signature
missing
Download raw message
On Thu Mar 30, 2023 at 9:00 PM CEST, Rosie Keith Languet wrote:
> Reading between the lines a little - would you say that cross-compiling
> with even freestanding C code is a 'youre on your own for now' business?
> That's cool too! Things seem to work plenty well enough for me to still
> move forward on the projects/experiments I've got in mind.

I would say that, at the moment, you're on your own as soon as both -l
and -t appear on your command line.
Details
Message ID
<CRK8BOV8N4XF.8QD8N40LITX@bookchin>
In-Reply-To
<CRJY82AC85FV.2J7VKN99O3M1D@taiga> (view parent)
DKIM signature
missing
Download raw message
👍
Reply to thread Export thread (mbox)