cmd/gomobile: add -target flag
Also add a very simple test for gomobile build, some documentation cleanup, and the -o flag for bind. Change-Id: I719b92010ba2a5813049827c99502828788611ef Reviewed-on: https://go-review.googlesource.com/11253 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
parent
6490f64aef
commit
10a37afdaf
@ -35,43 +35,39 @@ import (
|
||||
var cmdBind = &command{
|
||||
run: runBind,
|
||||
Name: "bind",
|
||||
Usage: "[package]",
|
||||
Usage: "[-target android|ios] [-o output] [build flags] [package]",
|
||||
Short: "build a shared library for android APK and iOS app",
|
||||
Long: `
|
||||
Bind generates language bindings like gobind (golang.org/x/mobile/cmd/gobind)
|
||||
for a package and builds a shared library for each platform from the go binding
|
||||
code.
|
||||
Bind generates language bindings for the package named by the import
|
||||
path, and compiles a library for the named target system.
|
||||
|
||||
For Android, the bind command produces an AAR (Android ARchive) file that
|
||||
archives the precompiled Java API stub classes, the compiled shared libraries,
|
||||
and all asset files in the /assets subdirectory under the package directory.
|
||||
The output AAR file name is '<package_name>.aar'.
|
||||
The -target flag takes a target system name, either android (the
|
||||
default) or ios.
|
||||
|
||||
The AAR file is commonly used for binary distribution of an Android library
|
||||
project and most Android IDEs support AAR import. For example, in Android
|
||||
Studio (1.2+), an AAR file can be imported using the module import wizard
|
||||
(File > New > New Module > Import .JAR or .AAR package), and setting it as
|
||||
a new dependency (File > Project Structure > Dependencies).
|
||||
For -target android, the bind command produces an AAR (Android ARchive)
|
||||
file that archives the precompiled Java API stub classes, the compiled
|
||||
shared libraries, and all asset files in the /assets subdirectory under
|
||||
the package directory. The output is named '<package_name>.aar' by
|
||||
default. This AAR file is commonly used for binary distribution of an
|
||||
Android library project and most Android IDEs support AAR import. For
|
||||
example, in Android Studio (1.2+), an AAR file can be imported using
|
||||
the module import wizard (File > New > New Module > Import .JAR or
|
||||
.AAR package), and setting it as a new dependency
|
||||
(File > Project Structure > Dependencies). This requires 'javac'
|
||||
(version 1.7+) and Android SDK (API level 9 or newer) to build the
|
||||
library for Android. The environment variable ANDROID_HOME must be set
|
||||
to the path to Android SDK.
|
||||
|
||||
This command requires 'javac' (version 1.7+) and Android SDK (API level 9
|
||||
or newer) to build the library for Android. The environment variable
|
||||
ANDROID_HOME must be set to the path to Android SDK.
|
||||
For -target ios, gomobile must be run on an OS X machine with Xcode
|
||||
installed. Support is not complete.
|
||||
|
||||
The -v flag provides verbose output, including the list of packages built.
|
||||
|
||||
These build flags are shared by the build command.
|
||||
For documentation, see 'go help build':
|
||||
-a
|
||||
-i
|
||||
-n
|
||||
-x
|
||||
-tags 'tag list'
|
||||
The build flags -a, -i, -n, -x, and -tags are shared with the build command.
|
||||
For documentation, see 'go help build'.
|
||||
`,
|
||||
}
|
||||
|
||||
// TODO: -mobile
|
||||
// TODO: reuse the -o option to specify the output file name?
|
||||
|
||||
func runBind(cmd *command) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
@ -93,6 +89,15 @@ func runBind(cmd *command) error {
|
||||
return err
|
||||
}
|
||||
|
||||
switch *buildTarget {
|
||||
case "android":
|
||||
// implementation is below
|
||||
case "ios":
|
||||
return fmt.Errorf(`-target=ios not yet supported`)
|
||||
default:
|
||||
return fmt.Errorf(`unknown -target, %q.`, *buildTarget)
|
||||
}
|
||||
|
||||
if sdkDir := os.Getenv("ANDROID_HOME"); sdkDir == "" {
|
||||
return fmt.Errorf("this command requires ANDROID_HOME environment variable (path to the Android SDK)")
|
||||
}
|
||||
@ -318,8 +323,14 @@ func main() {
|
||||
// javac and jar commands are needed to build classes.jar.
|
||||
func buildAAR(androidDir string, pkg *build.Package) (err error) {
|
||||
var out io.Writer = ioutil.Discard
|
||||
if *buildO == "" {
|
||||
*buildO = pkg.Name + ".aar"
|
||||
}
|
||||
if !strings.HasSuffix(*buildO, ".apk") {
|
||||
return fmt.Errorf("output file name %q does not end in '.aar'", *buildO)
|
||||
}
|
||||
if !buildN {
|
||||
f, err := os.Create(pkg.Name + ".aar")
|
||||
f, err := os.Create(*buildO)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -30,37 +30,36 @@ var tmpdir string
|
||||
var cmdBuild = &command{
|
||||
run: runBuild,
|
||||
Name: "build",
|
||||
Usage: "[-o output] [-i] [build flags] [package]",
|
||||
Usage: "[-target android|ios] [-o output] [build flags] [package]",
|
||||
Short: "compile android APK and iOS app",
|
||||
Long: `
|
||||
Build compiles and encodes the app named by the import path.
|
||||
|
||||
The named package must define a main function.
|
||||
|
||||
If an AndroidManifest.xml is defined in the package directory, it is
|
||||
added to the APK file. Otherwise, a default manifest is generated.
|
||||
The -target flag takes a target system name, either android (the
|
||||
default) or ios.
|
||||
|
||||
For -target android, if an AndroidManifest.xml is defined in the
|
||||
package directory, it is added to the APK output. Otherwise, a default
|
||||
manifest is generated.
|
||||
|
||||
For -target ios, gomobile must be run on an OS X machine with Xcode
|
||||
installed. Support is not complete.
|
||||
|
||||
If the package directory contains an assets subdirectory, its contents
|
||||
are copied into the APK file.
|
||||
are copied into the output.
|
||||
|
||||
The -o flag specifies the output file name. If not specified, the
|
||||
output file name depends on the package built. The output file must end
|
||||
in '.apk'.
|
||||
output file name depends on the package built.
|
||||
|
||||
The -v flag provides verbose output, including the list of packages built.
|
||||
|
||||
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'
|
||||
The build flags -a, -i, -n, -x, and -tags are shared with the build command.
|
||||
For documentation, see 'go help build'.
|
||||
`,
|
||||
}
|
||||
|
||||
// TODO: -mobile
|
||||
|
||||
func runBuild(cmd *command) (err error) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
@ -81,6 +80,15 @@ func runBuild(cmd *command) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
switch *buildTarget {
|
||||
case "android":
|
||||
// implementation is below
|
||||
case "ios":
|
||||
return fmt.Errorf(`-target=ios not yet supported`)
|
||||
default:
|
||||
return fmt.Errorf(`unknown -target, %q.`, *buildTarget)
|
||||
}
|
||||
|
||||
if pkg.Name != "main" {
|
||||
// Not an app, don't build a final package.
|
||||
return goAndroidBuild(pkg.ImportPath, "")
|
||||
@ -108,7 +116,7 @@ func runBuild(cmd *command) (err error) {
|
||||
}
|
||||
defer removeAll(tmpdir)
|
||||
if buildX {
|
||||
fmt.Fprintln(os.Stderr, "WORK="+tmpdir)
|
||||
fmt.Fprintln(xout, "WORK="+tmpdir)
|
||||
}
|
||||
|
||||
libName := path.Base(pkg.ImportPath)
|
||||
@ -306,15 +314,19 @@ func printcmd(format string, args ...interface{}) {
|
||||
|
||||
// "Build flags", used by multiple commands.
|
||||
var (
|
||||
buildA bool // -a
|
||||
buildI bool // -i
|
||||
buildN bool // -n
|
||||
buildV bool // -v
|
||||
buildX bool // -x
|
||||
buildO *string // -o
|
||||
buildA bool // -a
|
||||
buildI bool // -i
|
||||
buildN bool // -n
|
||||
buildV bool // -v
|
||||
buildX bool // -x
|
||||
buildO *string // -o
|
||||
buildTarget *string // -target
|
||||
)
|
||||
|
||||
func addBuildFlags(cmd *command) {
|
||||
buildO = cmd.flag.String("o", "", "")
|
||||
buildTarget = cmd.flag.String("target", "android", "")
|
||||
|
||||
cmd.flag.BoolVar(&buildA, "a", false, "")
|
||||
cmd.flag.BoolVar(&buildI, "i", false, "")
|
||||
cmd.flag.Var((*stringsFlag)(&ctx.BuildTags), "tags", "")
|
||||
@ -438,7 +450,6 @@ func pkgImportsAudio(pkg *build.Package) bool {
|
||||
}
|
||||
|
||||
func init() {
|
||||
buildO = cmdBuild.flag.String("o", "", "output file")
|
||||
addBuildFlags(cmdBuild)
|
||||
addBuildFlagsNVX(cmdBuild)
|
||||
|
||||
|
53
cmd/gomobile/build_test.go
Normal file
53
cmd/gomobile/build_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func TestBuild(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
defer func() {
|
||||
xout = os.Stderr
|
||||
buildN = false
|
||||
buildX = false
|
||||
}()
|
||||
xout = buf
|
||||
buildN = true
|
||||
buildX = true
|
||||
gopath = filepath.SplitList(os.Getenv("GOPATH"))[0]
|
||||
if goos == "windows" {
|
||||
os.Setenv("HOMEDRIVE", "C:")
|
||||
}
|
||||
cmdBuild.flag.Parse([]string{"golang.org/x/mobile/example/basic"})
|
||||
if *buildTarget != "android" {
|
||||
t.Fatalf("-target=%q, want android", *buildTarget)
|
||||
}
|
||||
err := runBuild(cmdBuild)
|
||||
if err != nil {
|
||||
t.Log(buf.String())
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, err := diffOutput(buf.String(), buildTmpl)
|
||||
if err != nil {
|
||||
t.Fatalf("computing diff failed: %v", err)
|
||||
}
|
||||
if diff != "" {
|
||||
t.Errorf("unexpected output:\n%s", diff)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var buildTmpl = template.Must(template.New("output").Parse(`WORK=$WORK
|
||||
GOMOBILE={{.GOPATH}}/pkg/gomobile
|
||||
GOOS=android GOARCH=arm GOARM=7 CGO_ENABLED=1 CC=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-gcc{{.EXE}} CXX=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-g++{{.EXE}} GOGCCFLAGS="-fPIC -marm -pthread -fmessage-length=0" GOROOT=$GOROOT GOPATH=$HOME GOMOBILEPATH=$GOMOBILE/android-{{.NDK}}/arm/bin go build -tags="" -toolexec=$GOMOBILE/android-{{.NDK}}/arm/bin/toolexec -x -buildmode=c-shared -o $WORK/libbasic.so golang.org/x/mobile/example/basic
|
||||
rm -r -f "$WORK"
|
||||
`))
|
@ -76,7 +76,7 @@ func init() {
|
||||
func runInit(cmd *command) error {
|
||||
version, err := goVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("%v: %s", err, version)
|
||||
}
|
||||
|
||||
gopaths := filepath.SplitList(goEnv("GOPATH"))
|
||||
@ -426,7 +426,7 @@ func goVersion() ([]byte, error) {
|
||||
if !bytes.Contains(buildHelp, []byte("-toolexec")) {
|
||||
return nil, fmt.Errorf("installed Go tool does not support -toolexec")
|
||||
}
|
||||
return exec.Command(gobin, "version").Output()
|
||||
return exec.Command(gobin, "version").CombinedOutput()
|
||||
}
|
||||
|
||||
// checkVersionMatch makes sure that the go command in the path matches
|
||||
|
@ -13,20 +13,23 @@ import (
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var gopath string
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
gopath := os.Getenv("GOPATH")
|
||||
gopathorig := os.Getenv("GOPATH")
|
||||
defer func() {
|
||||
xout = os.Stderr
|
||||
buildN = false
|
||||
buildX = false
|
||||
os.Setenv("GOPATH", gopath)
|
||||
os.Setenv("GOPATH", gopathorig)
|
||||
}()
|
||||
xout = buf
|
||||
buildN = true
|
||||
buildX = true
|
||||
// Test that first GOPATH element is chosen correctly.
|
||||
paths := []string{"GOPATH1", "/path2", "/path3"}
|
||||
gopath = "/GOPATH1"
|
||||
paths := []string{"/GOPATH1", "/path2", "/path3"}
|
||||
os.Setenv("GOPATH", strings.Join(paths, string(os.PathListSeparator)))
|
||||
os.Setenv("GOROOT_BOOTSTRAP", "go1.4")
|
||||
if goos == "windows" {
|
||||
@ -55,6 +58,7 @@ func diffOutput(got string, wantTmpl *template.Template) (string, error) {
|
||||
NDK: ndkVersion,
|
||||
GOOS: goos,
|
||||
GOARCH: goarch,
|
||||
GOPATH: gopath,
|
||||
NDKARCH: ndkarch,
|
||||
BuildScript: unixBuildScript,
|
||||
}
|
||||
@ -76,6 +80,7 @@ type outputData struct {
|
||||
NDK string
|
||||
GOOS string
|
||||
GOARCH string
|
||||
GOPATH string
|
||||
NDKARCH string
|
||||
EXE string // .extension for executables. (ex. ".exe" for windows)
|
||||
BuildScript string
|
||||
@ -86,9 +91,9 @@ const (
|
||||
windowsBuildScript = `TEMP=$WORK TMP=$WORK HOMEDRIVE=C: HOMEPATH=$HOMEPATH GOROOT_BOOTSTRAP=go1.4 $WORK/go/src/make.bat --no-clean`
|
||||
)
|
||||
|
||||
var initTmpl = template.Must(template.New("output").Parse(`GOMOBILE=GOPATH1/pkg/gomobile
|
||||
var initTmpl = template.Must(template.New("output").Parse(`GOMOBILE={{.GOPATH}}/pkg/gomobile
|
||||
mkdir -p $GOMOBILE/android-{{.NDK}}
|
||||
WORK=GOPATH1/pkg/gomobile/work
|
||||
WORK=/GOPATH1/pkg/gomobile/work
|
||||
mkdir -p $WORK/go/pkg
|
||||
cp -a $GOROOT/lib $WORK/go/lib
|
||||
cp -a $GOROOT/src $WORK/go/src
|
||||
|
@ -13,15 +13,16 @@ import (
|
||||
var cmdInstall = &command{
|
||||
run: runInstall,
|
||||
Name: "install",
|
||||
Usage: "[package]",
|
||||
Usage: "[-target android] [build flags] [package]",
|
||||
Short: "compile android APK and iOS app and install on device",
|
||||
Long: `
|
||||
Install compiles and installs the app named by the import path on the
|
||||
attached mobile device.
|
||||
|
||||
This command requires the 'adb' tool on the PATH.
|
||||
Only -target android is supported. The 'adb' tool must be on the PATH.
|
||||
|
||||
See the build command help for common flags and common behavior.
|
||||
The build flags -a, -i, -n, -x, and -tags are shared with the build command.
|
||||
For documentation, see 'go help build'.
|
||||
`,
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user