I am having an headache with cross compilation from amd64 to arm7l
I could finally do it with Gitlab CI, so now, I compile my binary in a docker image, here is the dockerfile:
FROM golang
WORKDIR /go/src/gitlab.com/company/edge_to_bc
COPY . .
RUN dpkg --add-architecture armhf && apt update && apt-get install -y gcc-arm-linux-gnueabihf libltdl-dev:armhf
I build it as
Then I will build the the new container "cross-compil" ready with the name ubuntu:cross-compil
Now, I can compile my binary with:
docker run -it -v ${EDGE_TO_BC_PATH}/release:/go/src/gitlab.com/company/edge_to_bc/release ubuntu:cross-compil bash -c 'CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 go build -v -o ./release/edge_to_bc '
I can see my executable generated in ./release/edge_to_bc
Then I build my docker image:
docker build -t registry.gitlab.com/company/edge_to_bc:armhf .
And I push it.
In the Dockerfile, I just copy the executable from host:
FROM alpine:3.7
RUN apk --no-cache add ca-certificates libtool
WORKDIR /sunclient/
COPY ./release/edge_to_bc ./
EXPOSE 5555
CMD [ "./edge_to_bc" ]
But when I run it in my arm board with:
docker run --rm registry.gitlab.com/company/edge_to_bc:armhf
I get:
standard_init_linux.go:207: exec user process caused "no such file or directory"
When debugging, if I want to get list of files with
docker run --rm registry.gitlab.com/company/edge_to_bc:armhf
I get:
standard_init_linux.go:207: exec user process caused "exec format error"
Which indicate binary still not have correct format...
What did I miss ? I spent a lot of time on this topic, and don't have much more ideas.
When I check the architecture of binary, this is what I get:
edge_to_bc git:(master) ✗ readelf -h ./release/edge_to_bc
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x19209
Start of program headers: 52 (bytes into file)
Start of section headers: 23993360 (bytes into file)
Flags: 0x5000400, Version5 EABI, hard-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 10
Size of section headers: 40 (bytes)
Number of section headers: 49
Section header string table index: 48
On the target OS, this is what I get:
[root@gw-sol1 ~]# uname -a
Linux gw-sol-1 4.4.113-UNRELEASED #1 SMP PREEMPT Thu Mar 7 16:46:40 CET 2019 armv7l armv7l armv7l GNU/Linux
EDIT:
When I build the app directly on ARM device, it will work:
go build -o ./release/edge_to_bc -v -ldflags '-w -s -extldflags "-static"' ./...
the ELF:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x125f1
Start of program headers: 52 (bytes into file)
Start of section headers: 16594072 (bytes into file)
Flags: 0x5000400, Version5 EABI, hard-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 38
Section header string table index: 37
It seems quite similar to the other one, at least in architecture.
Then build the docker image:
docker build . -t image/peer-test:armhf