cgo on arm/android

1,430 views
Skip to first unread message

Bob Hemington

unread,
Jul 16, 2012, 11:50:10 PM7/16/12
to golan...@googlegroups.com
Hello,

I'm curious what is the status of using cgo on arm/android devices?

My main interest is using cgo to make JNI calls, through the android NDK.

Is it possible, or when might I be able to do so?

Thank you

Dave Cheney

unread,
Jul 17, 2012, 12:13:11 AM7/17/12
to Bob Hemington, golan...@googlegroups.com
Cgo on linux/arm work if you build from source, details here

http://code.google.com/p/go-wiki/wiki/GoArm

From what I understand android is essentially a new OS, it is too different from Linux.

Bob Hemington

unread,
Jul 17, 2012, 12:36:19 AM7/17/12
to golan...@googlegroups.com, Bob Hemington
Okay,

I've made what I thought to be an example.


package main

/*
        void callme(void){
                int a = 1;
                a += 2;
        }
*/
import "C"
import "fmt"

func main() {
        fmt.Println("Hello world!")
}


which gives me an error:
$ go build test.go

# runtime/cgo
cc1: error: unrecognized command line option '-marm'


I've set GOARCH=arm and built using the latest go source downloaded via 'hg clone https://code.google.com/p/go'.
Any tips on what I'm doing wrong?

Thank you

Daniel Skinner

unread,
Jul 17, 2012, 2:02:05 AM7/17/12
to golan...@googlegroups.com, Bob Hemington
I haven't played with cgo yet but if I'm not mistaken, the wiki linked to previously deals with the go toolchain on arm, not necessarily cross compilation where host arch is not arm. You may need to dig in to that portion of cgo to see what to do.

Just as an example, for gc cross compilation I have the following to bootstrap the toolchain (builds 5g and 5l)

export GOOS=linux
export GOARCH=arm
cd ~/local/go/src
./make.bash

and then this to build a source file and link

~/local/go/pkg/tool/linux_amd64/5g "$1".go
~/local/go/pkg/tool/linux_amd64/5l "$1".5
rm "$1".5
mv 5.out "$1"

That produces a binary I can run on the phone, built from my laptop.

I would be interested to hear about cross compilation with cgo, or any other information related.

Dave Cheney

unread,
Jul 17, 2012, 2:13:17 AM7/17/12
to Daniel Skinner, golan...@googlegroups.com, Bob Hemington
Hello,

Reposting to the list.

To cross compile

cd $GOROOT/src
CGO_ENABLED=0 GOARCH=arm GOOS=linux ./make.bash

Assuming you have those three variables exported, then any invocation
of go build will produce a binary that will run on an arm system.

note: subtle application of GOARM={5,6,7} not covered.

The reason you can't currently cross compile with cgo enabled are

1. very few people have the correct set of cross compiling gcc
compilers installed.

2. even if they did, the dist tool and cgo tool don't understand
how to use them anyway.

3. even if both were true, 5l has to have access to the /lib/ld.so.3
library for the target to correctly link.

4. finally, cgo would need access to the headers and -dev packages for the
target arm system to produce a cross compiled, dynamically linked binary.

Cheers

Dave

minux

unread,
Jul 25, 2012, 8:19:16 PM7/25/12
to Dave Cheney, Daniel Skinner, golan...@googlegroups.com, Bob Hemington
To the real interested, I provide a way to cross packages for ARM with cgo support
at the end of the mail (although it doesn't support Android, because we don't support
its bionic libc yet).

On Mon, Jul 16, 2012 at 11:13 PM, Dave Cheney <da...@cheney.net> wrote:
To cross compile

cd $GOROOT/src
CGO_ENABLED=0 GOARCH=arm GOOS=linux ./make.bash

Assuming you have those three variables exported, then any invocation
of go build will produce a binary that will run on an arm system.

note: subtle application of GOARM={5,6,7} not covered.

The reason you can't currently cross compile with cgo enabled are

1. very few people have the correct set of cross compiling gcc
compilers installed.
this is true, but setting up correct cross compiler for ARM is not that difficult.

2. even if they did, the dist tool and cgo tool don't understand
how to use them anyway.
cmd/dist won't need to know, because it doesn't deal with cgo.
cmd/go only know to invoke (native or cross compiler) gcc as 'gcc', this is
unfortunate. 

3. even if both were true, 5l has to have access to the /lib/ld.so.3
library for the target to correctly link.
i'm afraid this is not true. 5l doesn't need to access target library to link. 

4. finally, cgo would need access to the headers and -dev packages for the
target arm system to produce a cross compiled, dynamically linked binary.
setting up correct cross compiler for ARM includes geting these right.


It's certainly possible to do cross compiling with cgo support, but this process
is somewhat complicated.

1. you have to set up a correct cross compiler with basic libc header/library
(note again that currently, we only support glibc)
you should be able to compile some pthread code, for example,
test/bench/shootout/threadring.c in the Go tree. Assume your cross compiler
is named gcc-arm, and is in $PATH, try:
gcc-arm test/bench/shootout/threadring.c;
then copy the a.out to your target machine, and run it with ./a.out 10 to see
if your cross compiler is working correctly.
ps: there are a lot of prebuilt ARM toolchain you can use if you don't want
to build a cross toolchain yourself.

2. prepare a script named "gcc" that wraps your cross gcc, for example,
#!/bin/sh
/path/to/gcc-arm "$@"
But, don't add it to $PATH yet (don't forget to "chmod +x gcc").

3. bootstrap Go, assuming you're in $GOROOT/src:
# first, do a simple non-cgo cross go build:
GOARCH=arm GOOS=linux ./make.bash

4. we need to trick cmd/go into thinking we are doing native compile so that
it will allow us to enable cgo:
PATH=/path/to/your/gcc/wrapper:$PATH GOARCH=arm \
GOOS=linux CGO_ENABLED=1 ../bin/go install -a -v std
ps: after this step, you not only have a cross toolchain for ARM with cgo
support, you also have go/gofmt/godoc for your target machine in
$GOROOT/bin/linux_arm.

5. we are ready to do cross compiling now.
example usage:
PATH=/path/to/your/gcc/wrapper:$PATH GOARCH=arm \
GOOS=linux CGO_ENABLED=1 \
$GOROOT/bin/go build $GOROOT/misc/cgo/stdio/hello.go

of course, you only need to do step 1 to 4 once, and you can
use shell aliases or wrapper script to make your life easier to
cross develop Go.

PS: cmd/go don't allow you to cross compile on different OSes, and
it can't be tricked unless we change some code, for example, apply
CL 6449047 before step 1.
Reply all
Reply to author
Forward
0 new messages