123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- // Copyright 2022 Google Inc. 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 android
- import (
- "encoding/json"
- "errors"
- "fmt"
- "path/filepath"
- "strings"
- )
- // The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
- // Such lists are used in the build system for things like bootclasspath jars or system server jars.
- // The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
- // module name. The pairs come from Make product variables as a list of colon-separated strings.
- //
- // Examples:
- // - "com.android.art:core-oj"
- // - "platform:framework"
- // - "system_ext:foo"
- type ConfiguredJarList struct {
- // A list of apex components, which can be an apex name,
- // or special names like "platform" or "system_ext".
- apexes []string
- // A list of jar module name components.
- jars []string
- }
- // Len returns the length of the list of jars.
- func (l *ConfiguredJarList) Len() int {
- return len(l.jars)
- }
- // Jar returns the idx-th jar component of (apex, jar) pairs.
- func (l *ConfiguredJarList) Jar(idx int) string {
- return l.jars[idx]
- }
- // Apex returns the idx-th apex component of (apex, jar) pairs.
- func (l *ConfiguredJarList) Apex(idx int) string {
- return l.apexes[idx]
- }
- // ContainsJar returns true if the (apex, jar) pairs contains a pair with the
- // given jar module name.
- func (l *ConfiguredJarList) ContainsJar(jar string) bool {
- return InList(jar, l.jars)
- }
- // If the list contains the given (apex, jar) pair.
- func (l *ConfiguredJarList) containsApexJarPair(apex, jar string) bool {
- for i := 0; i < l.Len(); i++ {
- if apex == l.apexes[i] && jar == l.jars[i] {
- return true
- }
- }
- return false
- }
- // ApexOfJar returns the apex component of the first pair with the given jar name on the list, or
- // an empty string if not found.
- func (l *ConfiguredJarList) ApexOfJar(jar string) string {
- if idx := IndexList(jar, l.jars); idx != -1 {
- return l.Apex(IndexList(jar, l.jars))
- }
- return ""
- }
- // IndexOfJar returns the first pair with the given jar name on the list, or -1
- // if not found.
- func (l *ConfiguredJarList) IndexOfJar(jar string) int {
- return IndexList(jar, l.jars)
- }
- func copyAndAppend(list []string, item string) []string {
- // Create the result list to be 1 longer than the input.
- result := make([]string, len(list)+1)
- // Copy the whole input list into the result.
- count := copy(result, list)
- // Insert the extra item at the end.
- result[count] = item
- return result
- }
- // Append an (apex, jar) pair to the list.
- func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList {
- // Create a copy of the backing arrays before appending to avoid sharing backing
- // arrays that are mutated across instances.
- apexes := copyAndAppend(l.apexes, apex)
- jars := copyAndAppend(l.jars, jar)
- return ConfiguredJarList{apexes, jars}
- }
- // Append a list of (apex, jar) pairs to the list.
- func (l *ConfiguredJarList) AppendList(other *ConfiguredJarList) ConfiguredJarList {
- apexes := make([]string, 0, l.Len()+other.Len())
- jars := make([]string, 0, l.Len()+other.Len())
- apexes = append(apexes, l.apexes...)
- jars = append(jars, l.jars...)
- apexes = append(apexes, other.apexes...)
- jars = append(jars, other.jars...)
- return ConfiguredJarList{apexes, jars}
- }
- // RemoveList filters out a list of (apex, jar) pairs from the receiving list of pairs.
- func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
- apexes := make([]string, 0, l.Len())
- jars := make([]string, 0, l.Len())
- for i, jar := range l.jars {
- apex := l.apexes[i]
- if !list.containsApexJarPair(apex, jar) {
- apexes = append(apexes, apex)
- jars = append(jars, jar)
- }
- }
- return ConfiguredJarList{apexes, jars}
- }
- // Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list
- // and any remaining jars that are not on this list.
- func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) {
- var apexes []string
- var jars []string
- for i, jar := range l.jars {
- if InList(jar, jarsToKeep) {
- apexes = append(apexes, l.apexes[i])
- jars = append(jars, jar)
- }
- }
- return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars)
- }
- // CopyOfJars returns a copy of the list of strings containing jar module name
- // components.
- func (l *ConfiguredJarList) CopyOfJars() []string {
- return CopyOf(l.jars)
- }
- // CopyOfApexJarPairs returns a copy of the list of strings with colon-separated
- // (apex, jar) pairs.
- func (l *ConfiguredJarList) CopyOfApexJarPairs() []string {
- pairs := make([]string, 0, l.Len())
- for i, jar := range l.jars {
- apex := l.apexes[i]
- pairs = append(pairs, apex+":"+jar)
- }
- return pairs
- }
- // BuildPaths returns a list of build paths based on the given directory prefix.
- func (l *ConfiguredJarList) BuildPaths(ctx PathContext, dir OutputPath) WritablePaths {
- paths := make(WritablePaths, l.Len())
- for i, jar := range l.jars {
- paths[i] = dir.Join(ctx, ModuleStem(jar)+".jar")
- }
- return paths
- }
- // BuildPathsByModule returns a map from module name to build paths based on the given directory
- // prefix.
- func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
- paths := map[string]WritablePath{}
- for _, jar := range l.jars {
- paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
- }
- return paths
- }
- // UnmarshalJSON converts JSON configuration from raw bytes into a
- // ConfiguredJarList structure.
- func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error {
- // Try and unmarshal into a []string each item of which contains a pair
- // <apex>:<jar>.
- var list []string
- err := json.Unmarshal(b, &list)
- if err != nil {
- // Did not work so return
- return err
- }
- apexes, jars, err := splitListOfPairsIntoPairOfLists(list)
- if err != nil {
- return err
- }
- l.apexes = apexes
- l.jars = jars
- return nil
- }
- func (l *ConfiguredJarList) MarshalJSON() ([]byte, error) {
- if len(l.apexes) != len(l.jars) {
- return nil, errors.New(fmt.Sprintf("Inconsistent ConfiguredJarList: apexes: %q, jars: %q", l.apexes, l.jars))
- }
- list := make([]string, 0, len(l.apexes))
- for i := 0; i < len(l.apexes); i++ {
- list = append(list, l.apexes[i]+":"+l.jars[i])
- }
- return json.Marshal(list)
- }
- // ModuleStem hardcodes the stem of framework-minus-apex to return "framework".
- //
- // TODO(b/139391334): hard coded until we find a good way to query the stem of a
- // module before any other mutators are run.
- func ModuleStem(module string) string {
- if module == "framework-minus-apex" {
- return "framework"
- }
- return module
- }
- // DevicePaths computes the on-device paths for the list of (apex, jar) pairs,
- // based on the operating system.
- func (l *ConfiguredJarList) DevicePaths(cfg Config, ostype OsType) []string {
- paths := make([]string, l.Len())
- for i, jar := range l.jars {
- apex := l.apexes[i]
- name := ModuleStem(jar) + ".jar"
- var subdir string
- if apex == "platform" {
- subdir = "system/framework"
- } else if apex == "system_ext" {
- subdir = "system_ext/framework"
- } else {
- subdir = filepath.Join("apex", apex, "javalib")
- }
- if ostype.Class == Host {
- paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name)
- } else {
- paths[i] = filepath.Join("/", subdir, name)
- }
- }
- return paths
- }
- func (l *ConfiguredJarList) String() string {
- var pairs []string
- for i := 0; i < l.Len(); i++ {
- pairs = append(pairs, l.apexes[i]+":"+l.jars[i])
- }
- return strings.Join(pairs, ",")
- }
- func splitListOfPairsIntoPairOfLists(list []string) ([]string, []string, error) {
- // Now we need to populate this list by splitting each item in the slice of
- // pairs and appending them to the appropriate list of apexes or jars.
- apexes := make([]string, len(list))
- jars := make([]string, len(list))
- for i, apexjar := range list {
- apex, jar, err := splitConfiguredJarPair(apexjar)
- if err != nil {
- return nil, nil, err
- }
- apexes[i] = apex
- jars[i] = jar
- }
- return apexes, jars, nil
- }
- // Expected format for apexJarValue = <apex name>:<jar name>
- func splitConfiguredJarPair(str string) (string, string, error) {
- pair := strings.SplitN(str, ":", 2)
- if len(pair) == 2 {
- apex := pair[0]
- jar := pair[1]
- if apex == "" {
- return apex, jar, fmt.Errorf("invalid apex '%s' in <apex>:<jar> pair '%s', expected format: <apex>:<jar>", apex, str)
- }
- return apex, jar, nil
- } else {
- return "error-apex", "error-jar", fmt.Errorf("malformed (apex, jar) pair: '%s', expected format: <apex>:<jar>", str)
- }
- }
- // EmptyConfiguredJarList returns an empty jar list.
- func EmptyConfiguredJarList() ConfiguredJarList {
- return ConfiguredJarList{}
- }
- var earlyBootJarsKey = NewOnceKey("earlyBootJars")
|