cross-compiling for alpine-aarch64
Closed this issue · 4 comments
Just leaving notes here as I don't think it's worth fixing per se, but this was rather a mess, so figured I might as well write it down for myself if nothing else. Feel free to close immediately unless you see something worth discussing.
- normal stuff, exporting a bunch of env vars:
LD=aarch64-alpine-linux-musl-ld CC=aarch64-alpine-linux-musl-gcc ARCH=arm64 CROSS_COMPILE=aarch64-alpine-linux-musl-
Normally LD and CC should come fromCROSS_COMPILE
, but$(CROSS_COMPILE)cc
does not exist so CC has to be set to make it use gcc instead (could also be worked around with a symlink), and LD is defined without CROSS_COMPILE in the makefile - alpine-specific: musl doesn't include argparse and one needs to add
-largp
to the link commands in the makefile. - cargo stuff:
- adding
--target=aarch64-unknown-linux-musl
to the cargo build command goes some way if the target has been added withrustup target add aarch64-unknown-linux-musl
previously (couldn't figure how to do that with the system rust and has to use rustup) - final link requires setting
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-alpine-linux-musl-gcc
as well on top, because why use standard environment variables... - the binary addr2line is at a slightly different location,
../sidecar/target/aarch64-unknown-linux-musl/$(if $(DEBUG),debug,release)/addr2line
(extra dir after target)
- adding
- the final ld relies on path so
_binary___sidecar_target_release_addr2line
needs to be updated to__binary_sidecar_start=_binary____sidecar_target_aarch64_unknown_linux_musl_release_addr2line
Here's a diff of the makefile for recap, with the env vars above that should contain everything for aarch64:
diff --git a/src/Makefile b/src/Makefile
index 8090f42..89e115c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -12,7 +12,7 @@ BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool
LIBBPF_SRC := $(abspath ../libbpf/src)
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
-SIDECAR := ../sidecar/target/$(if $(DEBUG),debug,release)/addr2line
+SIDECAR := ../sidecar/target/aarch64-unknown-linux-musl/$(if $(DEBUG),debug,release)/addr2line
# Use our own libbpf API headers and Linux UAPI headers distributed with
# libbpf to avoid dependency on system-wide headers, which could be missing or
# outdated
@@ -67,7 +67,7 @@ all: retsnoop simfail
clean:
$(call msg,CLEAN)
$(Q)rm -rf $(OUTPUT) retsnoop simfail bpftool
- $(Q)$(CARGO) clean --manifest-path=../sidecar/Cargo.toml
+ $(Q)$(CARGO) clean --manifest-path=../sidecar/Cargo.toml --target=aarch64-unknown-linux-musl
.PHONY: cscope
cscope:
@@ -128,16 +128,16 @@ $(OUTPUT)/mass_attacher.o: $(OUTPUT)/retsnoop.skel.h $(OUTPUT)/calib_feat.skel.h
$(SIDECAR)::
$(call msg,CARGO,addr2line)
- $(Q)$(CARGO) build --manifest-path=../sidecar/Cargo.toml $(if $(DEBUG),,--release)
+ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-alpine-linux-musl-gcc $(Q)$(CARGO) build --manifest-path=../sidecar/Cargo.toml $(if $(DEBUG),,--release) --target=aarch64-unknown-linux-musl
$(OUTPUT)/addr2line.embed.o: $(SIDECAR)
$(call msg,LLVM_STRIP,$<)
$(Q)$(LLVM_STRIP) -g $<
$(call msg,LD,$@)
$(Q)$(LD) -r -b binary \
- --defsym __binary_sidecar_start=_binary____sidecar_target_$(if $(DEBUG),debug,release)_addr2line_start \
- --defsym __binary_sidecar_end=_binary____sidecar_target_$(if $(DEBUG),debug,release)_addr2line_end \
- --defsym __binary_sidecar_size=_binary____sidecar_target_$(if $(DEBUG),debug,release)_addr2line_size \
+ --defsym __binary_sidecar_start=_binary____sidecar_target_aarch64_unknown_linux_musl_$(if $(DEBUG),debug,release)_addr2line_start \
+ --defsym __binary_sidecar_end=_binary____sidecar_target_aarch64_unknown_linux_musl_$(if $(DEBUG),debug,release)_addr2line_end \
+ --defsym __binary_sidecar_size=_binary____sidecar_target_aarch64_unknown_linux_musl_$(if $(DEBUG),debug,release)_addr2line_size \
-o $@ $<
$(OUTPUT)/addr2line.o: $(OUTPUT)/addr2line.embed.o
@@ -157,7 +157,7 @@ retsnoop: $(addprefix $(OUTPUT)/, \
mass_attacher.o) \
$(LIBBPF_OBJ)
$(call msg,BINARY,$@)
- $(Q)$(CC) $(CFLAGS) $^ -lelf -lz -o $@
+ $(Q)$(CC) $(CFLAGS) $^ -lelf -lz -largp -o $@
$(OUTPUT)/tests/simfail.o: $(OUTPUT)/tests/kprobe_bad_kfunc.skel.h \
$(OUTPUT)/tests/fentry_unsupp_func.skel.h \
@@ -168,7 +168,7 @@ simfail: $(addprefix $(OUTPUT)/tests/, \
simfail.o) \
$(LIBBPF_OBJ)
$(call msg,BINARY,$@)
- $(Q)$(CC) $(CFLAGS) $^ -lelf -lz -o $@
+ $(Q)$(CC) $(CFLAGS) $^ -lelf -lz -largp -o $@
# delete failed targets
.DELETE_ON_ERROR:
As a side note, if instead of cross compiling one goes the qemu-user route, cargo has a bug that makes it consume insane amount of memory when fetching its crate index while running under qemu-user.
That can be worked around by exporting CARGO_NET_GIT_FETCH_WITH_CLI=true
before running make, and this worked for me -- I'll be using the binary generated that way for now.
@martinetd I'm open to Makefile changes to make this easier, retsnoop's Makefile is not as crazy as, say, selftests/bpf/Makefile in Linux repo, so adding support for CROSS_COMPILE would be fine with me. If the musl stuff can be more or less isolated to one or two checks, that should be fine as well.
As for _binary____sidecar_target_release_addr2line_start not being there. This symbol name is automatically derived from the path (you changed it to ../sidecar/target/aarch64-unknown-linux-musl/release/addr2line
, so it will have extra _aarch64_unknown_linux_musl_
in the middle, I suspect. This is objcopy's convention, I don't have much control over this. But again, all that probably can be accommodated.
So if you feel like this has to be addressed, please send PR and let's talk about it.
Ah, I suspected something with the path for that ld symbol, but I kept the dashes in the target triplet instead of underscores, and ld didn't like dashes. Well, that sure works better and I've updated the first post with full instructions and an ugly diff for reference/recap, but nothing that could be merged as is.
As said initially I don't think it's necessarily worth fixing at this point -- unless someone comes in who want to e.g. package it for yocto, I'm not aware of any distribution doing cross build, I mostly looked because cargo + qemu-user was being stupid.
In particular I'm not sure how we could possibly do the mappings for cargo target and its env var; guessing the libc from CROSS_COMPILE doesn't sound like a good idea, so it's probably best to just leave some instructions instead? I don't know. If someone looks they might be able to find this issue ;)
Anyway, if it turns out I use retsnoop a bit I might look into packaging it for alpine, in which case I might send a patch just for argp, but it's a bit early for me at this point as it will be the first time I use it on an actual problem so I don't want to commit to anything right now.
@martinetd can this be closed?
I'd say cross compiling still isn't quite easy, but building the sidecar separately and pasing -largp
through LDFLAGS ought to work so it should have gotten quite a bit easier than last time I tried -- and I can't think of anything that'd be easy to improve anyway.
Thanks for the reminder, let's close this for now!