xref: /aosp_15_r20/external/bazelbuild-rules_android/src/tools/ak/link/link.go (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1// Copyright 2018 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package link is a thin wrapper around aapt2 to link android resources.
16package link
17
18import (
19	"flag"
20	"io/ioutil"
21	"log"
22	"os/exec"
23	"sync"
24
25	"src/common/golang/flags"
26	"src/common/golang/walk"
27	"src/common/golang/ziputils"
28	"src/tools/ak/types"
29)
30
31var (
32	// Cmd defines the command to run link.
33	Cmd = types.Command{
34		Init: Init,
35		Run:  Run,
36		Desc: desc,
37		Flags: []string{
38			"aapt2",
39			"sdk_jar",
40			"manifest",
41			"res_dirs",
42			"asset_dirs",
43			"pkg",
44			"src_jar",
45			"out",
46		},
47	}
48
49	aapt2     string
50	sdkJar    string
51	manifest  string
52	resDirs   flags.StringList
53	assetDirs flags.StringList
54	pkg       string
55	srcJar    string
56	out       string
57
58	initOnce sync.Once
59)
60
61// Init initializes link.
62func Init() {
63	initOnce.Do(func() {
64		flag.StringVar(&aapt2, "aapt2", "", "Path to the aapt2 binary.")
65		flag.StringVar(&sdkJar, "sdk_jar", "", "Path to the android jar.")
66		flag.StringVar(&manifest, "manifest", "", "Path to the application AndroidManifest.xml.")
67		flag.Var(&resDirs, "res_dirs", "List of resource archives to link.")
68		flag.Var(&assetDirs, "asset_dirs", "Paths to asset directories..")
69		flag.StringVar(&pkg, "pkg", "", "Package for R.java.")
70		flag.StringVar(&srcJar, "src_jar", "", "R java source jar path.")
71		flag.StringVar(&out, "out", "", "Output path for linked archive.")
72	})
73}
74
75func desc() string {
76	return "Link compiled Android resources."
77}
78
79// Run is the entry point for link.
80func Run() {
81	if aapt2 == "" ||
82		sdkJar == "" ||
83		manifest == "" ||
84		resDirs == nil ||
85		pkg == "" ||
86		srcJar == "" ||
87		out == "" {
88		log.Fatal("Flags -aapt2 -sdk_jar -manifest -res_dirs -pkg -src_jar and -out must be specified.")
89	}
90
91	// Note that relative order between directories needs to be respected by traversal function.
92	// I.e. all files in dir n most come before all files in directory n+1.
93	resArchives, err := walk.Files(resDirs)
94	if err != nil {
95		log.Fatalf("error getting resource archives: %v", err)
96	}
97
98	rjavaDir, err := ioutil.TempDir("", "rjava")
99	if err != nil {
100		log.Fatalf("error creating temp dir: %v", err)
101	}
102
103	args := []string{
104		"link", "--manifest", manifest, "--auto-add-overlay", "--no-static-lib-packages",
105		"--java", rjavaDir, "--custom-package", pkg, "-I", sdkJar}
106
107	for _, r := range resArchives {
108		args = append(args, "-R", r)
109	}
110
111	for _, a := range assetDirs {
112		args = append(args, "-A", a)
113	}
114
115	args = append(args, "-o", out)
116
117	if out, err := exec.Command(aapt2, args...).CombinedOutput(); err != nil {
118		log.Fatalf("error linking Android resources: %v\n %s", err, string(out))
119	}
120	if err := ziputils.Zip(rjavaDir, srcJar); err != nil {
121		log.Fatalf("error unable to create resources src jar: %v", err)
122	}
123}
124