Merge "Add mainline dev certificate dir to config"
diff --git a/android/Android.bp b/android/Android.bp
index f58a472..e0ad58f 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -38,7 +38,9 @@
"bazel_paths.go",
"buildinfo_prop.go",
"config.go",
+ "test_config.go",
"config_bp2build.go",
+ "configured_jars.go",
"csuite_config.go",
"deapexer.go",
"defaults.go",
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index e606cb1..0721953 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -215,6 +215,10 @@
"system/libartpalette": Bp2BuildDefaultTrueRecursively,
"system/libbase": Bp2BuildDefaultTrueRecursively,
"system/libfmq": Bp2BuildDefaultTrue,
+ "system/libhidl/transport/base/1.0": Bp2BuildDefaultTrue,
+ "system/libhidl/transport/manager/1.0": Bp2BuildDefaultTrue,
+ "system/libhidl/transport/manager/1.1": Bp2BuildDefaultTrue,
+ "system/libhidl/transport/manager/1.2": Bp2BuildDefaultTrue,
"system/libhwbinder": Bp2BuildDefaultTrueRecursively,
"system/libprocinfo": Bp2BuildDefaultTrue,
"system/libziparchive": Bp2BuildDefaultTrueRecursively,
@@ -382,6 +386,10 @@
"car-ui-androidx-core-common-nodeps",
"car-ui-androidx-lifecycle-common-nodeps",
"car-ui-androidx-constraintlayout-solver-nodeps",
+
+ //system/libhidl
+ // needed by cc_hidl_library
+ "libhidlbase",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -566,5 +574,12 @@
"prebuilt_android-support-annotations-nodeps",
"prebuilt_android-arch-paging-common-nodeps",
"prebuilt_android-arch-room-common-nodeps",
+
+ // Disabled pending the investigation of b/242220039
+ "libhidlbase",
+ "android.hidl.base@1.0",
+ "android.hidl.manager@1.0",
+ "android.hidl.manager@1.1",
+ "android.hidl.manager@1.2",
}
)
diff --git a/android/arch.go b/android/arch.go
index 6acc8ad..b5bd2f0 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -393,54 +393,6 @@
}
}
-func registerBp2buildArchPathDepsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("bp2build-arch-pathdeps", bp2buildArchPathDepsMutator).Parallel()
-}
-
-// add dependencies for architecture specific properties tagged with `android:"path"`
-func bp2buildArchPathDepsMutator(ctx BottomUpMutatorContext) {
- var module Module
- module = ctx.Module()
-
- m := module.base()
- if !m.ArchSpecific() {
- return
- }
-
- // addPathDepsForProps does not descend into sub structs, so we need to descend into the
- // arch-specific properties ourselves
- var properties []interface{}
- for _, archProperties := range m.archProperties {
- for _, archProps := range archProperties {
- archPropValues := reflect.ValueOf(archProps).Elem()
- // there are three "arch" variations, descend into each
- for _, variant := range []string{"Arch", "Multilib", "Target"} {
- // The properties are an interface, get the value (a pointer) that it points to
- archProps := archPropValues.FieldByName(variant).Elem()
- if archProps.IsNil() {
- continue
- }
- // And then a pointer to a struct
- archProps = archProps.Elem()
- for i := 0; i < archProps.NumField(); i += 1 {
- f := archProps.Field(i)
- // If the value of the field is a struct (as opposed to a pointer to a struct) then step
- // into the BlueprintEmbed field.
- if f.Kind() == reflect.Struct {
- f = f.FieldByName("BlueprintEmbed")
- }
- if f.IsZero() {
- continue
- }
- props := f.Interface().(interface{})
- properties = append(properties, props)
- }
- }
- }
- }
- addPathDepsForProps(ctx, properties)
-}
-
// osMutator splits an arch-specific module into a variant for each OS that is enabled for the
// module. It uses the HostOrDevice value passed to InitAndroidArchModule and the
// device_supported and host_supported properties to determine which OsTypes are enabled for this
@@ -998,19 +950,13 @@
if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` {
panic(fmt.Errorf("unexpected tag format %q", field.Tag))
}
- // don't delete path tag as it is needed for bp2build
// these tags don't need to be present in the runtime generated struct type.
- values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend"})
- if len(values) > 0 && values[0] != "path" {
+ values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
+ if len(values) > 0 {
panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
- } else if len(values) == 1 {
- // FIXME(b/200678898): This assumes that the only tag type when there's
- // `android:"arch_variant"` is `android` itself and thus clobbers others
- field.Tag = reflect.StructTag(`android:"` + strings.Join(values, ",") + `"`)
- } else {
- field.Tag = ``
}
+ field.Tag = ``
return true, field
}
return false, field
diff --git a/android/arch_test.go b/android/arch_test.go
index dd0b115..ad2076d 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -66,9 +66,9 @@
}{},
out: &struct {
A *string
- B *string `android:"path"`
- C *string `android:"path"`
- D *string `android:"path"`
+ B *string
+ C *string
+ D *string
}{},
filtered: true,
},
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 5804a46..a5fa043 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -29,6 +29,7 @@
"android/soong/bazel/cquery"
"android/soong/shared"
+
"github.com/google/blueprint"
"android/soong/bazel"
@@ -54,7 +55,7 @@
}
func RegisterMixedBuildsMutator(ctx RegistrationContext) {
- ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel()
})
}
@@ -766,9 +767,9 @@
cqueryOutput, cqueryErr, err := context.issueBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
if err != nil {
- _ = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryOutput), 0666)
+ return err
}
- if err != nil {
+ if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryOutput), 0666); err != nil {
return err
}
diff --git a/android/config.go b/android/config.go
index c2fcbfc..d3f8ab4 100644
--- a/android/config.go
+++ b/android/config.go
@@ -20,7 +20,6 @@
import (
"bytes"
"encoding/json"
- "errors"
"fmt"
"io/ioutil"
"os"
@@ -345,123 +344,6 @@
}
}
-// TestConfig returns a Config object for testing.
-func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
- envCopy := make(map[string]string)
- for k, v := range env {
- envCopy[k] = v
- }
-
- // Copy the real PATH value to the test environment, it's needed by
- // NonHermeticHostSystemTool() used in x86_darwin_host.go
- envCopy["PATH"] = os.Getenv("PATH")
-
- config := &config{
- productVariables: productVariables{
- DeviceName: stringPtr("test_device"),
- DeviceProduct: stringPtr("test_product"),
- Platform_sdk_version: intPtr(30),
- Platform_sdk_codename: stringPtr("S"),
- Platform_base_sdk_extension_version: intPtr(1),
- Platform_version_active_codenames: []string{"S", "Tiramisu"},
- DeviceSystemSdkVersions: []string{"14", "15"},
- Platform_systemsdk_versions: []string{"29", "30"},
- AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
- AAPTPreferredConfig: stringPtr("xhdpi"),
- AAPTCharacteristics: stringPtr("nosdcard"),
- AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
- UncompressPrivAppDex: boolPtr(true),
- ShippingApiLevel: stringPtr("30"),
- },
-
- outDir: buildDir,
- soongOutDir: filepath.Join(buildDir, "soong"),
- captureBuild: true,
- env: envCopy,
-
- // Set testAllowNonExistentPaths so that test contexts don't need to specify every path
- // passed to PathForSource or PathForModuleSrc.
- TestAllowNonExistentPaths: true,
-
- BazelContext: noopBazelContext{},
- mixedBuildDisabledModules: make(map[string]struct{}),
- mixedBuildEnabledModules: make(map[string]struct{}),
- }
- config.deviceConfig = &deviceConfig{
- config: config,
- }
- config.TestProductVariables = &config.productVariables
-
- config.mockFileSystem(bp, fs)
-
- determineBuildOS(config)
-
- return Config{config}
-}
-
-func modifyTestConfigToSupportArchMutator(testConfig Config) {
- config := testConfig.config
-
- config.Targets = map[OsType][]Target{
- Android: []Target{
- {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
- {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
- },
- config.BuildOS: []Target{
- {config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
- {config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
- },
- }
-
- if runtime.GOOS == "darwin" {
- config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1]
- }
-
- config.BuildOSTarget = config.Targets[config.BuildOS][0]
- config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
- config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
- config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
- config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
- config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
- config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
- config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
-}
-
-func modifyTestConfigForMusl(config Config) {
- delete(config.Targets, config.BuildOS)
- config.productVariables.HostMusl = boolPtr(true)
- determineBuildOS(config.config)
- config.Targets[config.BuildOS] = []Target{
- {config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
- {config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
- }
-
- config.BuildOSTarget = config.Targets[config.BuildOS][0]
- config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
-}
-
-// TestArchConfig returns a Config object suitable for using for tests that
-// need to run the arch mutator.
-func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
- testConfig := TestConfig(buildDir, env, bp, fs)
- modifyTestConfigToSupportArchMutator(testConfig)
- return testConfig
-}
-
-// ConfigForAdditionalRun is a config object which is "reset" for another
-// bootstrap run. Only per-run data is reset. Data which needs to persist across
-// multiple runs in the same program execution is carried over (such as Bazel
-// context or environment deps).
-func ConfigForAdditionalRun(c Config) (Config, error) {
- newConfig, err := NewConfig(c.moduleListFile, c.runGoTests, c.outDir, c.soongOutDir, c.env)
- if err != nil {
- return Config{}, err
- }
- newConfig.BazelContext = c.BazelContext
- newConfig.envDeps = c.envDeps
- return newConfig, nil
-}
-
// NewConfig creates a new Config object. The srcDir argument specifies the path
// to the root source directory. It also loads the config file, if found.
func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) {
@@ -744,7 +626,8 @@
// these per device type.
//
// NOTE: Do not base conditional logic on this value. It may break product
-// inheritance.
+//
+// inheritance.
func (c *config) DeviceProduct() string {
return *c.productVariables.DeviceProduct
}
@@ -1746,316 +1629,6 @@
return c.productVariables.IgnorePrefer32OnDevice
}
-// 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)
- }
-}
-
-// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests.
-func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
- // Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to
- // a json list of strings and then unmarshalling into a ConfiguredJarList instance.
- b, err := json.Marshal(list)
- if err != nil {
- panic(err)
- }
-
- var jarList ConfiguredJarList
- err = json.Unmarshal(b, &jarList)
- if err != nil {
- panic(err)
- }
-
- return jarList
-}
-
-// EmptyConfiguredJarList returns an empty jar list.
-func EmptyConfiguredJarList() ConfiguredJarList {
- return ConfiguredJarList{}
-}
-
-var earlyBootJarsKey = NewOnceKey("earlyBootJars")
-
func (c *config) BootJars() []string {
return c.Once(earlyBootJarsKey, func() interface{} {
list := c.productVariables.BootJars.CopyOfJars()
diff --git a/android/configured_jars.go b/android/configured_jars.go
new file mode 100644
index 0000000..53fef05
--- /dev/null
+++ b/android/configured_jars.go
@@ -0,0 +1,314 @@
+// 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")
diff --git a/android/test_config.go b/android/test_config.go
new file mode 100644
index 0000000..f36e8ba
--- /dev/null
+++ b/android/test_config.go
@@ -0,0 +1,145 @@
+// 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"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "github.com/google/blueprint/proptools"
+)
+
+// TestConfig returns a Config object for testing.
+func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
+ envCopy := make(map[string]string)
+ for k, v := range env {
+ envCopy[k] = v
+ }
+
+ // Copy the real PATH value to the test environment, it's needed by
+ // NonHermeticHostSystemTool() used in x86_darwin_host.go
+ envCopy["PATH"] = os.Getenv("PATH")
+
+ config := &config{
+ productVariables: productVariables{
+ DeviceName: stringPtr("test_device"),
+ DeviceProduct: stringPtr("test_product"),
+ Platform_sdk_version: intPtr(30),
+ Platform_sdk_codename: stringPtr("S"),
+ Platform_base_sdk_extension_version: intPtr(1),
+ Platform_version_active_codenames: []string{"S", "Tiramisu"},
+ DeviceSystemSdkVersions: []string{"14", "15"},
+ Platform_systemsdk_versions: []string{"29", "30"},
+ AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
+ AAPTPreferredConfig: stringPtr("xhdpi"),
+ AAPTCharacteristics: stringPtr("nosdcard"),
+ AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
+ UncompressPrivAppDex: boolPtr(true),
+ ShippingApiLevel: stringPtr("30"),
+ },
+
+ outDir: buildDir,
+ soongOutDir: filepath.Join(buildDir, "soong"),
+ captureBuild: true,
+ env: envCopy,
+
+ // Set testAllowNonExistentPaths so that test contexts don't need to specify every path
+ // passed to PathForSource or PathForModuleSrc.
+ TestAllowNonExistentPaths: true,
+
+ BazelContext: noopBazelContext{},
+ mixedBuildDisabledModules: make(map[string]struct{}),
+ mixedBuildEnabledModules: make(map[string]struct{}),
+ }
+ config.deviceConfig = &deviceConfig{
+ config: config,
+ }
+ config.TestProductVariables = &config.productVariables
+
+ config.mockFileSystem(bp, fs)
+
+ determineBuildOS(config)
+
+ return Config{config}
+}
+
+func modifyTestConfigToSupportArchMutator(testConfig Config) {
+ config := testConfig.config
+
+ config.Targets = map[OsType][]Target{
+ Android: []Target{
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridgeDisabled, "", "", false},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridgeDisabled, "", "", false},
+ },
+ config.BuildOS: []Target{
+ {config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
+ {config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
+ },
+ }
+
+ if runtime.GOOS == "darwin" {
+ config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1]
+ }
+
+ config.BuildOSTarget = config.Targets[config.BuildOS][0]
+ config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
+ config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
+ config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
+ config.TestProductVariables.DeviceArch = proptools.StringPtr("arm64")
+ config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
+ config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
+ config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
+}
+
+func modifyTestConfigForMusl(config Config) {
+ delete(config.Targets, config.BuildOS)
+ config.productVariables.HostMusl = boolPtr(true)
+ determineBuildOS(config.config)
+ config.Targets[config.BuildOS] = []Target{
+ {config.BuildOS, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", false},
+ {config.BuildOS, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", false},
+ }
+
+ config.BuildOSTarget = config.Targets[config.BuildOS][0]
+ config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
+}
+
+// TestArchConfig returns a Config object suitable for using for tests that
+// need to run the arch mutator.
+func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
+ testConfig := TestConfig(buildDir, env, bp, fs)
+ modifyTestConfigToSupportArchMutator(testConfig)
+ return testConfig
+}
+
+// CreateTestConfiguredJarList is a function to create ConfiguredJarList for tests.
+func CreateTestConfiguredJarList(list []string) ConfiguredJarList {
+ // Create the ConfiguredJarList in as similar way as it is created at runtime by marshalling to
+ // a json list of strings and then unmarshalling into a ConfiguredJarList instance.
+ b, err := json.Marshal(list)
+ if err != nil {
+ panic(err)
+ }
+
+ var jarList ConfiguredJarList
+ err = json.Unmarshal(b, &jarList)
+ if err != nil {
+ panic(err)
+ }
+
+ return jarList
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 357ea44..4fcef9d 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -290,7 +290,11 @@
"-Wno-deprecated-non-prototype",
}
- llvmNextExtraCommonGlobalCflags = []string{}
+ llvmNextExtraCommonGlobalCflags = []string{
+ "-Wno-error=array-parameter", // http://b/241941550
+ "-Wno-error=deprecated-builtins", // http://b/241601211
+ "-Wno-error=deprecated", // in external/googletest/googletest
+ }
IllegalFlags = []string{
"-w",
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index 674edad..232e686 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -37,16 +37,22 @@
// http://b/216364337 - TODO: Follow-up after compiler update to
// disable or fix individual instances.
"-cert-err33-c",
+ // http://b/241125373
+ "-bugprone-unchecked-optional-access",
}
// Some clang-tidy checks are included in some tidy_checks_as_errors lists,
// but not all warnings are fixed/suppressed yet. These checks are not
// disabled in the TidyGlobalNoChecks list, so we can see them and fix/suppress them.
globalNoErrorCheckList = []string{
- // http://b/155034563
- "-bugprone-signed-char-misuse",
+ // http://b/241997913
+ "-bugprone-assignment-in-if-condition",
// http://b/155034972
"-bugprone-branch-clone",
+ // http://b/155034563
+ "-bugprone-signed-char-misuse",
+ // http://b/241819232
+ "-misc-const-correctness",
}
)
@@ -80,8 +86,10 @@
"misc-*",
"performance-*",
"portability-*",
+ "-bugprone-assignment-in-if-condition",
"-bugprone-easily-swappable-parameters",
"-bugprone-narrowing-conversions",
+ "-misc-const-correctness",
"-misc-no-recursion",
"-misc-non-private-member-variables-in-classes",
"-misc-unused-parameters",
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 3d18849..cb85634 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -268,6 +268,8 @@
func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
+ flags.SetOutput(ctx.Writer)
+
flags.Usage = func() {
fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
@@ -318,6 +320,8 @@
func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
+ flags.SetOutput(ctx.Writer)
+
flags.Usage = func() {
fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
@@ -401,6 +405,8 @@
func buildActionConfig(ctx build.Context, args ...string) build.Config {
flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
+ flags.SetOutput(ctx.Writer)
+
flags.Usage = func() {
fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
@@ -453,21 +459,32 @@
const numBuildActionFlags = 2
if len(args) < numBuildActionFlags {
flags.Usage()
- ctx.Fatalln("Improper build action arguments.")
+ ctx.Fatalln("Improper build action arguments: too few arguments")
}
- flags.Parse(args[0:numBuildActionFlags])
+ parseError := flags.Parse(args[0:numBuildActionFlags])
// The next block of code is to validate that exactly one build action is set and the dir flag
// is specified.
- buildActionCount := 0
+ buildActionFound := false
var buildAction build.BuildAction
- for _, flag := range buildActionFlags {
- if flag.set {
- buildActionCount++
- buildAction = flag.action
+ for _, f := range buildActionFlags {
+ if f.set {
+ if buildActionFound {
+ if parseError == nil {
+ //otherwise Parse() already called Usage()
+ flags.Usage()
+ }
+ ctx.Fatalf("Build action already specified, omit: --%s\n", f.name)
+ }
+ buildActionFound = true
+ buildAction = f.action
}
}
- if buildActionCount != 1 {
+ if !buildActionFound {
+ if parseError == nil {
+ //otherwise Parse() already called Usage()
+ flags.Usage()
+ }
ctx.Fatalln("Build action not defined.")
}
if *dir == "" {
@@ -509,8 +526,16 @@
// getCommand finds the appropriate command based on args[1] flag. args[0]
// is the soong_ui filename.
func getCommand(args []string) (*command, []string, error) {
+ listFlags := func() []string {
+ flags := make([]string, len(commands))
+ for i, c := range commands {
+ flags[i] = c.flag
+ }
+ return flags
+ }
+
if len(args) < 2 {
- return nil, nil, fmt.Errorf("Too few arguments: %q", args)
+ return nil, nil, fmt.Errorf("Too few arguments: %q\nUse one of these: %q", args, listFlags())
}
for _, c := range commands {
@@ -518,13 +543,7 @@
return &c, args[2:], nil
}
}
-
- // command not found
- flags := make([]string, len(commands))
- for i, c := range commands {
- flags[i] = c.flag
- }
- return nil, nil, fmt.Errorf("Command not found: %q\nDid you mean one of these: %q", args, flags)
+ return nil, nil, fmt.Errorf("Command not found: %q\nDid you mean one of these: %q", args[1], listFlags())
}
// For Bazel support, this moves files and directories from e.g. out/dist/$f to DIST_DIR/$f if necessary.
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 72cc894..0199d3a 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -299,7 +299,15 @@
ClangProperties: cc.RustBindgenClangProperties{},
}
- module := NewSourceProviderModule(hod, bindgen, false)
+ module := NewSourceProviderModule(hod, bindgen, false, true)
+
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ type stub_props struct {
+ Visibility []string
+ }
+ props := &stub_props{[]string{":__subpackages__"}}
+ ctx.PrependProperties(props)
+ })
return module, bindgen
}
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 9fe27c4c..88e80fe 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -238,7 +238,7 @@
Properties: ProtobufProperties{},
}
- module := NewSourceProviderModule(hod, protobuf, false)
+ module := NewSourceProviderModule(hod, protobuf, false, false)
return module, protobuf
}
diff --git a/rust/source_provider.go b/rust/source_provider.go
index 7719611..4f8d22b 100644
--- a/rust/source_provider.go
+++ b/rust/source_provider.go
@@ -65,9 +65,12 @@
}
}
-func NewSourceProviderModule(hod android.HostOrDeviceSupported, sourceProvider SourceProvider, enableLints bool) *Module {
+func NewSourceProviderModule(hod android.HostOrDeviceSupported, sourceProvider SourceProvider, enableLints bool, rlibOnly bool) *Module {
_, library := NewRustLibrary(hod)
library.BuildOnlyRust()
+ if rlibOnly {
+ library.BuildOnlyRlib()
+ }
library.sourceProvider = sourceProvider
module := newModule(hod, android.MultilibBoth)
diff --git a/ui/build/build.go b/ui/build/build.go
index 5b80b4d..f7a2d7b 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -201,7 +201,20 @@
buildLock := BecomeSingletonOrFail(ctx, config)
defer buildLock.Unlock()
+ logArgsOtherThan := func(specialTargets ...string) {
+ var ignored []string
+ for _, a := range config.Arguments() {
+ if !inList(a, specialTargets) {
+ ignored = append(ignored, a)
+ }
+ }
+ if len(ignored) > 0 {
+ ctx.Printf("ignoring arguments %q", ignored)
+ }
+ }
+
if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
+ logArgsOtherThan("clean", "clobber")
clean(ctx, config)
return
}
@@ -279,6 +292,7 @@
if inList("installclean", config.Arguments()) ||
inList("install-clean", config.Arguments()) {
+ logArgsOtherThan("installclean", "install-clean")
installClean(ctx, config)
ctx.Println("Deleted images and staging directories.")
return
@@ -286,6 +300,7 @@
if inList("dataclean", config.Arguments()) ||
inList("data-clean", config.Arguments()) {
+ logArgsOtherThan("dataclean", "data-clean")
dataClean(ctx, config)
ctx.Println("Deleted data files.")
return