Skip to content

Instantly share code, notes, and snippets.

@ernesto-jimenez
Last active August 21, 2023 08:41
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ernesto-jimenez/8042366 to your computer and use it in GitHub Desktop.
Save ernesto-jimenez/8042366 to your computer and use it in GitHub Desktop.

Patch to cross compile to android with net/http support

Installation instructions

We need to patch Go's source code to allow cgo when cross-compiling and make Android-specific changes since it sometimes differs from linux (e.g.: it doesn't use /etc/resolv.conf for DNS config)

  1. Clone the go source: hg clone -u release https://code.google.com/p/go
  2. Enter the go source directory: cd go
  3. Apply the patch in this gist: patch -p1 < /path/to/patch/go_android.patch
  4. Enter the go/src directory: cd src
  5. Generate binaries for Android cross-compile: GOOS=linux GOARCH=arm ./make.bash
  6. Install standard packages for android: GOOS=linux GOARCH=arm CGOENABLED=1 ../bin/go install -tags android -a -v std

Example program for Android and running in the device

Requirements: an android device with remote debugging enabled, adb to build the binary. This doesn't require the device to be rooted.

This example is cross compiling the https://github.com/ernesto-jimenez/emit_urls project.

  1. Cross compile the binary: GOARM=5 GOOS=linux GOARCH=arm CGOENABLED=1 ../bin/go build -tags android -o main-arm $GOPATH/src/github.com/ernesto-jimenez/emit_urls/main.go
  2. Push binary to the Android device with adb: adb push main-arm /data/local/tmp/
  3. Run program in the device: adb shell ./data/local/tmp/main-arm http://rediris.es

Credits

This is based on the following patch from @minux https://codereview.appspot.com/6454055

diff -r 87dea3f5ebe7 src/cmd/go/build.go
--- a/src/cmd/go/build.go Fri Nov 29 08:32:31 2013 +1100
+++ b/src/cmd/go/build.go Thu Dec 19 17:34:24 2013 +0100
@@ -1928,9 +1928,9 @@
)
func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfiles []string) (outGo, outObj []string, err error) {
- if goos != toolGOOS {
- return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
- }
+ //if goos != toolGOOS {
+ //return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
+ //}
cgoCPPFLAGS := stringList(envList("CGO_CPPFLAGS"), p.CgoCPPFLAGS)
cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS)
diff -r 87dea3f5ebe7 src/pkg/net/dnsconfig_android.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/net/dnsconfig_android.go Thu Dec 19 17:34:24 2013 +0100
@@ -0,0 +1,53 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build android,linux
+
+package net
+
+import (
+ "fmt"
+ "os/exec"
+)
+
+type dnsConfig struct {
+ servers []string // servers to use
+ search []string // suffixes to append to local name
+ ndots int // number of dots in name to trigger absolute lookup
+ timeout int // seconds before giving up on packet
+ attempts int // lost packets before giving up on server
+ rotate bool // round robin among servers
+}
+
+// Using getprop since Android doesn't have resolv.conf
+func dnsReadConfig() (*dnsConfig, error) {
+ conf := new(dnsConfig)
+ conf.servers = make([]string, 3)[0:0] // small, but the standard limit
+ conf.search = make([]string, 0)
+ conf.ndots = 1
+ conf.timeout = 5
+ conf.attempts = 2
+ conf.rotate = false
+ var ip string
+
+ for i := 1; i <= 4; i++ {
+ out, err := exec.Command("/system/bin/getprop", fmt.Sprintf("net.dns%v", i)).Output()
+ m := len(out)
+ if err != nil {
+ continue
+ }
+ if m < 2 {
+ continue
+ }
+ ip = string(out[:m-1])
+
+ a := conf.servers
+ n := len(a)
+ a = a[0 : n+1]
+ a[n] = ip
+ conf.servers = a
+ }
+
+ return conf, nil
+}
diff -r 87dea3f5ebe7 src/pkg/net/dnsconfig_unix.go
--- a/src/pkg/net/dnsconfig_unix.go Fri Nov 29 08:32:31 2013 +1100
+++ b/src/pkg/net/dnsconfig_unix.go Thu Dec 19 17:34:24 2013 +0100
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd !android,linux netbsd openbsd
// Read system DNS config from /etc/resolv.conf
diff -r 87dea3f5ebe7 src/pkg/os/file_android.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/file_android.go Thu Dec 19 17:34:24 2013 +0100
@@ -0,0 +1,17 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build android,linux
+
+package os
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+ dir := Getenv("TMPDIR")
+ if dir == "" {
+ dir = "/data/local/tmp"
+ }
+ return dir
+}
+
diff -r 87dea3f5ebe7 src/pkg/os/file_non_android.go
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pkg/os/file_non_android.go Thu Dec 19 17:34:24 2013 +0100
@@ -0,0 +1,17 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd !android,linux netbsd openbsd
+
+package os
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+ dir := Getenv("TMPDIR")
+ if dir == "" {
+ dir = "/tmp"
+ }
+ return dir
+}
+
diff -r 87dea3f5ebe7 src/pkg/os/file_unix.go
--- a/src/pkg/os/file_unix.go Fri Nov 29 08:32:31 2013 +1100
+++ b/src/pkg/os/file_unix.go Thu Dec 19 17:34:24 2013 +0100
@@ -279,11 +279,3 @@
return name
}
-// TempDir returns the default directory to use for temporary files.
-func TempDir() string {
- dir := Getenv("TMPDIR")
- if dir == "" {
- dir = "/tmp"
- }
- return dir
-}
@Shaked
Copy link

Shaked commented Sep 6, 2015

Hey, seems like I keep getting /system/bin/sh: /data/local/tmp/main-arm: not executable: magic 7F45. Any idea?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment