cmd/gomobile: add -n and -x flags
Besides being useful for debugging, I intend to use these in a followup CL to write some simple tests. Change-Id: I9420c0b72111bcc86ce0330886106221aab533ba Reviewed-on: https://go-review.googlesource.com/4690 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
parent
7e40b31538
commit
1a5645cad8
@ -23,6 +23,8 @@ import (
|
||||
|
||||
var ctx = build.Default
|
||||
var pkg *build.Package
|
||||
var ndkccpath string
|
||||
var tmpdir string
|
||||
|
||||
var cmdBuild = &command{
|
||||
run: runBuild,
|
||||
@ -50,12 +52,12 @@ These build flags are shared by the build, install, and test commands.
|
||||
For documentation, see 'go help build':
|
||||
-a
|
||||
-i
|
||||
-n
|
||||
-x
|
||||
-tags 'tag list'
|
||||
`,
|
||||
}
|
||||
|
||||
// TODO: -n
|
||||
// TODO: -x
|
||||
// TODO: -mobile
|
||||
|
||||
func runBuild(cmd *command) error {
|
||||
@ -93,11 +95,18 @@ func runBuild(cmd *command) error {
|
||||
return fmt.Errorf(`%s does not import "golang.org/x/mobile/app"`, pkg.ImportPath)
|
||||
}
|
||||
|
||||
workPath, err := ioutil.TempDir("", "gobuildapk-work-")
|
||||
if err != nil {
|
||||
return err
|
||||
if buildN {
|
||||
tmpdir = "$WORK"
|
||||
} else {
|
||||
tmpdir, err = ioutil.TempDir("", "gobuildapk-work-")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer removeAll(tmpdir)
|
||||
if buildX {
|
||||
fmt.Fprintln(os.Stderr, "WORK="+tmpdir)
|
||||
}
|
||||
defer os.RemoveAll(workPath)
|
||||
|
||||
libName := path.Base(pkg.ImportPath)
|
||||
manifestData, err := ioutil.ReadFile(filepath.Join(pkg.Dir, "AndroidManifest.xml"))
|
||||
@ -126,20 +135,21 @@ func runBuild(cmd *command) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
libPath := filepath.Join(workPath, "lib"+libName+".so")
|
||||
libPath := filepath.Join(tmpdir, "lib"+libName+".so")
|
||||
|
||||
gopath := goEnv("GOPATH")
|
||||
var ccpath string
|
||||
for _, p := range filepath.SplitList(gopath) {
|
||||
ccpath = filepath.Join(p, filepath.FromSlash("pkg/gomobile/android-"+ndkVersion+"/arm/bin"))
|
||||
if _, err = os.Stat(ccpath); err == nil {
|
||||
ndkccpath = filepath.Join(p, filepath.FromSlash("pkg/gomobile/android-"+ndkVersion))
|
||||
if _, err = os.Stat(filepath.Join(ndkccpath, "arm", "bin")); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil || ccpath == "" {
|
||||
if err != nil || ndkccpath == "" {
|
||||
// TODO(crawshaw): call gomobile init
|
||||
return fmt.Errorf("android %s toolchain not installed in $GOPATH/pkg/gomobile, run gomobile init", ndkVersion)
|
||||
return fmt.Errorf("android toolchain not installed in $GOPATH/pkg/gomobile, run:\n\tgomobile init")
|
||||
}
|
||||
if buildX {
|
||||
fmt.Fprintln(os.Stderr, "NDKCCPATH="+ndkccpath)
|
||||
}
|
||||
|
||||
gocmd := exec.Command(
|
||||
@ -164,14 +174,19 @@ func runBuild(cmd *command) error {
|
||||
`GOARCH=arm`,
|
||||
`GOARM=7`,
|
||||
`CGO_ENABLED=1`,
|
||||
`CC=` + filepath.Join(ccpath, "arm-linux-androideabi-gcc"),
|
||||
`CXX=` + filepath.Join(ccpath, "arm-linux-androideabi-g++"),
|
||||
`CC=` + filepath.Join(ndkccpath, "arm", "bin", "arm-linux-androideabi-gcc"),
|
||||
`CXX=` + filepath.Join(ndkccpath, "arm", "bin", "arm-linux-androideabi-g++"),
|
||||
`GOGCCFLAGS="-fPIC -marm -pthread -fmessage-length=0"`,
|
||||
`GOROOT=` + goEnv("GOROOT"),
|
||||
`GOPATH=` + gopath,
|
||||
}
|
||||
if err := gocmd.Run(); err != nil {
|
||||
return err
|
||||
if buildX {
|
||||
printcmd("%s", strings.Join(gocmd.Env, " ")+" "+strings.Join(gocmd.Args, " "))
|
||||
}
|
||||
if !buildN {
|
||||
if err := gocmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
block, _ := pem.Decode([]byte(debugCert))
|
||||
@ -194,9 +209,21 @@ func runBuild(cmd *command) error {
|
||||
return err
|
||||
}
|
||||
|
||||
apkw := NewWriter(out, privKey)
|
||||
var apkw *Writer
|
||||
if !buildN {
|
||||
apkw = NewWriter(out, privKey)
|
||||
}
|
||||
apkwcreate := func(name string) (io.Writer, error) {
|
||||
if buildV {
|
||||
fmt.Fprintf(os.Stderr, "apk: %s\n", name)
|
||||
}
|
||||
if buildN {
|
||||
return ioutil.Discard, nil
|
||||
}
|
||||
return apkw.Create(name)
|
||||
}
|
||||
|
||||
w, err := apkw.Create("AndroidManifest.xml")
|
||||
w, err := apkwcreate("AndroidManifest.xml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -204,16 +231,18 @@ func runBuild(cmd *command) error {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := os.Open(libPath)
|
||||
w, err = apkwcreate("lib/armeabi/lib" + libName + ".so")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w, err = apkw.Create("lib/armeabi/lib" + libName + ".so")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(w, r); err != nil {
|
||||
return err
|
||||
if !buildN {
|
||||
r, err := os.Open(libPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(w, r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Add any assets.
|
||||
@ -238,7 +267,7 @@ func runBuild(cmd *command) error {
|
||||
return nil
|
||||
}
|
||||
name := "assets/" + path[len(assetsDir)+1:]
|
||||
w, err := apkw.Create(name)
|
||||
w, err := apkwcreate(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -254,14 +283,30 @@ func runBuild(cmd *command) error {
|
||||
|
||||
// TODO: add gdbserver to apk?
|
||||
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
return apkw.Close()
|
||||
}
|
||||
|
||||
func printcmd(format string, args ...interface{}) {
|
||||
cmd := fmt.Sprintf(format+"\n", args...)
|
||||
if tmpdir != "" {
|
||||
cmd = strings.Replace(cmd, tmpdir, "$WORK", -1)
|
||||
}
|
||||
if ndkccpath != "" {
|
||||
cmd = strings.Replace(cmd, ndkccpath, "$NDKCCPATH", -1)
|
||||
}
|
||||
fmt.Fprint(os.Stderr, cmd)
|
||||
}
|
||||
|
||||
// "Build flags", used by multiple commands.
|
||||
var (
|
||||
buildA bool // -a
|
||||
buildV bool // -v
|
||||
buildI bool // -i
|
||||
buildN bool // -n
|
||||
buildV bool // -v
|
||||
buildX bool // -x
|
||||
buildO *string // -o
|
||||
)
|
||||
|
||||
@ -271,20 +316,21 @@ func addBuildFlags(cmd *command) {
|
||||
cmd.flag.Var((*stringsFlag)(&ctx.BuildTags), "tags", "")
|
||||
}
|
||||
|
||||
func addBuildFlagsNXV(cmd *command) {
|
||||
// TODO: -n, -x
|
||||
func addBuildFlagsNVX(cmd *command) {
|
||||
cmd.flag.BoolVar(&buildN, "n", false, "")
|
||||
cmd.flag.BoolVar(&buildV, "v", false, "")
|
||||
cmd.flag.BoolVar(&buildX, "x", false, "")
|
||||
}
|
||||
|
||||
func init() {
|
||||
buildO = cmdBuild.flag.String("o", "", "output file")
|
||||
addBuildFlags(cmdBuild)
|
||||
addBuildFlagsNXV(cmdBuild)
|
||||
addBuildFlagsNVX(cmdBuild)
|
||||
|
||||
addBuildFlags(cmdInstall)
|
||||
addBuildFlagsNXV(cmdInstall)
|
||||
addBuildFlagsNVX(cmdInstall)
|
||||
|
||||
addBuildFlagsNXV(cmdInit)
|
||||
addBuildFlagsNVX(cmdInit)
|
||||
}
|
||||
|
||||
// A random uninteresting private key.
|
||||
|
@ -57,20 +57,33 @@ func runInit(cmd *command) error {
|
||||
if len(gopaths) == 0 {
|
||||
return fmt.Errorf("GOPATH is not set")
|
||||
}
|
||||
ndkccpath = filepath.Join(gopaths[0], filepath.FromSlash("pkg/gomobile/android-"+ndkVersion))
|
||||
if buildX {
|
||||
fmt.Fprintln(os.Stderr, "NDKCCPATH="+ndkccpath)
|
||||
}
|
||||
|
||||
dst := filepath.Join(gopaths[0], filepath.FromSlash("pkg/gomobile/android-"+ndkVersion+"/arm"))
|
||||
if err := os.RemoveAll(dst); err != nil && !os.IsExist(err) {
|
||||
if err := removeAll(ndkccpath); err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Join(dst, "sysroot", "usr"), 0755); err != nil {
|
||||
dst := filepath.Join(ndkccpath, "arm")
|
||||
dstSysroot := filepath.Join(dst, "sysroot", "usr")
|
||||
if err := mkdir(dstSysroot); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpdir, err := ioutil.TempDir(dst, "gomobile-init-")
|
||||
if err != nil {
|
||||
return err
|
||||
if buildN {
|
||||
tmpdir = filepath.Join(ndkccpath, "work")
|
||||
} else {
|
||||
var err error
|
||||
tmpdir, err = ioutil.TempDir(ndkccpath, "gomobile-init-")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
if buildX {
|
||||
fmt.Fprintln(os.Stderr, "WORK="+tmpdir)
|
||||
}
|
||||
defer removeAll(tmpdir)
|
||||
|
||||
ndkName := "android-" + ndkVersion + "-" + runtime.GOOS + "-" + arch + "."
|
||||
if runtime.GOOS == "windows" {
|
||||
@ -78,46 +91,27 @@ func runInit(cmd *command) error {
|
||||
} else {
|
||||
ndkName += "bin"
|
||||
}
|
||||
f, err := os.OpenFile(filepath.Join(tmpdir, ndkName), os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
url := "http://dl.google.com/android/ndk/" + ndkName
|
||||
|
||||
if buildV {
|
||||
fmt.Fprintf(os.Stderr, "fetching %s\n", url)
|
||||
}
|
||||
|
||||
// TODO(crawshaw): The arm compiler toolchain compresses to 33 MB, less than a tenth of the NDK. Provide an alternative binary download.
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
if err := fetch(filepath.Join(tmpdir, ndkName), url); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(f, resp.Body)
|
||||
err2 := resp.Body.Close()
|
||||
err3 := f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
if err3 != nil {
|
||||
return err3
|
||||
}
|
||||
|
||||
inflate := exec.Command(filepath.Join(tmpdir, ndkName))
|
||||
inflate.Dir = tmpdir
|
||||
out, err := inflate.CombinedOutput()
|
||||
if err != nil {
|
||||
if buildV {
|
||||
os.Stderr.Write(out)
|
||||
if buildX {
|
||||
printcmd("%s", inflate.Args[0])
|
||||
}
|
||||
if !buildN {
|
||||
out, err := inflate.CombinedOutput()
|
||||
if err != nil {
|
||||
if buildV {
|
||||
os.Stderr.Write(out)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
srcSysroot := filepath.Join(tmpdir, "android-ndk-r10d", "platforms", "android-15", "arch-arm", "usr")
|
||||
dstSysroot := filepath.Join(dst, "sysroot", "usr")
|
||||
if err := move(dstSysroot, srcSysroot, "include", "lib"); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -128,11 +122,11 @@ func runInit(cmd *command) error {
|
||||
}
|
||||
|
||||
linkpath := filepath.Join(dst, "arm-linux-androideabi", "bin")
|
||||
if err := os.MkdirAll(linkpath, 0755); err != nil {
|
||||
if err := mkdir(linkpath); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, name := range []string{"ld", "ld.gold", "as", "gcc", "g++"} {
|
||||
if err := os.Symlink(filepath.Join(dst, "bin", "arm-linux-androideabi-"+name), filepath.Join(linkpath, name)); err != nil {
|
||||
if err := symlink(filepath.Join(dst, "bin", "arm-linux-androideabi-"+name), filepath.Join(linkpath, name)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -161,22 +155,55 @@ func runInit(cmd *command) error {
|
||||
make.Stdout = os.Stdout
|
||||
make.Stderr = os.Stderr
|
||||
}
|
||||
if buildX {
|
||||
printcmd("%s", strings.Join(make.Env, " ")+" "+strings.Join(make.Args, " "))
|
||||
}
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
if err := make.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func move(dst, src string, names ...string) error {
|
||||
for _, name := range names {
|
||||
if err := os.Rename(filepath.Join(src, name), filepath.Join(dst, name)); err != nil {
|
||||
srcf := filepath.Join(src, name)
|
||||
dstf := filepath.Join(dst, name)
|
||||
if buildX {
|
||||
printcmd("mv %s %s", srcf, dstf)
|
||||
}
|
||||
if buildN {
|
||||
continue
|
||||
}
|
||||
if err := os.Rename(srcf, dstf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func mkdir(dir string) error {
|
||||
if buildX {
|
||||
printcmd("mkdir -p %s", dir)
|
||||
}
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
return os.MkdirAll(dir, 0755)
|
||||
}
|
||||
|
||||
func symlink(src, dst string) error {
|
||||
if buildX {
|
||||
printcmd("ln -s %s %s", src, dst)
|
||||
}
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
return os.Symlink(src, dst)
|
||||
}
|
||||
|
||||
func checkGoVersion() error {
|
||||
if err := exec.Command("which", "go").Run(); err != nil {
|
||||
return fmt.Errorf(`no Go tool on $PATH`)
|
||||
@ -188,6 +215,49 @@ func checkGoVersion() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetch(dst, url string) error {
|
||||
if buildV {
|
||||
fmt.Fprintf(os.Stderr, "fetching %s\n", url)
|
||||
}
|
||||
if buildX {
|
||||
printcmd("curl -o%s %s", dst, url)
|
||||
}
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(dst, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(crawshaw): The arm compiler toolchain compresses to 33 MB, less than a tenth of the NDK. Provide an alternative binary download.
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(f, resp.Body)
|
||||
err2 := resp.Body.Close()
|
||||
err3 := f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return err3
|
||||
}
|
||||
|
||||
func removeAll(path string) error {
|
||||
if buildX {
|
||||
printcmd("rm -r -f %q", path)
|
||||
}
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
func goEnv(name string) string {
|
||||
if val := os.Getenv(name); val != "" {
|
||||
return val
|
||||
|
Loading…
x
Reference in New Issue
Block a user