blob: 4850ae78a9b742e97d78852e46b47bdb81e0edcd [file] [log] [blame]
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package link is a thin wrapper around aapt2 to link android resources.
package link
import (
"flag"
"io/ioutil"
"log"
"os/exec"
"sync"
"src/common/golang/flags"
"src/common/golang/walk"
"src/common/golang/ziputils"
"src/tools/ak/types"
)
var (
// Cmd defines the command to run link.
Cmd = types.Command{
Init: Init,
Run: Run,
Desc: desc,
Flags: []string{
"aapt2",
"sdk_jar",
"manifest",
"res_dirs",
"asset_dirs",
"pkg",
"src_jar",
"out",
},
}
aapt2 string
sdkJar string
manifest string
resDirs flags.StringList
assetDirs flags.StringList
pkg string
srcJar string
out string
initOnce sync.Once
)
// Init initializes link.
func Init() {
initOnce.Do(func() {
flag.StringVar(&aapt2, "aapt2", "", "Path to the aapt2 binary.")
flag.StringVar(&sdkJar, "sdk_jar", "", "Path to the android jar.")
flag.StringVar(&manifest, "manifest", "", "Path to the application AndroidManifest.xml.")
flag.Var(&resDirs, "res_dirs", "List of resource archives to link.")
flag.Var(&assetDirs, "asset_dirs", "Paths to asset directories..")
flag.StringVar(&pkg, "pkg", "", "Package for R.java.")
flag.StringVar(&srcJar, "src_jar", "", "R java source jar path.")
flag.StringVar(&out, "out", "", "Output path for linked archive.")
})
}
func desc() string {
return "Link compiled Android resources."
}
// Run is the entry point for link.
func Run() {
if aapt2 == "" ||
sdkJar == "" ||
manifest == "" ||
resDirs == nil ||
pkg == "" ||
srcJar == "" ||
out == "" {
log.Fatal("Flags -aapt2 -sdk_jar -manifest -res_dirs -pkg -src_jar and -out must be specified.")
}
// Note that relative order between directories needs to be respected by traversal function.
// I.e. all files in dir n most come before all files in directory n+1.
resArchives, err := walk.Files(resDirs)
if err != nil {
log.Fatalf("error getting resource archives: %v", err)
}
rjavaDir, err := ioutil.TempDir("", "rjava")
if err != nil {
log.Fatalf("error creating temp dir: %v", err)
}
args := []string{
"link", "--manifest", manifest, "--auto-add-overlay", "--no-static-lib-packages",
"--java", rjavaDir, "--custom-package", pkg, "-I", sdkJar}
for _, r := range resArchives {
args = append(args, "-R", r)
}
for _, a := range assetDirs {
args = append(args, "-A", a)
}
args = append(args, "-o", out)
if out, err := exec.Command(aapt2, args...).CombinedOutput(); err != nil {
log.Fatalf("error linking Android resources: %v\n %s", err, string(out))
}
if err := ziputils.Zip(rjavaDir, srcJar); err != nil {
log.Fatalf("error unable to create resources src jar: %v", err)
}
}