forked from xlab/android-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
152 lines (135 loc) · 4.52 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package main
import (
"log"
"os"
"path/filepath"
"github.com/jawher/mow.cli"
"github.com/xlab/closer"
"github.com/xlab/treeprint"
)
var app = cli.App("android-project", `Android project bootstrap tool for use instead of version that was removed from Android SDK (since Revision 25.3.0).
See https://developer.android.com/studio/releases/sdk-tools.html`)
func init() {
log.SetFlags(0)
}
func main() {
app.Command("update", "Updates an Android project (must already have an AndroidManifest.xml).", cmdUpdateFunc)
app.Command("platforms", "Lists Android platforms supported within SDK.", cmdPlatformsFunc)
if err := app.Run(os.Args); err != nil {
closer.Fatalln(err)
}
}
func cmdPlatformsFunc(c *cli.Cmd) {
sdkDir := c.String(cli.StringOpt{
Name: "sdk",
Desc: "Android SDK location, can also be set using ANDROID_HOME env variable.",
EnvVar: "ANDROID_HOME",
HideValue: true,
})
c.Spec = "[--sdk]"
c.Action = func() {
defer closer.Close()
if len(*sdkDir) == 0 {
closer.Fatalln("ANDROID_HOME environment variable not set (or --sdk flag not provided).")
}
_, platformsDir := learnPaths(*sdkDir)
log.Println("Available Android platforms:")
platforms := learnPlatforms(platformsDir)
for _, platform := range platforms {
log.Println("*", platform)
}
}
}
func cmdUpdateFunc(c *cli.Cmd) {
pathOpt := c.StringOpt("p path", "", "The project's directory.")
nameOpt := c.StringOpt("n name", "", "Project name.")
forceOpt := c.BoolOpt("f force", false, "Force generation, even if the target platform is not supported.")
targetOpt := c.StringOpt("t target", "android-23", "Target ID to set for the project.")
sdkDir := c.String(cli.StringOpt{
Name: "sdk",
Desc: "Android SDK location, can also be set using ANDROID_HOME env variable.",
EnvVar: "ANDROID_HOME",
HideValue: true,
})
c.Spec = "[--sdk] [--target] --name --path"
c.Action = func() {
defer closer.Close()
if len(*sdkDir) == 0 {
closer.Fatalln("ANDROID_HOME environment variable not set (or --sdk flag not provided).")
}
tree := treeprint.New()
closer.Bind(func() {
log.Println(tree)
})
ndkDir, platformsDir := learnPaths(*sdkDir)
env := tree.AddBranch("Environment").
AddMetaNode(*sdkDir, "Android SDK location").
AddMetaNode(ndkDir, "Android NDK location").
AddMetaNode(platformsDir, "Android Platforms location")
platforms := learnPlatforms(platformsDir)
env.AddMetaNode(platforms, "Android Platforms available")
ctx := &TemplateContext{
ProjectName: *nameOpt,
ProjectTarget: *targetOpt,
SDKDir: *sdkDir,
}
tree.AddBranch("Project").
AddMetaNode(ctx.ProjectName, "Project name").
AddMetaNode(ctx.ProjectTarget, "Project target").
AddMetaNode(*pathOpt, "Project location")
manifestFileName := filepath.Join(*pathOpt, "AndroidManifest.xml")
if _, err := os.Stat(manifestFileName); os.IsNotExist(err) {
closer.Fatalln("AndroidManifest.xml not found in project location")
}
var platformSupported bool
for _, platform := range platforms {
if *targetOpt == platform {
platformSupported = true
}
}
if !platformSupported && !(*forceOpt) {
closer.Fatalln("Platform", *targetOpt, "not supported within this SDK, build may fail. Use -f flag to override.")
}
files := tree.AddBranch("Files updated")
for _, tpl := range templates {
fileName := filepath.Join(*pathOpt, tpl.TargetName())
f, err := os.Create(fileName)
if err != nil {
closer.Fatalf("Failed to create file %s: %v", fileName, err)
}
if err := tpl.Render(ctx, f); err != nil {
closer.Fatalf("Failed to render template %s: %v", tpl.Name(), err)
}
f.Close()
files.AddNode(fileName)
}
}
}
func learnPlatforms(platformsDir string) []string {
var platforms []string
filepath.Walk(platformsDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == platformsDir {
return nil
}
platforms = append(platforms, filepath.Base(path))
return filepath.SkipDir
})
return platforms
}
func learnPaths(sdkDir string) (ndkDir, platformsDir string) {
if _, err := os.Stat(sdkDir); err != nil {
closer.Fatalln("Android SDK location is provided but not valid:", sdkDir)
}
ndkDir = filepath.Join(sdkDir, "ndk-bundle")
if _, err := os.Stat(sdkDir); err != nil {
log.Println("WARN: Android SDK location is provided but has no ndk-bundle:", ndkDir)
}
platformsDir = filepath.Join(sdkDir, "platforms")
if _, err := os.Stat(sdkDir); err != nil {
closer.Fatalln("Android SDK location is provided but has no platforms:", platformsDir)
}
return
}