Last two months , We have been working on the localization project , hold golang Developed program , Running on domestic platform , Operating systems are basically based on Linux, however CPU Architecture besides x86, also ARM and MIPS, Our usual Golang All run on x86
&& x64 Architecture CPU upper , So there are many pitfalls in the process of transplantation , Recorded here .

<>Golang Cross compiling

<> Cross compiling

stay X64 On ubuntu 16.04 The executable programs of other platforms are compiled on the system

<> see Golang Supported platforms and versions
go tool dist list
This command lists all go Language supported operating system and cpu framework

<>golang Cross compilation of

actually go Cross compiling is very simple , You just need to specify the system and CPU framework , There's basically no problem , After compiling, the file can be copied to the corresponding platform :
GOOS=linux GOARCH=arm64 go build xxx.go # Sometimes it needs to be added CGO_ENABLE=0 CGO_ENABLE=0
GOOS=linux GOARCH=arm64 go build xxx.go
go The cross compiler support of the language is very good , As long as you follow the above steps, there will be no problem . pit , It's mainly in the pit cgo!

<> use cgo Cross compilation of

use cgo, It must be specified CGO_ENABLE=1. And must be specified CC The parameter is the gcc Cross compiler for .
Suppose we mutate 64 position ARM The program of the platform , You have to download it in advance aarch64 Version of c++ Cross compiler tool
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=
./aarch64-unknown-linux-gnueabi-5.4.0-2.23-4.4.6/bin/aarch64-unknown-linux-gnueabi-gcc
go build xxx.go
If the CGO Called C The program depends on various libraries , Then the compilation process will report errors for various dependent libraries not found , Various basic functions are undefined . And they are the most basic libraries in the system, such as
libglibc,libgstream etc .

The solution is that it must be at compile time , Add the parameters of the link library , The linked library must cross compile the system library of the target platform instead of the current system .

This is when downloading the cross compiler tool chain , It usually comes with , I put it in the root of the system , And then through C++ The syntax of linking libraries at compile time links libraries in :
There are three main parameters :-I , -isystem , -L, -l
The following command is an example , Suppose the project uses phnono,curl,protobuf And other components
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=
./aarch64-unknown-linux-gnueabi-5.4.0-2.23-4.4.6/bin/aarch64-unknown-linux-gnueabi-gcc
-Wall -std=c++11 -Llib -isystem/aarch64/usr/include -L/aarch64/lib -ldl
-lpthread -Wl,-rpath-link,/aarch64/lib -L/aarch64/lib/aarch64-linux-gnu
-L/aarch64/usr/lib -I/aarch64/usr/include -L/aarch64/usr/lib/aarch64-linux-gnu
-ldl -lpthread -Wl,-rpath-link,/aarch64/usr/lib/aarch64-linux-gnu -lphonon
-lcurl -lprotobuf go build xxx.go
So far , Basically solve the problem of unable to compile .

<> Platform differences

In compiling ARM Version of the code , Several system calls were not found

* undefined: syscall.Dup2
* undefined: syscall.SYS_FORK
Solution : contrast golang Source code implementation :go/src/syscall/zsyscall_linux_amd64.go and
go/src/syscall/zsyscall_linux_arm64.go
, find arm Platform not implemented Dup2 But it does Dup3, The parameters are slightly different , The solution is to modify where the call is made :
// - syscall.Dup2(oldfd, newfd) Amend to read : syscall.Dup3(oldfd,newfd,0)
and SYS_FORK Call to , Find out golang Of ARM Realization is not realized at all fork System call for , No, SYS_FORK This macro or an alternative .
I have no choice but to modify the project code , take fork The system call of is changed to another way .

<>MIPS The size of the problem

report errors :go.o: compiled for a big endian system and target is little endian
Mainly reflected in the size of the end of the byte order , This is me cross compiling Mips A problem of version discovery , A close look at my compile command shows that :
CGO_ENABLED=1 GOOS=linux GOARCH=mips64 CC=
./mips64el-unknown-linux-gnu-5.4.0-2.12-2.6.32/bin/mips64el-unknown-linux-gnu-gcc
go build xxx.go
In the order here :CC What is specified is mips64el Compiler for ,el Represents the small end byte order , and GOARCH=mips64 This is the big endian order , Compilation error caused by inconsistency ,
Solution :go and gcc Maintaining unity , Subject to the target platform ( Loongson is small end byte order )

* take GOARCH Designated as mips64le( Note that le no el)
* It's better to add LDFLAG=-EL CGO_ENABLED=1 GOOS=linux GOARCH=mips64le CC=
./mips64el-unknown-linux-gnu-5.4.0-2.12-2.6.32/bin/mips64el-unknown-linux-gnu-gcc
LDFLAGS=-EL go build xxx.go
<>Tips

in summary :

* golang Program development uses less native system calls syscall
* It works go Solved , Don't use it as much as possible cgo
* If there is a module, it must pass C/C++ call , recommend C++ and golang separate ,C++ and Golang Use between programs socket And so on

Technology