diff options
74 files changed, 4550 insertions, 937 deletions
@@ -4,6 +4,7 @@ per-file * = dwillemsen@google.com per-file * = eakammer@google.com per-file * = jungjw@google.com per-file * = patricearruda@google.com +per-file * = hansson@google.com per-file * = paulduffin@google.com per-file ndk_*.go, *gen_stub_libs.py = danalbert@google.com diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 928ca03c8..7c4d3e0b9 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -1,2 +1,5 @@ [Builtin Hooks] gofmt = true + +[Hook Scripts] +do_not_use_DO_NOT_MERGE = ${REPO_ROOT}/build/soong/scripts/check_do_not_merge.sh ${PREUPLOAD_COMMIT} diff --git a/android/Android.bp b/android/Android.bp index bd72b7b14..593399ebc 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -24,6 +24,8 @@ bootstrap_go_package { "hooks.go", "image.go", "license.go", + "license_kind.go", + "licenses.go", "makevars.go", "module.go", "mutator.go", @@ -63,7 +65,6 @@ bootstrap_go_package { "csuite_config_test.go", "depset_test.go", "expand_test.go", - "license_test.go", "module_test.go", "mutator_test.go", "namespace_test.go", diff --git a/android/androidmk.go b/android/androidmk.go index 54a0c6465..5bcf1fe9e 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "os" "path/filepath" + "reflect" "sort" "strings" @@ -46,7 +47,7 @@ type AndroidMkDataProvider interface { type AndroidMkData struct { Class string SubName string - DistFile OptionalPath + DistFiles TaggedDistFiles OutputFile OptionalPath Disabled bool Include string @@ -72,7 +73,7 @@ type AndroidMkEntriesProvider interface { type AndroidMkEntries struct { Class string SubName string - DistFile OptionalPath + DistFiles TaggedDistFiles OutputFile OptionalPath Disabled bool Include string @@ -176,61 +177,150 @@ func (a *AndroidMkEntries) AddStrings(name string, value ...string) { a.EntryMap[name] = append(a.EntryMap[name], value...) } -func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) { - a.EntryMap = make(map[string][]string) +// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling +// for partial MTS test suites. +func (a *AndroidMkEntries) AddCompatibilityTestSuites(suites ...string) { + // MTS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}. + // To reduce repetition, if we find a partial MTS test suite without an full MTS test suite, + // we add the full test suite to our list. + if PrefixInList(suites, "mts-") && !InList("mts", suites) { + suites = append(suites, "mts") + } + a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...) +} + +// Compute the list of Make strings to declare phone goals and dist-for-goals +// calls from the module's dist and dists properties. +func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string { amod := mod.(Module).base() name := amod.BaseModuleName() - if a.Include == "" { - a.Include = "$(BUILD_PREBUILT)" + var ret []string + var availableTaggedDists TaggedDistFiles + + if a.DistFiles != nil { + availableTaggedDists = a.DistFiles + } else if a.OutputFile.Valid() { + availableTaggedDists = MakeDefaultDistFiles(a.OutputFile.Path()) + } else { + // Nothing dist-able for this module. + return nil } - a.Required = append(a.Required, amod.commonProperties.Required...) - a.Host_required = append(a.Host_required, amod.commonProperties.Host_required...) - a.Target_required = append(a.Target_required, amod.commonProperties.Target_required...) - // Fill in the header part. - if len(amod.commonProperties.Dist.Targets) > 0 { - distFile := a.DistFile - if !distFile.Valid() { - distFile = a.OutputFile + // Iterate over this module's dist structs, merged from the dist and dists properties. + for _, dist := range amod.Dists() { + // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore + goals := strings.Join(dist.Targets, " ") + + // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map" + var tag string + if dist.Tag == nil { + // If the dist struct does not specify a tag, use the default output files tag. + tag = "" + } else { + tag = *dist.Tag + } + + // Get the paths of the output files to be dist'd, represented by the tag. + // Can be an empty list. + tagPaths := availableTaggedDists[tag] + if len(tagPaths) == 0 { + // Nothing to dist for this tag, continue to the next dist. + continue + } + + if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) { + errorMessage := "Cannot apply dest/suffix for more than one dist " + + "file for %s goals in module %s. The list of dist files, " + + "which should have a single element, is:\n%s" + panic(fmt.Errorf(errorMessage, goals, name, tagPaths)) } - if distFile.Valid() { - dest := filepath.Base(distFile.String()) - if amod.commonProperties.Dist.Dest != nil { + ret = append(ret, fmt.Sprintf(".PHONY: %s\n", goals)) + + // Create dist-for-goals calls for each path in the dist'd files. + for _, path := range tagPaths { + // It's possible that the Path is nil from errant modules. Be defensive here. + if path == nil { + tagName := "default" // for error message readability + if dist.Tag != nil { + tagName = *dist.Tag + } + panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name)) + } + + dest := filepath.Base(path.String()) + + if dist.Dest != nil { var err error - if dest, err = validateSafePath(*amod.commonProperties.Dist.Dest); err != nil { + if dest, err = validateSafePath(*dist.Dest); err != nil { // This was checked in ModuleBase.GenerateBuildActions panic(err) } } - if amod.commonProperties.Dist.Suffix != nil { + if dist.Suffix != nil { ext := filepath.Ext(dest) - suffix := *amod.commonProperties.Dist.Suffix + suffix := *dist.Suffix dest = strings.TrimSuffix(dest, ext) + suffix + ext } - if amod.commonProperties.Dist.Dir != nil { + if dist.Dir != nil { var err error - if dest, err = validateSafePath(*amod.commonProperties.Dist.Dir, dest); err != nil { + if dest, err = validateSafePath(*dist.Dir, dest); err != nil { // This was checked in ModuleBase.GenerateBuildActions panic(err) } } - goals := strings.Join(amod.commonProperties.Dist.Targets, " ") - fmt.Fprintln(&a.header, ".PHONY:", goals) - fmt.Fprintf(&a.header, "$(call dist-for-goals,%s,%s:%s)\n", - goals, distFile.String(), dest) + ret = append( + ret, + fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", goals, path.String(), dest)) } } + return ret +} + +// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..) +// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make. +func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) { + fmt.Fprintln(w, "LOCAL_LICENSE_KINDS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_KINDS"], " ")) + fmt.Fprintln(w, "LOCAL_LICENSE_CONDITIONS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_CONDITIONS"], " ")) + fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(a.EntryMap["LOCAL_NOTICE_FILE"], " ")) + if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok { + fmt.Fprintln(w, "LOCAL_LICENSE_PACKAGE_NAME :=", strings.Join(pn, " ")) + } +} + +func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) { + a.EntryMap = make(map[string][]string) + amod := mod.(Module).base() + name := amod.BaseModuleName() + + if a.Include == "" { + a.Include = "$(BUILD_PREBUILT)" + } + a.Required = append(a.Required, amod.commonProperties.Required...) + a.Host_required = append(a.Host_required, amod.commonProperties.Host_required...) + a.Target_required = append(a.Target_required, amod.commonProperties.Target_required...) + + for _, distString := range a.GetDistForGoals(mod) { + fmt.Fprintf(&a.header, distString) + } + fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)") // Collect make variable assignment entries. a.SetString("LOCAL_PATH", filepath.Dir(bpPath)) a.SetString("LOCAL_MODULE", name+a.SubName) + a.AddStrings("LOCAL_LICENSE_KINDS", amod.commonProperties.Effective_license_kinds...) + a.AddStrings("LOCAL_LICENSE_CONDITIONS", amod.commonProperties.Effective_license_conditions...) + a.AddStrings("LOCAL_NOTICE_FILE", amod.commonProperties.Effective_license_text...) + // TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ? + if amod.commonProperties.Effective_package_name != nil { + a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *amod.commonProperties.Effective_package_name) + } a.SetString("LOCAL_MODULE_CLASS", a.Class) a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String()) a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...) @@ -441,6 +531,7 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M } }() + // Additional cases here require review for correct license propagation to make. switch x := mod.(type) { case AndroidMkDataProvider: return translateAndroidModule(ctx, w, mod, x) @@ -449,6 +540,7 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M case AndroidMkEntriesProvider: return translateAndroidMkEntriesModule(ctx, w, mod, x) default: + // Not exported to make so no make variables to set. return nil } } @@ -460,6 +552,10 @@ func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Mo fmt.Fprintln(w, ".PHONY:", name) fmt.Fprintln(w, name+":", goBinary.InstallPath()) fmt.Fprintln(w, "") + // Assuming no rules in make include go binaries in distributables. + // If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files. + // In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for + // `goBinary.InstallPath()` pointing to the `name`.meta_lic file. return nil } @@ -469,7 +565,7 @@ func (data *AndroidMkData) fillInData(config Config, bpPath string, mod blueprin entries := AndroidMkEntries{ Class: data.Class, SubName: data.SubName, - DistFile: data.DistFile, + DistFiles: data.DistFiles, OutputFile: data.OutputFile, Disabled: data.Disabled, Include: data.Include, @@ -525,6 +621,25 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Mod blueprintDir := filepath.Dir(ctx.BlueprintFile(mod)) if data.Custom != nil { + // List of module types allowed to use .Custom(...) + // Additions to the list require careful review for proper license handling. + switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type + case "*aidl.aidlApi": // writes non-custom before adding .phony + case "*aidl.aidlMapping": // writes non-custom before adding .phony + case "*android.customModule": // appears in tests only + case "*apex.apexBundle": // license properties written + case "*bpf.bpf": // license properties written (both for module and objs) + case "*genrule.Module": // writes non-custom before adding .phony + case "*java.SystemModules": // doesn't go through base_rules + case "*java.systemModulesImport": // doesn't go through base_rules + case "*phony.phony": // license properties written + case "*selinux.selinuxContextsModule": // license properties written + case "*sysprop.syspropLibrary": // license properties written + default: + if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") { + return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod)) + } + } data.Custom(w, name, prefix, blueprintDir, data) } else { WriteAndroidMkData(w, data) @@ -557,6 +672,7 @@ func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blue return nil } + // Any new or special cases here need review to verify correct propagation of license information. for _, entries := range provider.AndroidMkEntries() { entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod) entries.write(w) diff --git a/android/androidmk_test.go b/android/androidmk_test.go index 71f802043..a558f453f 100644 --- a/android/androidmk_test.go +++ b/android/androidmk_test.go @@ -15,6 +15,7 @@ package android import ( + "fmt" "io" "reflect" "testing" @@ -22,10 +23,12 @@ import ( type customModule struct { ModuleBase - data AndroidMkData + data AndroidMkData + distFiles TaggedDistFiles } func (m *customModule) GenerateAndroidBuildActions(ctx ModuleContext) { + m.distFiles = m.GenerateTaggedDistFiles(ctx) } func (m *customModule) AndroidMk() AndroidMkData { @@ -36,6 +39,28 @@ func (m *customModule) AndroidMk() AndroidMkData { } } +func (m *customModule) OutputFiles(tag string) (Paths, error) { + switch tag { + case "": + return PathsForTesting("one.out"), nil + case ".multiple": + return PathsForTesting("two.out", "three/four.out"), nil + case ".another-tag": + return PathsForTesting("another.out"), nil + default: + return nil, fmt.Errorf("unsupported module reference tag %q", tag) + } +} + +func (m *customModule) AndroidMkEntries() []AndroidMkEntries { + return []AndroidMkEntries{ + { + Class: "CUSTOM_MODULE", + DistFiles: m.distFiles, + }, + } +} + func customModuleFactory() Module { module := &customModule{} InitAndroidModule(module) @@ -76,3 +101,191 @@ func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testin assertEqual([]string{"baz"}, m.data.Host_required) assertEqual([]string{"qux"}, m.data.Target_required) } + +func TestGetDistForGoals(t *testing.T) { + testCases := []struct { + bp string + expectedAndroidMkLines []string + }{ + { + bp: ` + custom { + name: "foo", + dist: { + targets: ["my_goal"] + } + } + `, + expectedAndroidMkLines: []string{ + ".PHONY: my_goal\n", + "$(call dist-for-goals,my_goal,one.out:one.out)\n", + }, + }, + { + bp: ` + custom { + name: "foo", + dist: { + targets: ["my_goal"], + tag: ".another-tag", + } + } + `, + expectedAndroidMkLines: []string{ + ".PHONY: my_goal\n", + "$(call dist-for-goals,my_goal,another.out:another.out)\n", + }, + }, + { + bp: ` + custom { + name: "foo", + dists: [ + { + targets: ["my_goal"], + tag: ".another-tag", + }, + ], + } + `, + expectedAndroidMkLines: []string{ + ".PHONY: my_goal\n", + "$(call dist-for-goals,my_goal,another.out:another.out)\n", + }, + }, + { + bp: ` + custom { + name: "foo", + dists: [ + { + targets: ["my_goal"], + }, + { + targets: ["my_second_goal", "my_third_goal"], + }, + ], + } + `, + expectedAndroidMkLines: []string{ + ".PHONY: my_goal\n", + "$(call dist-for-goals,my_goal,one.out:one.out)\n", + ".PHONY: my_second_goal my_third_goal\n", + "$(call dist-for-goals,my_second_goal my_third_goal,one.out:one.out)\n", + }, + }, + { + bp: ` + custom { + name: "foo", + dist: { + targets: ["my_goal"], + }, + dists: [ + { + targets: ["my_second_goal", "my_third_goal"], + }, + ], + } + `, + expectedAndroidMkLines: []string{ + ".PHONY: my_second_goal my_third_goal\n", + "$(call dist-for-goals,my_second_goal my_third_goal,one.out:one.out)\n", + ".PHONY: my_goal\n", + "$(call dist-for-goals,my_goal,one.out:one.out)\n", + }, + }, + { + bp: ` + custom { + name: "foo", + dist: { + targets: ["my_goal", "my_other_goal"], + tag: ".multiple", + }, + dists: [ + { + targets: ["my_second_goal"], + tag: ".multiple", + }, + { + targets: ["my_third_goal"], + dir: "test/dir", + }, + { + targets: ["my_fourth_goal"], + suffix: ".suffix", + }, + { + targets: ["my_fifth_goal"], + dest: "new-name", + }, + { + targets: ["my_sixth_goal"], + dest: "new-name", + dir: "some/dir", + suffix: ".suffix", + }, + ], + } + `, + expectedAndroidMkLines: []string{ + ".PHONY: my_second_goal\n", + "$(call dist-for-goals,my_second_goal,two.out:two.out)\n", + "$(call dist-for-goals,my_second_goal,three/four.out:four.out)\n", + ".PHONY: my_third_goal\n", + "$(call dist-for-goals,my_third_goal,one.out:test/dir/one.out)\n", + ".PHONY: my_fourth_goal\n", + "$(call dist-for-goals,my_fourth_goal,one.out:one.suffix.out)\n", + ".PHONY: my_fifth_goal\n", + "$(call dist-for-goals,my_fifth_goal,one.out:new-name)\n", + ".PHONY: my_sixth_goal\n", + "$(call dist-for-goals,my_sixth_goal,one.out:some/dir/new-name.suffix)\n", + ".PHONY: my_goal my_other_goal\n", + "$(call dist-for-goals,my_goal my_other_goal,two.out:two.out)\n", + "$(call dist-for-goals,my_goal my_other_goal,three/four.out:four.out)\n", + }, + }, + } + + for _, testCase := range testCases { + config := TestConfig(buildDir, nil, testCase.bp, nil) + config.inMake = true // Enable androidmk Singleton + + ctx := NewTestContext() + ctx.RegisterSingletonType("androidmk", AndroidMkSingleton) + ctx.RegisterModuleType("custom", customModuleFactory) + ctx.Register(config) + + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + FailIfErrored(t, errs) + + module := ctx.ModuleForTests("foo", "").Module().(*customModule) + entries := AndroidMkEntriesForTest(t, config, "", module) + if len(entries) != 1 { + t.Errorf("Expected a single AndroidMk entry, got %d", len(entries)) + } + androidMkLines := entries[0].GetDistForGoals(module) + + if len(androidMkLines) != len(testCase.expectedAndroidMkLines) { + t.Errorf( + "Expected %d AndroidMk lines, got %d:\n%v", + len(testCase.expectedAndroidMkLines), + len(androidMkLines), + androidMkLines, + ) + } + for idx, line := range androidMkLines { + expectedLine := testCase.expectedAndroidMkLines[idx] + if line != expectedLine { + t.Errorf( + "Expected AndroidMk line to be '%s', got '%s'", + line, + expectedLine, + ) + } + } + } +} diff --git a/android/apex.go b/android/apex.go index 30152db29..4c914ee65 100644 --- a/android/apex.go +++ b/android/apex.go @@ -442,19 +442,21 @@ func (d *ApexBundleDepsInfo) FullListPath() Path { // Generate two module out files: // 1. FullList with transitive deps and their parents in the dep graph // 2. FlatList with a flat list of transitive deps +// In both cases transitive deps of external deps are not included. Neither are deps that are only +// available to APEXes; they are developed with updatability in mind and don't need manual approval. func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) { var fullContent strings.Builder var flatContent strings.Builder - fmt.Fprintf(&flatContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion) + fmt.Fprintf(&fullContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion) for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) { info := depInfos[key] toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion) if info.IsExternal { toName = toName + " (external)" } - fmt.Fprintf(&fullContent, "%s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", ")) - fmt.Fprintf(&flatContent, " %s\\n", toName) + fmt.Fprintf(&fullContent, " %s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", ")) + fmt.Fprintf(&flatContent, "%s\\n", toName) } d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath diff --git a/android/config.go b/android/config.go index 3541f831e..24ec29d3e 100644 --- a/android/config.go +++ b/android/config.go @@ -113,7 +113,7 @@ type config struct { // If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error // in tests when a path doesn't exist. - testAllowNonExistentPaths bool + TestAllowNonExistentPaths bool OncePer } @@ -237,7 +237,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string // Set testAllowNonExistentPaths so that test contexts don't need to specify every path // passed to PathForSource or PathForModuleSrc. - testAllowNonExistentPaths: true, + TestAllowNonExistentPaths: true, } config.deviceConfig = &deviceConfig{ config: config, diff --git a/android/csuite_config.go b/android/csuite_config.go index 15c518a07..bf24d98c7 100644 --- a/android/csuite_config.go +++ b/android/csuite_config.go @@ -14,11 +14,6 @@ package android -import ( - "fmt" - "io" -) - func init() { RegisterModuleType("csuite_config", CSuiteConfigFactory) } @@ -38,22 +33,21 @@ func (me *CSuiteConfig) GenerateAndroidBuildActions(ctx ModuleContext) { me.OutputFilePath = PathForModuleOut(ctx, me.BaseModuleName()).OutputPath } -func (me *CSuiteConfig) AndroidMk() AndroidMkData { - androidMkData := AndroidMkData{ +func (me *CSuiteConfig) AndroidMkEntries() []AndroidMkEntries { + androidMkEntries := AndroidMkEntries{ Class: "FAKE", Include: "$(BUILD_SYSTEM)/suite_host_config.mk", OutputFile: OptionalPathForPath(me.OutputFilePath), } - androidMkData.Extra = []AndroidMkExtraFunc{ - func(w io.Writer, outputFile Path) { + androidMkEntries.ExtraEntries = []AndroidMkExtraEntriesFunc{ + func(entries *AndroidMkEntries) { if me.properties.Test_config != nil { - fmt.Fprintf(w, "LOCAL_TEST_CONFIG := %s\n", - *me.properties.Test_config) + entries.SetString("LOCAL_TEST_CONFIG", *me.properties.Test_config) } - fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE := csuite") + entries.AddCompatibilityTestSuites("csuite") }, } - return androidMkData + return []AndroidMkEntries{androidMkEntries} } func InitCSuiteConfigModule(me *CSuiteConfig) { diff --git a/android/defaults.go b/android/defaults.go index 81e340e8e..880c68927 100644 --- a/android/defaults.go +++ b/android/defaults.go @@ -95,6 +95,8 @@ func InitDefaultableModule(module DefaultableModule) { module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties) module.AddProperties(module.defaults()) + + module.base().customizableProperties = module.GetProperties() } // A restricted subset of context methods, similar to LoadHookContext. @@ -195,7 +197,8 @@ func InitDefaultsModule(module DefaultsModule) { module.AddProperties( &hostAndDeviceProperties{}, commonProperties, - &ApexProperties{}) + &ApexProperties{}, + &distProperties{}) initAndroidModuleBase(module) initProductVariableModule(module) @@ -220,6 +223,9 @@ func InitDefaultsModule(module DefaultsModule) { // its checking phase and parsing phase so add it to the list as a normal property. AddVisibilityProperty(module, "visibility", &commonProperties.Visibility) + // The applicable licenses property for defaults is 'licenses'. + setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses) + base.module = module } diff --git a/android/license.go b/android/license.go index 00ddacd41..3bc6199b2 100644 --- a/android/license.go +++ b/android/license.go @@ -14,6 +14,18 @@ package android +import ( + "github.com/google/blueprint" +) + +type licenseKindDependencyTag struct { + blueprint.BaseDependencyTag +} + +var ( + licenseKindTag = licenseKindDependencyTag{} +) + func init() { RegisterLicenseBuildComponents(InitRegistrationContext) } @@ -44,7 +56,7 @@ type licenseModule struct { } func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) { - // Do nothing. + ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...) } func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) { diff --git a/android/license_kind.go b/android/license_kind.go new file mode 100644 index 000000000..ddecd775f --- /dev/null +++ b/android/license_kind.go @@ -0,0 +1,66 @@ +// Copyright 2020 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 + +func init() { + RegisterLicenseKindBuildComponents(InitRegistrationContext) +} + +// Register the license_kind module type. +func RegisterLicenseKindBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("license_kind", LicenseKindFactory) +} + +type licenseKindProperties struct { + // Specifies the conditions for all licenses of the kind. + Conditions []string + // Specifies the url to the canonical license definition. + Url string + // Specifies where this license can be used + Visibility []string +} + +type licenseKindModule struct { + ModuleBase + DefaultableModuleBase + + properties licenseKindProperties +} + +func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) { + // Nothing to do. +} + +func (m *licenseKindModule) GenerateAndroidBuildActions(ModuleContext) { + // Nothing to do. +} + +func LicenseKindFactory() Module { + module := &licenseKindModule{} + + base := module.base() + module.AddProperties(&base.nameProperties, &module.properties) + + base.generalProperties = module.GetProperties() + base.customizableProperties = module.GetProperties() + + // The visibility property needs to be checked and parsed by the visibility module. + setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility) + + initAndroidModuleBase(module) + InitDefaultableModule(module) + + return module +} diff --git a/android/license_test.go b/android/license_test.go deleted file mode 100644 index e80ba5e94..000000000 --- a/android/license_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package android - -import ( - "testing" -) - -var licenseTests = []struct { - name string - fs map[string][]byte - expectedErrors []string -}{ - { - name: "license must not accept licenses property", - fs: map[string][]byte{ - "top/Blueprints": []byte(` - license { - name: "top_license", - visibility: ["//visibility:private"], - licenses: ["other_license"], - - }`), - }, - expectedErrors: []string{ - `top/Blueprints:5:14: unrecognized property "licenses"`, - }, - }, - { - name: "public license", - fs: map[string][]byte{ - "top/Blueprints": []byte(` - license { - name: "top_proprietary", - license_kinds: ["top_by_exception_only"], - visibility: ["//visibility:public"], - }`), - "other/Blueprints": []byte(` - rule { - name: "arule", - licenses: ["top_proprietary"], - - }`), - "yetmore/Blueprints": []byte(` - package { - default_applicable_licenses: ["top_proprietary"], - }`), - }, - }, - { - name: "multiple licenses", - fs: map[string][]byte{ - "top/Blueprints": []byte(` - package { - default_applicable_licenses: ["top_proprietary"], - } - license { - name: "top_allowed_as_notice", - license_kinds: ["top_notice"], - } - license { - name: "top_proprietary", - license_kinds: ["top_by_exception_only"], - visibility: ["//visibility:public"], - } - rule { - name: "myrule", - licenses: ["top_allowed_as_notice", "top_proprietary"] - }`), - "other/Blueprints": []byte(` - rule { - name: "arule", - licenses: ["top_proprietary"], - - }`), - "yetmore/Blueprints": []byte(` - package { - default_applicable_licenses: ["top_proprietary"], - }`), - }, - }, -} - -func TestLicense(t *testing.T) { - for _, test := range licenseTests { - t.Run(test.name, func(t *testing.T) { - _, errs := testLicense(test.fs) - expectedErrors := test.expectedErrors - if expectedErrors == nil { - FailIfErrored(t, errs) - } else { - for _, expectedError := range expectedErrors { - FailIfNoMatchingErrors(t, expectedError, errs) - } - if len(errs) > len(expectedErrors) { - t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs)) - for i, expectedError := range expectedErrors { - t.Errorf("expectedErrors[%d] = %s", i, expectedError) - } - for i, err := range errs { - t.Errorf("errs[%d] = %s", i, err) - } - } - } - }) - } -} -func testLicense(fs map[string][]byte) (*TestContext, []error) { - // Create a new config per test as visibility information is stored in the config. - env := make(map[string]string) - env["ANDROID_REQUIRE_LICENSES"] = "1" - config := TestArchConfig(buildDir, env, "", fs) - ctx := NewTestArchContext() - RegisterPackageBuildComponents(ctx) - registerTestPrebuiltBuildComponents(ctx) - RegisterLicenseBuildComponents(ctx) - ctx.RegisterModuleType("rule", newMockRuleModule) - ctx.PreArchMutators(RegisterVisibilityRuleChecker) - ctx.PreArchMutators(RegisterDefaultsPreArchMutators) - ctx.PreArchMutators(RegisterVisibilityRuleGatherer) - ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer) - ctx.Register(config) - _, errs := ctx.ParseBlueprintsFiles(".") - if len(errs) > 0 { - return ctx, errs - } - _, errs = ctx.PrepareBuildActions(config) - return ctx, errs -} - -type mockRuleModule struct { - ModuleBase - DefaultableModuleBase -} - -func newMockRuleModule() Module { - m := &mockRuleModule{} - InitAndroidModule(m) - InitDefaultableModule(m) - return m -} - -func (p *mockRuleModule) GenerateAndroidBuildActions(ModuleContext) { -} diff --git a/android/licenses.go b/android/licenses.go new file mode 100644 index 000000000..2838f5d28 --- /dev/null +++ b/android/licenses.go @@ -0,0 +1,295 @@ +// Copyright 2020 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 ( + "reflect" + "sync" + + "github.com/google/blueprint" +) + +// Adds cross-cutting licenses dependency to propagate license metadata through the build system. +// +// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name. +// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies. +// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency. +// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts. + +type licensesDependencyTag struct { + blueprint.BaseDependencyTag +} + +var ( + licensesTag = licensesDependencyTag{} +) + +// Describes the property provided by a module to reference applicable licenses. +type applicableLicensesProperty interface { + // The name of the property. e.g. default_applicable_licenses or licenses + getName() string + // The values assigned to the property. (Must reference license modules.) + getStrings() []string +} + +type applicableLicensesPropertyImpl struct { + name string + licensesProperty *[]string +} + +func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty { + return applicableLicensesPropertyImpl{ + name: name, + licensesProperty: licensesProperty, + } +} + +func (p applicableLicensesPropertyImpl) getName() string { + return p.name +} + +func (p applicableLicensesPropertyImpl) getStrings() []string { + return *p.licensesProperty +} + +// Set the primary applicable licenses property for a module. +func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) { + module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty) +} + +// Storage blob for a package's default_applicable_licenses mapped by package directory. +type licensesContainer struct { + licenses []string +} + +func (r licensesContainer) getLicenses() []string { + return r.licenses +} + +var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap") + +// The map from package dir name to default applicable licenses as a licensesContainer. +func moduleToPackageDefaultLicensesMap(config Config) *sync.Map { + return config.Once(packageDefaultLicensesMap, func() interface{} { + return &sync.Map{} + }).(*sync.Map) +} + +// Registers the function that maps each package to its default_applicable_licenses. +// +// This goes before defaults expansion so the defaults can pick up the package default. +func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) { + ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel() +} + +// Registers the function that gathers the license dependencies for each module. +// +// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement. +func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) { + ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel() +} + +// Registers the function that verifies the licenses and license_kinds dependency types for each module. +func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) { + ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel() +} + +// Maps each package to its default applicable licenses. +func licensesPackageMapper(ctx BottomUpMutatorContext) { + p, ok := ctx.Module().(*packageModule) + if !ok { + return + } + + licenses := getLicenses(ctx, p) + + dir := ctx.ModuleDir() + c := makeLicensesContainer(licenses) + moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c) +} + +// Copies the default_applicable_licenses property values for mapping by package directory. +func makeLicensesContainer(propVals []string) licensesContainer { + licenses := make([]string, 0, len(propVals)) + licenses = append(licenses, propVals...) + + return licensesContainer{licenses} +} + +// Gathers the applicable licenses into dependency references after defaults expansion. +func licensesPropertyGatherer(ctx BottomUpMutatorContext) { + m, ok := ctx.Module().(Module) + if !ok { + return + } + + if exemptFromRequiredApplicableLicensesProperty(m) { + return + } + + licenses := getLicenses(ctx, m) + + ctx.AddVariationDependencies(nil, licensesTag, licenses...) +} + +// Verifies the license and license_kind dependencies are each the correct kind of module. +func licensesDependencyChecker(ctx BottomUpMutatorContext) { + m, ok := ctx.Module().(Module) + if !ok { + return + } + + // license modules have no licenses, but license_kinds must refer to license_kind modules + if _, ok := m.(*licenseModule); ok { + for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) { + if _, ok := module.(*licenseKindModule); !ok { + ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module)) + } + } + return + } + + if exemptFromRequiredApplicableLicensesProperty(m) { + return + } + + for _, module := range ctx.GetDirectDepsWithTag(licensesTag) { + if _, ok := module.(*licenseModule); !ok { + propertyName := "licenses" + primaryProperty := m.base().primaryLicensesProperty + if primaryProperty != nil { + propertyName = primaryProperty.getName() + } + ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module)) + } + } +} + +// Flattens license and license_kind dependencies into calculated properties. +// +// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer +// only to license_kind modules. +func licensesPropertyFlattener(ctx ModuleContext) { + m, ok := ctx.Module().(Module) + if !ok { + return + } + + // license modules have no licenses, but license_kinds must refer to license_kind modules + if l, ok := m.(*licenseModule); ok { + mergeProps(&m.base().commonProperties.Effective_licenses, ctx.ModuleName()) + mergeProps(&m.base().commonProperties.Effective_license_text, PathsForModuleSrc(ctx, l.properties.License_text).Strings()...) + for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) { + if lk, ok := module.(*licenseKindModule); ok { + mergeProps(&m.base().commonProperties.Effective_license_conditions, lk.properties.Conditions...) + mergeProps(&m.base().commonProperties.Effective_license_kinds, ctx.OtherModuleName(module)) + } else { + ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module)) + } + } + return + } + + if exemptFromRequiredApplicableLicensesProperty(m) { + return + } + + for _, module := range ctx.GetDirectDepsWithTag(licensesTag) { + if l, ok := module.(*licenseModule); ok { + if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil { + m.base().commonProperties.Effective_package_name = l.properties.Package_name + } + mergeProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...) + mergeProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...) + mergeProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...) + mergeProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...) + } else { + propertyName := "licenses" + primaryProperty := m.base().primaryLicensesProperty + if primaryProperty != nil { + propertyName = primaryProperty.getName() + } + ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module)) + } + } +} + +// Update a property string array with a distinct union of its values and a list of new values. +func mergeProps(prop *[]string, values ...string) { + s := make(map[string]bool) + for _, v := range *prop { + s[v] = true + } + for _, v := range values { + s[v] = true + } + *prop = []string{} + *prop = append(*prop, SortedStringKeys(s)...) +} + +// Get the licenses property falling back to the package default. +func getLicenses(ctx BaseModuleContext, module Module) []string { + if exemptFromRequiredApplicableLicensesProperty(module) { + return nil + } + + primaryProperty := module.base().primaryLicensesProperty + if primaryProperty == nil { + if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") { + ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module)) + } + return nil + } + + licenses := primaryProperty.getStrings() + if len(licenses) > 0 { + s := make(map[string]bool) + for _, l := range licenses { + if _, ok := s[l]; ok { + ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName()) + } + s[l] = true + } + return licenses + } + + dir := ctx.OtherModuleDir(module) + + moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config()) + value, ok := moduleToApplicableLicenses.Load(dir) + var c licensesContainer + if ok { + c = value.(licensesContainer) + } else { + c = licensesContainer{} + } + return c.getLicenses() +} + +// Returns whether a module is an allowed list of modules that do not have or need applicable licenses. +func exemptFromRequiredApplicableLicensesProperty(module Module) bool { + switch reflect.TypeOf(module).String() { + case "*android.licenseModule": // is a license, doesn't need one + case "*android.licenseKindModule": // is a license, doesn't need one + case "*android.NamespaceModule": // just partitions things, doesn't add anything + case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses + case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses + case "*android.soongConfigStringVariableDummyModule": // used for creating aliases + case "*android.SoongConfigBoolVariableDummyModule": // used for creating aliases + default: + return false + } + return true +} diff --git a/android/module.go b/android/module.go index a498839ce..6b00d7982 100644 --- a/android/module.go +++ b/android/module.go @@ -94,6 +94,8 @@ type EarlyModuleContext interface { GlobFiles(globPattern string, excludes []string) Paths IsSymlink(path Path) bool Readlink(path Path) string + + Namespace() *Namespace } // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns @@ -204,7 +206,6 @@ type ModuleContext interface { VisitAllModuleVariants(visit func(Module)) GetMissingDependencies() []string - Namespace() blueprint.Namespace } type Module interface { @@ -231,6 +232,8 @@ type Module interface { InstallBypassMake() bool SkipInstall() IsSkipInstall() bool + ReplacedByPrebuilt() + IsReplacedByPrebuilt() bool ExportedToMake() bool InitRc() Paths VintfFragments() Paths @@ -300,6 +303,28 @@ func newPackageId(pkg string) qualifiedModuleName { return qualifiedModuleName{pkg: pkg, name: ""} } +type Dist struct { + // Copy the output of this module to the $DIST_DIR when `dist` is specified on the + // command line and any of these targets are also on the command line, or otherwise + // built + Targets []string `android:"arch_variant"` + + // The name of the output artifact. This defaults to the basename of the output of + // the module. + Dest *string `android:"arch_variant"` + + // The directory within the dist directory to store the artifact. Defaults to the + // top level directory (""). + Dir *string `android:"arch_variant"` + + // A suffix to add to the artifact file name (before any extension). + Suffix *string `android:"arch_variant"` + + // A string tag to select the OutputFiles associated with the tag. Defaults to the + // the empty "" string. + Tag *string `android:"arch_variant"` +} + type nameProperties struct { // The name of the module. Must be unique across all modules. Name *string @@ -360,9 +385,20 @@ type commonProperties struct { // more details. Visibility []string - // Names of the licenses that apply to this module. + // Describes the licenses applicable to this module. Must reference license modules. Licenses []string + // Flattened from direct license dependencies. Equal to Licenses unless particular module adds more. + Effective_licenses []string `blueprint:"mutated"` + // Override of module name when reporting licenses + Effective_package_name *string `blueprint:"mutated"` + // Notice files + Effective_license_text []string `blueprint:"mutated"` + // License names + Effective_license_kinds []string `blueprint:"mutated"` + // License conditions + Effective_license_conditions []string `blueprint:"mutated"` + // control whether this module compiles for 32-bit, 64-bit, or both. Possible values // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit @@ -442,24 +478,6 @@ type commonProperties struct { // relative path to a file to include in the list of notices for the device Notice *string `android:"path"` - Dist struct { - // copy the output of this module to the $DIST_DIR when `dist` is specified on the - // command line and any of these targets are also on the command line, or otherwise - // built - Targets []string `android:"arch_variant"` - - // The name of the output artifact. This defaults to the basename of the output of - // the module. - Dest *string `android:"arch_variant"` - - // The directory within the dist directory to store the artifact. Defaults to the - // top level directory (""). - Dir *string `android:"arch_variant"` - - // A suffix to add to the artifact file name (before any extension). - Suffix *string `android:"arch_variant"` - } `android:"arch_variant"` - // The OsType of artifacts that this module variant is responsible for creating. // // Set by osMutator @@ -512,6 +530,9 @@ type commonProperties struct { SkipInstall bool `blueprint:"mutated"` + // Whether the module has been replaced by a prebuilt + ReplacedByPrebuilt bool `blueprint:"mutated"` + NamespaceExportedToMake bool `blueprint:"mutated"` MissingDeps []string `blueprint:"mutated"` @@ -525,6 +546,30 @@ type commonProperties struct { ImageVariation string `blueprint:"mutated"` } +type distProperties struct { + // configuration to distribute output files from this module to the distribution + // directory (default: $OUT/dist, configurable with $DIST_DIR) + Dist Dist `android:"arch_variant"` + + // a list of configurations to distribute output files from this module to the + // distribution directory (default: $OUT/dist, configurable with $DIST_DIR) + Dists []Dist `android:"arch_variant"` +} + +// A map of OutputFile tag keys to Paths, for disting purposes. +type TaggedDistFiles map[string]Paths + +func MakeDefaultDistFiles(paths ...Path) TaggedDistFiles { + for _, path := range paths { + if path == nil { + panic("The path to a dist file cannot be nil.") + } + } + + // The default OutputFile tag is the empty "" string. + return TaggedDistFiles{"": paths} +} + type hostAndDeviceProperties struct { // If set to true, build a variant of the module for the host. Defaults to false. Host_supported *bool @@ -606,7 +651,8 @@ func InitAndroidModule(m Module) { m.AddProperties( &base.nameProperties, - &base.commonProperties) + &base.commonProperties, + &base.distProperties) initProductVariableModule(m) @@ -616,6 +662,10 @@ func InitAndroidModule(m Module) { // The default_visibility property needs to be checked and parsed by the visibility module during // its checking and parsing phases so make it the primary visibility property. setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility) + + // The default_applicable_licenses property needs to be checked and parsed by the licenses module during + // its checking and parsing phases so make it the primary licenses property. + setPrimaryLicensesProperty(m, "licenses", &base.commonProperties.Licenses) } func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) { @@ -697,6 +747,7 @@ type ModuleBase struct { nameProperties nameProperties commonProperties commonProperties + distProperties distProperties variableProperties interface{} hostAndDeviceProperties hostAndDeviceProperties generalProperties []interface{} @@ -710,6 +761,9 @@ type ModuleBase struct { // The primary visibility property, may be nil, that controls access to the module. primaryVisibilityProperty visibilityProperty + // The primary licenses property, may be nil, records license metadata for the module. + primaryLicensesProperty applicableLicensesProperty + noAddressSanitizer bool installFiles Paths checkbuildFiles Paths @@ -803,6 +857,41 @@ func (m *ModuleBase) visibilityProperties() []visibilityProperty { return m.visibilityPropertyInfo } +func (m *ModuleBase) Dists() []Dist { + if len(m.distProperties.Dist.Targets) > 0 { + // Make a copy of the underlying Dists slice to protect against + // backing array modifications with repeated calls to this method. + distsCopy := append([]Dist(nil), m.distProperties.Dists...) + return append(distsCopy, m.distProperties.Dist) + } else { + return m.distProperties.Dists + } +} + +func (m *ModuleBase) GenerateTaggedDistFiles(ctx BaseModuleContext) TaggedDistFiles { + distFiles := make(TaggedDistFiles) + for _, dist := range m.Dists() { + var tag string + var distFilesForTag Paths + if dist.Tag == nil { + tag = "" + } else { + tag = *dist.Tag + } + distFilesForTag, err := m.base().module.(OutputFileProducer).OutputFiles(tag) + if err != nil { + ctx.PropertyErrorf("dist.tag", "%s", err.Error()) + } + for _, distFile := range distFilesForTag { + if distFile != nil && !distFiles[tag].containsPath(distFile) { + distFiles[tag] = append(distFiles[tag], distFile) + } + } + } + + return distFiles +} + func (m *ModuleBase) Target() Target { return m.commonProperties.CompileTarget } @@ -959,6 +1048,15 @@ func (m *ModuleBase) IsSkipInstall() bool { return m.commonProperties.SkipInstall == true } +func (m *ModuleBase) ReplacedByPrebuilt() { + m.commonProperties.ReplacedByPrebuilt = true + m.SkipInstall() +} + +func (m *ModuleBase) IsReplacedByPrebuilt() bool { + return m.commonProperties.ReplacedByPrebuilt +} + func (m *ModuleBase) ExportedToMake() bool { return m.commonProperties.NamespaceExportedToMake } @@ -1082,7 +1180,7 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) { var deps Paths - namespacePrefix := ctx.Namespace().(*Namespace).id + namespacePrefix := ctx.Namespace().id if namespacePrefix != "" { namespacePrefix = namespacePrefix + "-" } @@ -1238,20 +1336,20 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) ctx.Variable(pctx, "moduleDescSuffix", s) // Some common property checks for properties that will be used later in androidmk.go - if m.commonProperties.Dist.Dest != nil { - _, err := validateSafePath(*m.commonProperties.Dist.Dest) + if m.distProperties.Dist.Dest != nil { + _, err := validateSafePath(*m.distProperties.Dist.Dest) if err != nil { ctx.PropertyErrorf("dist.dest", "%s", err.Error()) } } - if m.commonProperties.Dist.Dir != nil { - _, err := validateSafePath(*m.commonProperties.Dist.Dir) + if m.distProperties.Dist.Dir != nil { + _, err := validateSafePath(*m.distProperties.Dist.Dir) if err != nil { ctx.PropertyErrorf("dist.dir", "%s", err.Error()) } } - if m.commonProperties.Dist.Suffix != nil { - if strings.Contains(*m.commonProperties.Dist.Suffix, "/") { + if m.distProperties.Dist.Suffix != nil { + if strings.Contains(*m.distProperties.Dist.Suffix, "/") { ctx.PropertyErrorf("dist.suffix", "Suffix may not contain a '/' character.") } } @@ -1267,11 +1365,16 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) notice := proptools.StringDefault(m.commonProperties.Notice, "NOTICE") if module := SrcIsModule(notice); module != "" { m.noticeFile = ctx.ExpandOptionalSource(¬ice, "notice") - } else { + } else if notice != "" { noticePath := filepath.Join(ctx.ModuleDir(), notice) m.noticeFile = ExistentPathForSource(ctx, noticePath) } + licensesPropertyFlattener(ctx) + if ctx.Failed() { + return + } + m.module.GenerateAndroidBuildActions(ctx) if ctx.Failed() { return @@ -1380,6 +1483,10 @@ func (e *earlyModuleContext) SystemExtSpecific() bool { return e.kind == systemExtSpecificModule } +func (e *earlyModuleContext) Namespace() *Namespace { + return e.EarlyModuleContext.Namespace().(*Namespace) +} + type baseModuleContext struct { bp blueprint.BaseModuleContext earlyModuleContext @@ -1734,6 +1841,16 @@ func (m *moduleContext) FinalModule() Module { return m.bp.FinalModule().(Module) } +// IsMetaDependencyTag returns true for cross-cutting metadata dependencies. +func IsMetaDependencyTag(tag blueprint.DependencyTag) bool { + if tag == licenseKindTag { + return true + } else if tag == licensesTag { + return true + } + return false +} + func (m *moduleContext) ModuleSubDir() string { return m.bp.ModuleSubDir() } diff --git a/android/mutator.go b/android/mutator.go index 77d5f433e..49c6322fe 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -109,6 +109,11 @@ var preArch = []RegisterMutatorFunc{ // RegisterVisibilityRuleChecker, + // Record the default_applicable_licenses for each package. + // + // This must run before the defaults so that defaults modules can pick up the package default. + RegisterLicensesPackageMapper, + // Apply properties from defaults modules to the referencing modules. // // Any mutators that are added before this will not see any modules created by @@ -123,6 +128,12 @@ var preArch = []RegisterMutatorFunc{ // prebuilt. RegisterPrebuiltsPreArchMutators, + // Gather the licenses properties for all modules for use during expansion and enforcement. + // + // This must come after the defaults mutators to ensure that any licenses supplied + // in a defaults module has been successfully applied before the rules are gathered. + RegisterLicensesPropertyGatherer, + // Gather the visibility rules for all modules for us during visibility enforcement. // // This must come after the defaults mutators to ensure that any visibility supplied @@ -144,6 +155,7 @@ var postDeps = []RegisterMutatorFunc{ registerPathDepsMutator, RegisterPrebuiltsPostDepsMutators, RegisterVisibilityRuleEnforcer, + RegisterLicensesDependencyChecker, RegisterNeverallowMutator, RegisterOverridePostDepsMutators, } diff --git a/android/neverallow.go b/android/neverallow.go index 2eba4a950..620d616f2 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -51,7 +51,6 @@ var neverallows = []Rule{} func init() { AddNeverAllowRules(createIncludeDirsRules()...) AddNeverAllowRules(createTrebleRules()...) - AddNeverAllowRules(createLibcoreRules()...) AddNeverAllowRules(createMediaRules()...) AddNeverAllowRules(createJavaDeviceForHostRules()...) AddNeverAllowRules(createCcSdkVariantRules()...) @@ -132,31 +131,6 @@ func createTrebleRules() []Rule { } } -func createLibcoreRules() []Rule { - var coreLibraryProjects = []string{ - "libcore", - "external/apache-harmony", - "external/apache-xml", - "external/bouncycastle", - "external/conscrypt", - "external/icu", - "external/okhttp", - "external/wycheproof", - "prebuilts", - } - - // Core library constraints. The sdk_version: "none" can only be used in core library projects. - // Access to core library targets is restricted using visibility rules. - rules := []Rule{ - NeverAllow(). - NotIn(coreLibraryProjects...). - With("sdk_version", "none"). - WithoutMatcher("name", Regexp("^android_.*stubs_current$")), - } - - return rules -} - func createMediaRules() []Rule { return []Rule{ NeverAllow(). @@ -187,6 +161,10 @@ func createCcSdkVariantRules() []Rule { // derive_sdk_prefer32 suppress the platform installation rules, but fails when // the APEX modules contain the SDK variant and the platform variant still exists. "frameworks/base/apex/sdkextensions/derive_sdk", + + // libtextclassifier_tests needs to use the SDK variant so that the coverage data + // aligns with the usage in a mainline module. b/166040889 + "external/libtextclassifier/native", } platformVariantPropertiesAllowedList := []string{ diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 45d36a69b..b72ab8c8e 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -215,50 +215,6 @@ var neverallowTests = []struct { "java_device_for_host can only be used in allowed projects", }, }, - // Libcore rule tests - { - name: "sdk_version: \"none\" inside core libraries", - fs: map[string][]byte{ - "libcore/Android.bp": []byte(` - java_library { - name: "inside_core_libraries", - sdk_version: "none", - }`), - }, - }, - { - name: "sdk_version: \"none\" on android_*stubs_current stub", - fs: map[string][]byte{ - "frameworks/base/Android.bp": []byte(` - java_library { - name: "android_stubs_current", - sdk_version: "none", - }`), - }, - }, - { - name: "sdk_version: \"none\" outside core libraries", - fs: map[string][]byte{ - "Android.bp": []byte(` - java_library { - name: "outside_core_libraries", - sdk_version: "none", - }`), - }, - expectedErrors: []string{ - "module \"outside_core_libraries\": violates neverallow", - }, - }, - { - name: "sdk_version: \"current\"", - fs: map[string][]byte{ - "Android.bp": []byte(` - java_library { - name: "outside_core_libraries", - sdk_version: "current", - }`), - }, - }, // CC sdk rule tests { name: `"sdk_variant_only" outside allowed list`, diff --git a/android/override_module.go b/android/override_module.go index 90ddf5049..3d8b18bb4 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -302,3 +302,15 @@ func replaceDepsOnOverridingModuleMutator(ctx BottomUpMutatorContext) { } } } + +// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current +// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule +// or if this variant is not overridden. +func ModuleNameWithPossibleOverride(ctx ModuleContext) string { + if overridable, ok := ctx.Module().(OverridableModule); ok { + if o := overridable.GetOverriddenBy(); o != "" { + return o + } + } + return ctx.ModuleName() +} diff --git a/android/package.go b/android/package.go index 053fec286..7012fc7d8 100644 --- a/android/package.go +++ b/android/package.go @@ -31,7 +31,7 @@ func RegisterPackageBuildComponents(ctx RegistrationContext) { type packageProperties struct { // Specifies the default visibility for all modules defined in this package. Default_visibility []string - // Specifies the names of the default licenses for all modules defined in this package. + // Specifies the default license terms for all modules defined in this package. Default_applicable_licenses []string } @@ -70,5 +70,9 @@ func PackageFactory() Module { // its checking and parsing phases so make it the primary visibility property. setPrimaryVisibilityProperty(module, "default_visibility", &module.properties.Default_visibility) + // The default_applicable_licenses property needs to be checked and parsed by the licenses module during + // its checking and parsing phases so make it the primary licenses property. + setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses) + return module } diff --git a/android/package_test.go b/android/package_test.go index f25599cf8..9321ba826 100644 --- a/android/package_test.go +++ b/android/package_test.go @@ -17,9 +17,11 @@ var packageTests = []struct { package { name: "package", visibility: ["//visibility:private"], + licenses: ["license"], }`), }, expectedErrors: []string{ + `top/Blueprints:5:14: unrecognized property "licenses"`, `top/Blueprints:3:10: unrecognized property "name"`, `top/Blueprints:4:16: unrecognized property "visibility"`, }, @@ -47,7 +49,7 @@ var packageTests = []struct { default_applicable_licenses: ["license"], } - package { + package { }`), }, expectedErrors: []string{ diff --git a/android/paths.go b/android/paths.go index ddbeed3c5..2e0b25125 100644 --- a/android/paths.go +++ b/android/paths.go @@ -211,6 +211,15 @@ func (p OptionalPath) String() string { // Paths is a slice of Path objects, with helpers to operate on the collection. type Paths []Path +func (paths Paths) containsPath(path Path) bool { + for _, p := range paths { + if p == path { + return true + } + } + return false +} + // PathsForSource returns Paths rooted from SrcDir func PathsForSource(ctx PathContext, paths []string) Paths { ret := make(Paths, len(paths)) @@ -396,7 +405,7 @@ func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (P p := pathForModuleSrc(ctx, s) if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil { reportPathErrorf(ctx, "%s: %s", p, err.Error()) - } else if !exists && !ctx.Config().testAllowNonExistentPaths { + } else if !exists && !ctx.Config().TestAllowNonExistentPaths { reportPathErrorf(ctx, "module source path %q does not exist", p) } @@ -771,7 +780,7 @@ func PathForSource(ctx PathContext, pathComponents ...string) SourcePath { } } else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil { reportPathErrorf(ctx, "%s: %s", path, err.Error()) - } else if !exists && !ctx.Config().testAllowNonExistentPaths { + } else if !exists && !ctx.Config().TestAllowNonExistentPaths { reportPathErrorf(ctx, "source path %q does not exist", path) } return path diff --git a/android/prebuilt.go b/android/prebuilt.go index ee4a13af2..8ad81e6cd 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -227,7 +227,7 @@ func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { p := m.(PrebuiltInterface).Prebuilt() if p.usePrebuilt(ctx, s) { p.properties.UsePrebuilt = true - s.SkipInstall() + s.ReplacedByPrebuilt() } }) } diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go index f905b1ab2..9677f34cf 100644 --- a/android/soong_config_modules_test.go +++ b/android/soong_config_modules_test.go @@ -19,8 +19,24 @@ import ( "testing" ) +type soongConfigTestDefaultsModuleProperties struct { +} + +type soongConfigTestDefaultsModule struct { + ModuleBase + DefaultsModuleBase +} + +func soongConfigTestDefaultsModuleFactory() Module { + m := &soongConfigTestDefaultsModule{} + m.AddProperties(&soongConfigTestModuleProperties{}) + InitDefaultsModule(m) + return m +} + type soongConfigTestModule struct { ModuleBase + DefaultableModuleBase props soongConfigTestModuleProperties } @@ -32,6 +48,7 @@ func soongConfigTestModuleFactory() Module { m := &soongConfigTestModule{} m.AddProperties(&m.props) InitAndroidModule(m) + InitDefaultableModule(m) return m } @@ -40,13 +57,13 @@ func (t soongConfigTestModule) GenerateAndroidBuildActions(ModuleContext) {} func TestSoongConfigModule(t *testing.T) { configBp := ` soong_config_module_type { - name: "acme_test_defaults", - module_type: "test_defaults", + name: "acme_test", + module_type: "test", config_namespace: "acme", variables: ["board", "feature1", "FEATURE3"], bool_variables: ["feature2"], value_variables: ["size"], - properties: ["cflags", "srcs"], + properties: ["cflags", "srcs", "defaults"], } soong_config_string_variable { @@ -66,14 +83,20 @@ func TestSoongConfigModule(t *testing.T) { importBp := ` soong_config_module_type_import { from: "SoongConfig.bp", - module_types: ["acme_test_defaults"], + module_types: ["acme_test"], } ` bp := ` - acme_test_defaults { + test_defaults { + name: "foo_defaults", + cflags: ["DEFAULT"], + } + + acme_test { name: "foo", cflags: ["-DGENERIC"], + defaults: ["foo_defaults"], soong_config_variables: { board: { soc_a: { @@ -97,6 +120,46 @@ func TestSoongConfigModule(t *testing.T) { }, }, } + + test_defaults { + name: "foo_defaults_a", + cflags: ["DEFAULT_A"], + } + + test_defaults { + name: "foo_defaults_b", + cflags: ["DEFAULT_B"], + } + + acme_test { + name: "foo_with_defaults", + cflags: ["-DGENERIC"], + defaults: ["foo_defaults"], + soong_config_variables: { + board: { + soc_a: { + cflags: ["-DSOC_A"], + defaults: ["foo_defaults_a"], + }, + soc_b: { + cflags: ["-DSOC_B"], + defaults: ["foo_defaults_b"], + }, + }, + size: { + cflags: ["-DSIZE=%s"], + }, + feature1: { + cflags: ["-DFEATURE1"], + }, + feature2: { + cflags: ["-DFEATURE2"], + }, + FEATURE3: { + cflags: ["-DFEATURE3"], + }, + }, + } ` run := func(t *testing.T, bp string, fs map[string][]byte) { @@ -117,7 +180,9 @@ func TestSoongConfigModule(t *testing.T) { ctx.RegisterModuleType("soong_config_module_type", soongConfigModuleTypeFactory) ctx.RegisterModuleType("soong_config_string_variable", soongConfigStringVariableDummyFactory) ctx.RegisterModuleType("soong_config_bool_variable", soongConfigBoolVariableDummyFactory) - ctx.RegisterModuleType("test_defaults", soongConfigTestModuleFactory) + ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory) + ctx.RegisterModuleType("test", soongConfigTestModuleFactory) + ctx.PreArchMutators(RegisterDefaultsPreArchMutators) ctx.Register(config) _, errs := ctx.ParseBlueprintsFiles("Android.bp") @@ -125,10 +190,18 @@ func TestSoongConfigModule(t *testing.T) { _, errs = ctx.PrepareBuildActions(config) FailIfErrored(t, errs) + basicCFlags := []string{"DEFAULT", "-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"} + foo := ctx.ModuleForTests("foo", "").Module().(*soongConfigTestModule) - if g, w := foo.props.Cflags, []string{"-DGENERIC", "-DSIZE=42", "-DSOC_A", "-DFEATURE1"}; !reflect.DeepEqual(g, w) { + if g, w := foo.props.Cflags, basicCFlags; !reflect.DeepEqual(g, w) { t.Errorf("wanted foo cflags %q, got %q", w, g) } + + fooDefaults := ctx.ModuleForTests("foo_with_defaults", "").Module().(*soongConfigTestModule) + if g, w := fooDefaults.props.Cflags, append([]string{"DEFAULT_A"}, basicCFlags...); !reflect.DeepEqual(g, w) { + t.Errorf("wanted foo_with_defaults cflags %q, got %q", w, g) + } + } t.Run("single file", func(t *testing.T) { diff --git a/apex/Android.bp b/apex/Android.bp index 144f44197..1a5f6837e 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -5,6 +5,7 @@ bootstrap_go_package { "blueprint", "soong", "soong-android", + "soong-bpf", "soong-cc", "soong-java", "soong-python", diff --git a/apex/OWNERS b/apex/OWNERS index a382ae810..8e4ba5cd5 100644 --- a/apex/OWNERS +++ b/apex/OWNERS @@ -1 +1 @@ -per-file * = jiyong@google.com
\ No newline at end of file +per-file * = jiyong@google.com diff --git a/apex/androidmk.go b/apex/androidmk.go index e4cdef0bc..66f4dc897 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -79,10 +79,6 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo } for _, fi := range a.filesInfo { - if ccMod, ok := fi.module.(*cc.Module); ok && ccMod.Properties.HideFromMake { - continue - } - linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() var moduleName string @@ -254,7 +250,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo return moduleNames } -func (a *apexBundle) writeRequiredModules(w io.Writer) { +func (a *apexBundle) writeRequiredModules(w io.Writer, apexBundleName string) { var required []string var targetRequired []string var hostRequired []string @@ -293,7 +289,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { if len(moduleNames) > 0 { fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " ")) } - a.writeRequiredModules(w) + a.writeRequiredModules(w, name) fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)") } else { @@ -312,7 +308,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { if len(a.requiredDeps) > 0 { fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " ")) } - a.writeRequiredModules(w) + a.writeRequiredModules(w, name) var postInstallCommands []string if a.prebuiltFileToDelete != "" { postInstallCommands = append(postInstallCommands, "rm -rf "+ @@ -345,6 +341,24 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n", goal, a.installedFilesFile.String(), distFile) } + + if a.apisUsedByModuleFile.String() != "" { + goal := "apps_only" + distFile := a.apisUsedByModuleFile.String() + fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+ + " $(call dist-for-goals,%s,%s:ndk_apis_usedby_apex/$(notdir %s))\n"+ + "endif\n", + goal, distFile, distFile) + } + + if a.apisBackedByModuleFile.String() != "" { + goal := "apps_only" + distFile := a.apisBackedByModuleFile.String() + fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+ + " $(call dist-for-goals,%s,%s:ndk_apis_backedby_apex/$(notdir %s))\n"+ + "endif\n", + goal, distFile, distFile) + } } }} } diff --git a/apex/apex.go b/apex/apex.go index 7da8e1cf2..e4b052572 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -28,6 +28,7 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bpf" "android/soong/cc" prebuilt_etc "android/soong/etc" "android/soong/java" @@ -63,6 +64,7 @@ var ( certificateTag = dependencyTag{name: "certificate"} usesTag = dependencyTag{name: "uses"} androidAppTag = dependencyTag{name: "androidApp", payload: true} + bpfTag = dependencyTag{name: "bpf", payload: true} apexAvailBaseline = makeApexAvailableBaseline() @@ -1062,6 +1064,9 @@ type apexBundleProperties struct { // List of tests that are embedded inside this APEX bundle Tests []string + // List of BPF programs inside APEX + Bpfs []string + // Name of the apex_key module that provides the private key to sign APEX Key *string @@ -1268,6 +1273,8 @@ type apexFile struct { lintDepSets java.LintDepSets // only for javalibs and apps certificate java.Certificate // only for apps overriddenPackageName string // only for apps + + noticeFile android.OptionalPath } func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile { @@ -1283,6 +1290,7 @@ func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleNa ret.requiredModuleNames = module.RequiredModuleNames() ret.targetRequiredModuleNames = module.TargetRequiredModuleNames() ret.hostRequiredModuleNames = module.HostRequiredModuleNames() + ret.noticeFile = module.NoticeFile() } return ret } @@ -1391,6 +1399,10 @@ type apexBundle struct { // Optional list of lint report zip files for apexes that contain java or app modules lintReports android.Paths + + // Path of API coverage generate files + apisUsedByModuleFile android.ModuleOutPath + apisBackedByModuleFile android.ModuleOutPath } func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, @@ -1552,6 +1564,9 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), javaLibTag, a.properties.Java_libs...) + ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), + bpfTag, a.properties.Bpfs...) + // With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library. if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), @@ -1813,6 +1828,11 @@ func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface { return af } +func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, bpfProgram bpf.BpfModule) apexFile { + dirInApex := filepath.Join("etc", "bpf") + return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram) +} + // Context "decorator", overriding the InstallBypassMake method to always reply `true`. type flattenedApexContext struct { android.ModuleContext @@ -2079,6 +2099,15 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } else { ctx.PropertyErrorf("apps", "%q is not an android_app module", depName) } + case bpfTag: + if bpfProgram, ok := child.(bpf.BpfModule); ok { + filesToCopy, _ := bpfProgram.OutputFiles("") + for _, bpfFile := range filesToCopy { + filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, bpfProgram)) + } + } else { + ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName) + } case prebuiltTag: if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok { filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName)) diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go index 83a56a2b5..1ac2e5c3e 100644 --- a/apex/apex_singleton.go +++ b/apex/apex_singleton.go @@ -27,39 +27,81 @@ func init() { } type apexDepsInfoSingleton struct { - // Output file with all flatlists from updatable modules' deps-info combined - updatableFlatListsPath android.OutputPath + allowedApexDepsInfoCheckResult android.OutputPath } func apexDepsInfoSingletonFactory() android.Singleton { return &apexDepsInfoSingleton{} } -var combineFilesRule = pctx.AndroidStaticRule("combineFilesRule", - blueprint.RuleParams{ - Command: "cat $out.rsp | xargs cat > $out", +var ( + // Generate new apex allowed_deps.txt by merging all internal dependencies. + generateApexDepsInfoFilesRule = pctx.AndroidStaticRule("generateApexDepsInfoFilesRule", blueprint.RuleParams{ + Command: "cat $out.rsp | xargs cat" + + // Only track non-external dependencies, i.e. those that end up in the binary + " | grep -v '(external)'" + + // Ignore comments in any of the files + " | grep -v '^#'" + + " | sort -u -f >$out", Rspfile: "$out.rsp", RspfileContent: "$in", - }, + }) + + // Diff two given lists while ignoring comments in the allowed deps file. + diffAllowedApexDepsInfoRule = pctx.AndroidStaticRule("diffAllowedApexDepsInfoRule", blueprint.RuleParams{ + Description: "Diff ${allowed_deps} and ${new_allowed_deps}", + Command: ` + if grep -v '^#' ${allowed_deps} | diff -B - ${new_allowed_deps}; then + touch ${out}; + else + echo -e "\n******************************"; + echo "ERROR: go/apex-allowed-deps-error"; + echo "******************************"; + echo "Detected changes to allowed dependencies in updatable modules."; + echo "To fix and update packages/modules/common/build/allowed_deps.txt, please run:"; + echo "$$ (croot && packages/modules/common/build/update-apex-allowed-deps.sh)"; + echo "Members of mainline-modularization@google.com will review the changes."; + echo -e "******************************\n"; + exit 1; + fi; + `, + }, "allowed_deps", "new_allowed_deps") ) func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) { updatableFlatLists := android.Paths{} ctx.VisitAllModules(func(module android.Module) { if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok { - if path := binaryInfo.FlatListPath(); path != nil { - if binaryInfo.Updatable() { - updatableFlatLists = append(updatableFlatLists, path) - } + if path := binaryInfo.FlatListPath(); path != nil && binaryInfo.Updatable() { + updatableFlatLists = append(updatableFlatLists, path) } } }) - s.updatableFlatListsPath = android.PathForOutput(ctx, "apex", "depsinfo", "updatable-flatlists.txt") + allowedDeps := android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt").Path() + + newAllowedDeps := android.PathForOutput(ctx, "apex", "depsinfo", "new-allowed-deps.txt") ctx.Build(pctx, android.BuildParams{ - Rule: combineFilesRule, - Description: "Generate " + s.updatableFlatListsPath.String(), - Inputs: updatableFlatLists, - Output: s.updatableFlatListsPath, + Rule: generateApexDepsInfoFilesRule, + Inputs: append(updatableFlatLists, allowedDeps), + Output: newAllowedDeps, }) + + s.allowedApexDepsInfoCheckResult = android.PathForOutput(ctx, newAllowedDeps.Rel()+".check") + ctx.Build(pctx, android.BuildParams{ + Rule: diffAllowedApexDepsInfoRule, + Input: newAllowedDeps, + Output: s.allowedApexDepsInfoCheckResult, + Args: map[string]string{ + "allowed_deps": allowedDeps.String(), + "new_allowed_deps": newAllowedDeps.String(), + }, + }) + + ctx.Phony("apex-allowed-deps-check", s.allowedApexDepsInfoCheckResult) +} + +func (s *apexDepsInfoSingleton) MakeVars(ctx android.MakeVarsContext) { + // Export check result to Make. The path is added to droidcore. + ctx.Strict("APEX_ALLOWED_DEPS_CHECK", s.allowedApexDepsInfoCheckResult.String()) } diff --git a/apex/apex_test.go b/apex/apex_test.go index 8803a5f97..3442b6d08 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -27,6 +27,7 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bpf" "android/soong/cc" "android/soong/dexpreopt" prebuilt_etc "android/soong/etc" @@ -232,6 +233,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr java.RegisterAppBuildComponents(ctx) java.RegisterSdkLibraryBuildComponents(ctx) ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory) + ctx.RegisterModuleType("bpf", bpf.BpfFactory) ctx.PreDepsMutators(RegisterPreDepsMutators) ctx.PostDepsMutators(RegisterPostDepsMutators) @@ -533,18 +535,16 @@ func TestBasicApex(t *testing.T) { ensureListContains(t, noticeInputs, "custom_notice_for_static_lib") fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") - ensureListContains(t, fullDepsInfo, "myjar(minSdkVersion:(no version)) <- myapex") - ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex") - ensureListContains(t, fullDepsInfo, "mylib2(minSdkVersion:(no version)) <- mylib") - ensureListContains(t, fullDepsInfo, "myotherjar(minSdkVersion:(no version)) <- myjar") - ensureListContains(t, fullDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external) <- myjar") + ensureListContains(t, fullDepsInfo, " myjar(minSdkVersion:(no version)) <- myapex") + ensureListContains(t, fullDepsInfo, " mylib2(minSdkVersion:(no version)) <- mylib") + ensureListContains(t, fullDepsInfo, " myotherjar(minSdkVersion:(no version)) <- myjar") + ensureListContains(t, fullDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external) <- myjar") flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n") - ensureListContains(t, flatDepsInfo, " myjar(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " mylib(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " mylib2(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " myotherjar(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external)") + ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external)") } func TestDefaults(t *testing.T) { @@ -556,6 +556,7 @@ func TestDefaults(t *testing.T) { native_shared_libs: ["mylib"], java_libs: ["myjar"], apps: ["AppFoo"], + bpfs: ["bpf"], } prebuilt_etc { @@ -596,12 +597,20 @@ func TestDefaults(t *testing.T) { system_modules: "none", apex_available: [ "myapex" ], } + + bpf { + name: "bpf", + srcs: ["bpf.c", "bpf2.c"], + } + `) ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ "etc/myetc", "javalib/myjar.jar", "lib64/mylib.so", "app/AppFoo/AppFoo.apk", + "etc/bpf/bpf.o", + "etc/bpf/bpf2.o", }) } @@ -846,14 +855,10 @@ func TestApexWithExplicitStubsDependency(t *testing.T) { ensureNotContains(t, libFooStubsLdFlags, "libbar.so") fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") - ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex2") - ensureListContains(t, fullDepsInfo, "libbaz(minSdkVersion:(no version)) <- mylib") - ensureListContains(t, fullDepsInfo, "libfoo(minSdkVersion:(no version)) (external) <- mylib") + ensureListContains(t, fullDepsInfo, " libfoo(minSdkVersion:(no version)) (external) <- mylib") flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n") - ensureListContains(t, flatDepsInfo, " mylib(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " libbaz(minSdkVersion:(no version))") - ensureListContains(t, flatDepsInfo, " libfoo(minSdkVersion:(no version)) (external)") + ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)") } func TestApexWithRuntimeLibsDependency(t *testing.T) { diff --git a/apex/builder.go b/apex/builder.go index 8573dc0d7..47ced77da 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -36,6 +36,7 @@ var ( func init() { pctx.Import("android/soong/android") + pctx.Import("android/soong/cc/config") pctx.Import("android/soong/java") pctx.HostBinToolVariable("apexer", "apexer") // ART minimal builds (using the master-art manifest) do not have the "frameworks/base" @@ -62,6 +63,7 @@ func init() { pctx.HostBinToolVariable("jsonmodify", "jsonmodify") pctx.HostBinToolVariable("conv_apex_manifest", "conv_apex_manifest") pctx.HostBinToolVariable("extract_apks", "extract_apks") + pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh") } var ( @@ -172,6 +174,12 @@ var ( `exit 1); touch ${out}`, Description: "Diff ${image_content_file} and ${allowed_files_file}", }, "image_content_file", "allowed_files_file", "apex_module_name") + + generateAPIsUsedbyApexRule = pctx.StaticRule("generateAPIsUsedbyApexRule", blueprint.RuleParams{ + Command: "$genNdkUsedbyApexPath ${image_dir} ${readelf} ${out}", + CommandDeps: []string{"${genNdkUsedbyApexPath}"}, + Description: "Generate symbol list used by Apex", + }, "image_dir", "readelf") ) func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, requireNativeLibs []string) { @@ -237,6 +245,12 @@ func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName st return true }) + for _, fi := range a.filesInfo { + if fi.noticeFile.Valid() { + noticeFiles = append(noticeFiles, fi.noticeFile.Path()) + } + } + if len(noticeFiles) == 0 { return android.NoticeOutputs{} } @@ -463,13 +477,10 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String()) } - targetSdkVersion := ctx.Config().DefaultAppTargetSdk() - // TODO(b/157078772): propagate min_sdk_version to apexer. - minSdkVersion := ctx.Config().DefaultAppTargetSdk() - - if a.minSdkVersion(ctx) == android.SdkVersion_Android10 { - minSdkVersion = strconv.Itoa(a.minSdkVersion(ctx)) - } + minSdkVersion := strconv.Itoa(a.minSdkVersion(ctx)) + // apex module doesn't have a concept of target_sdk_version, hence for the time being + // targetSdkVersion == default targetSdkVersion of the branch. + targetSdkVersion := strconv.Itoa(ctx.Config().DefaultAppTargetSdkInt()) if java.UseApiFingerprint(ctx) { targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", java.ApiFingerprintPath(ctx).String()) @@ -547,6 +558,39 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { Description: "apex proto convert", }) + implicitInputs = append(implicitInputs, unsignedOutputFile) + + // Run coverage analysis + apisUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.txt") + ctx.Build(pctx, android.BuildParams{ + Rule: generateAPIsUsedbyApexRule, + Implicits: implicitInputs, + Description: "coverage", + Output: apisUsedbyOutputFile, + Args: map[string]string{ + "image_dir": imageDir.String(), + "readelf": "${config.ClangBin}/llvm-readelf", + }, + }) + a.apisUsedByModuleFile = apisUsedbyOutputFile + + var libNames []string + for _, f := range a.filesInfo { + if f.class == nativeSharedLib { + libNames = append(libNames, f.Stem()) + } + } + apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt") + ndkLibraryList := android.PathForSource(ctx, "system/core/rootdir/etc/public.libraries.android.txt") + rule := android.NewRuleBuilder() + rule.Command(). + Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")). + Output(apisBackedbyOutputFile). + Input(ndkLibraryList). + Flags(libNames) + rule.Build(pctx, ctx, "ndk_backedby_list", "Generate API libraries backed by Apex") + a.apisBackedByModuleFile = apisBackedbyOutputFile + bundleConfig := a.buildBundleConfig(ctx) ctx.Build(pctx, android.BuildParams{ @@ -715,6 +759,12 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { return !externalDep } + // Skip dependencies that are only available to APEXes; they are developed with updatability + // in mind and don't need manual approval. + if to.(android.ApexModule).NotAvailableForPlatform() { + return !externalDep + } + if info, exists := depInfos[to.Name()]; exists { if !android.InList(from.Name(), info.From) { info.From = append(info.From, from.Name()) diff --git a/bpf/bpf.go b/bpf/bpf.go index 59d1502ff..4b5237576 100644 --- a/bpf/bpf.go +++ b/bpf/bpf.go @@ -26,7 +26,7 @@ import ( ) func init() { - android.RegisterModuleType("bpf", bpfFactory) + android.RegisterModuleType("bpf", BpfFactory) pctx.Import("android/soong/cc/config") } @@ -43,6 +43,13 @@ var ( "ccCmd", "cFlags") ) +// BpfModule interface is used by the apex package to gather information from a bpf module. +type BpfModule interface { + android.Module + + OutputFiles(tag string) (android.Paths, error) +} + type BpfProperties struct { Srcs []string `android:"path"` Cflags []string @@ -137,7 +144,7 @@ func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) { var _ android.OutputFileProducer = (*bpf)(nil) -func bpfFactory() android.Module { +func BpfFactory() android.Module { module := &bpf{} module.AddProperties(&module.properties) diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go index eeca05771..d06d7d1a5 100644 --- a/bpf/bpf_test.go +++ b/bpf/bpf_test.go @@ -59,7 +59,7 @@ func testConfig(buildDir string, env map[string]string, bp string) android.Confi func testContext(config android.Config) *android.TestContext { ctx := cc.CreateTestContext() - ctx.RegisterModuleType("bpf", bpfFactory) + ctx.RegisterModuleType("bpf", BpfFactory) ctx.Register(config) return ctx diff --git a/cc/androidmk.go b/cc/androidmk.go index fede601b4..8208ea3f3 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -241,7 +241,10 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries entries.Class = "HEADER_LIBRARIES" } - entries.DistFile = library.distFile + if library.distFile != nil { + entries.DistFiles = android.MakeDefaultDistFiles(library.distFile) + } + entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { library.androidMkWriteExportedFlags(entries) library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries) @@ -310,7 +313,7 @@ func (binary *binaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *a ctx.subAndroidMk(entries, binary.baseInstaller) entries.Class = "EXECUTABLES" - entries.DistFile = binary.distFile + entries.DistFiles = binary.distFiles entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", binary.unstrippedOutputFile.String()) if len(binary.symlinks) > 0 { @@ -335,8 +338,7 @@ func (benchmark *benchmarkDecorator) AndroidMkEntries(ctx AndroidMkContext, entr entries.Class = "NATIVE_TESTS" entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { if len(benchmark.Properties.Test_suites) > 0 { - entries.SetString("LOCAL_COMPATIBILITY_SUITE", - strings.Join(benchmark.Properties.Test_suites, " ")) + entries.AddCompatibilityTestSuites(benchmark.Properties.Test_suites...) } if benchmark.testConfig != nil { entries.SetString("LOCAL_FULL_TEST_CONFIG", benchmark.testConfig.String()) @@ -358,8 +360,7 @@ func (test *testBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android. } entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { if len(test.Properties.Test_suites) > 0 { - entries.SetString("LOCAL_COMPATIBILITY_SUITE", - strings.Join(test.Properties.Test_suites, " ")) + entries.AddCompatibilityTestSuites(test.Properties.Test_suites...) } if test.testConfig != nil { entries.SetString("LOCAL_FULL_TEST_CONFIG", test.testConfig.String()) diff --git a/cc/binary.go b/cc/binary.go index 251b7f0c4..565cb8ae7 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -98,8 +98,8 @@ type binaryDecorator struct { // Output archive of gcno coverage information coverageOutputFile android.OptionalPath - // Location of the file that should be copied to dist dir when requested - distFile android.OptionalPath + // Location of the files that should be copied to dist dir when requested + distFiles android.TaggedDistFiles post_install_cmds []string } @@ -367,11 +367,11 @@ func (binary *binaryDecorator) link(ctx ModuleContext, binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile) } else { versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName) - binary.distFile = android.OptionalPathForPath(versionedOutputFile) + binary.distFiles = android.MakeDefaultDistFiles(versionedOutputFile) if binary.stripper.needsStrip(ctx) { out := android.PathForModuleOut(ctx, "versioned-stripped", fileName) - binary.distFile = android.OptionalPathForPath(out) + binary.distFiles = android.MakeDefaultDistFiles(out) binary.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags) } diff --git a/cc/library.go b/cc/library.go index 3deb17300..24c0629cd 100644 --- a/cc/library.go +++ b/cc/library.go @@ -365,7 +365,7 @@ type libraryDecorator struct { unstrippedOutputFile android.Path // Location of the file that should be copied to dist dir when requested - distFile android.OptionalPath + distFile android.Path versionScriptPath android.ModuleGenPath @@ -890,7 +890,7 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, library.injectVersionSymbol(ctx, outputFile, versionedOutputFile) } else { versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName) - library.distFile = android.OptionalPathForPath(versionedOutputFile) + library.distFile = versionedOutputFile library.injectVersionSymbol(ctx, outputFile, versionedOutputFile) } } @@ -984,11 +984,11 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, library.injectVersionSymbol(ctx, outputFile, versionedOutputFile) } else { versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName) - library.distFile = android.OptionalPathForPath(versionedOutputFile) + library.distFile = versionedOutputFile if library.stripper.needsStrip(ctx) { out := android.PathForModuleOut(ctx, "versioned-stripped", fileName) - library.distFile = android.OptionalPathForPath(out) + library.distFile = out library.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags) } diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go index 8453413c7..ffe502a96 100644 --- a/cmd/soong_ui/main.go +++ b/cmd/soong_ui/main.go @@ -174,7 +174,6 @@ func main() { met := metrics.New() met.SetBuildDateTime(buildStarted) - met.SetBuildCommand(os.Args) stat := &status.Status{} defer stat.Finish() diff --git a/java/Android.bp b/java/Android.bp index 1fda7f71d..f9ef5511d 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -57,6 +57,7 @@ bootstrap_go_package { "device_host_converter_test.go", "dexpreopt_test.go", "dexpreopt_bootjars_test.go", + "hiddenapi_singleton_test.go", "java_test.go", "jdeps_test.go", "kotlin_test.go", diff --git a/java/androidmk.go b/java/androidmk.go index ae257d7ad..413988eab 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -91,7 +91,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { } else { mainEntries = android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", - DistFile: android.OptionalPathForPath(library.distFile), + DistFiles: library.distFiles, OutputFile: android.OptionalPathForPath(library.outputFile), Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ @@ -127,8 +127,11 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...) } - if library.proguardDictionary != nil { - entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary) + if library.dexer.proguardDictionary.Valid() { + entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.dexer.proguardDictionary.Path()) + } + if library.proguardUsageZip.Valid() { + entries.SetPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", library.proguardUsageZip.Path()) } entries.SetString("LOCAL_MODULE_STEM", library.Stem()) @@ -148,9 +151,9 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { func testSuiteComponent(entries *android.AndroidMkEntries, test_suites []string) { entries.SetString("LOCAL_MODULE_TAGS", "tests") if len(test_suites) > 0 { - entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", test_suites...) + entries.AddCompatibilityTestSuites(test_suites...) } else { - entries.SetString("LOCAL_COMPATIBILITY_SUITE", "null-suite") + entries.AddCompatibilityTestSuites("null-suite") } } @@ -196,7 +199,7 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries { entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable)) entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile) entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile) - entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion().raw) + entries.SetString("LOCAL_SDK_VERSION", prebuilt.makeSdkVersion()) entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem()) }, }, @@ -332,8 +335,11 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { if app.jacocoReportClassesFile != nil { entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", app.jacocoReportClassesFile) } - if app.proguardDictionary != nil { - entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.proguardDictionary) + if app.dexer.proguardDictionary.Valid() { + entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.dexer.proguardDictionary.Path()) + } + if app.proguardUsageZip.Valid() { + entries.SetPath("LOCAL_SOONG_PROGUARD_USAGE_ZIP", app.proguardUsageZip.Path()) } if app.Name() == "framework-res" { @@ -561,15 +567,21 @@ func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries { // are created in make if only the api txt file is being generated. This is // needed because an invalid output file would prevent the make entries from // being written. + // + // Note that dstubs.apiFile can be also be nil if WITHOUT_CHECKS_API is true. // TODO(b/146727827): Revert when we do not need to generate stubs and API separately. - distFile := android.OptionalPathForPath(dstubs.apiFile) + + var distFiles android.TaggedDistFiles + if dstubs.apiFile != nil { + distFiles = android.MakeDefaultDistFiles(dstubs.apiFile) + } outputFile := android.OptionalPathForPath(dstubs.stubsSrcJar) if !outputFile.Valid() { - outputFile = distFile + outputFile = android.OptionalPathForPath(dstubs.apiFile) } return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", - DistFile: distFile, + DistFiles: distFiles, OutputFile: outputFile, Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ diff --git a/java/androidmk_test.go b/java/androidmk_test.go index 7daa6244f..49cc0358c 100644 --- a/java/androidmk_test.go +++ b/java/androidmk_test.go @@ -156,16 +156,157 @@ func TestDistWithTag(t *testing.T) { } `) - without_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module()) - with_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module()) + withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module()) + withTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module()) - if len(without_tag_entries) != 2 || len(with_tag_entries) != 2 { - t.Errorf("two mk entries per module expected, got %d and %d", len(without_tag_entries), len(with_tag_entries)) + if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 { + t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries)) } - if !with_tag_entries[0].DistFile.Valid() || !strings.Contains(with_tag_entries[0].DistFile.String(), "/javac/foo_with_tag.jar") { - t.Errorf("expected classes.jar DistFile, got %v", with_tag_entries[0].DistFile) + if len(withTagEntries[0].DistFiles[".jar"]) != 1 || + !strings.Contains(withTagEntries[0].DistFiles[".jar"][0].String(), "/javac/foo_with_tag.jar") { + t.Errorf("expected DistFiles to contain classes.jar, got %v", withTagEntries[0].DistFiles) } - if without_tag_entries[0].DistFile.Valid() { - t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile) + if len(withoutTagEntries[0].DistFiles[".jar"]) > 0 { + t.Errorf("did not expect explicit DistFile for .jar tag, got %v", withoutTagEntries[0].DistFiles[".jar"]) + } +} + +func TestDistWithDest(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["my_goal"], + dest: "my/custom/dest/dir", + }, + } + `) + + module := ctx.ModuleForTests("foo", "android_common").Module() + entries := android.AndroidMkEntriesForTest(t, config, "", module) + if len(entries) != 2 { + t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries)) + } + + distStrings := entries[0].GetDistForGoals(module) + + if len(distStrings) != 2 { + t.Errorf("Expected 2 entries for dist: PHONY and dist-for-goals, but got %q", distStrings) + } + + if distStrings[0] != ".PHONY: my_goal\n" { + t.Errorf("Expected .PHONY entry to declare my_goal, but got: %s", distStrings[0]) + } + + if !strings.Contains(distStrings[1], "$(call dist-for-goals,my_goal") || + !strings.Contains(distStrings[1], ".intermediates/foo/android_common/dex/foo.jar:my/custom/dest/dir") { + t.Errorf( + "Expected dist-for-goals entry to contain my_goal and new dest dir, but got: %s", distStrings[1]) + } +} + +func TestDistsWithAllProperties(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["baz"], + }, + dists: [ + { + targets: ["bar"], + tag: ".jar", + dest: "bar.jar", + dir: "bar/dir", + suffix: ".qux", + }, + ] + } + `) + + module := ctx.ModuleForTests("foo", "android_common").Module() + entries := android.AndroidMkEntriesForTest(t, config, "", module) + if len(entries) != 2 { + t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries)) + } + + distStrings := entries[0].GetDistForGoals(module) + + if len(distStrings) != 4 { + t.Errorf("Expected 4 entries for dist: PHONY and dist-for-goals, but got %d", len(distStrings)) + } + + if distStrings[0] != ".PHONY: bar\n" { + t.Errorf("Expected .PHONY entry to declare bar, but got: %s", distStrings[0]) + } + + if !strings.Contains(distStrings[1], "$(call dist-for-goals,bar") || + !strings.Contains( + distStrings[1], + ".intermediates/foo/android_common/javac/foo.jar:bar/dir/bar.qux.jar") { + t.Errorf( + "Expected dist-for-goals entry to contain bar and new dest dir, but got: %s", distStrings[1]) + } + + if distStrings[2] != ".PHONY: baz\n" { + t.Errorf("Expected .PHONY entry to declare baz, but got: %s", distStrings[2]) + } + + if !strings.Contains(distStrings[3], "$(call dist-for-goals,baz") || + !strings.Contains(distStrings[3], ".intermediates/foo/android_common/dex/foo.jar:foo.jar") { + t.Errorf( + "Expected dist-for-goals entry to contain my_other_goal and new dest dir, but got: %s", + distStrings[3]) + } +} + +func TestDistsWithTag(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo_without_tag", + srcs: ["a.java"], + compile_dex: true, + dists: [ + { + targets: ["hi"], + }, + ], + } + java_library { + name: "foo_with_tag", + srcs: ["a.java"], + compile_dex: true, + dists: [ + { + targets: ["hi"], + tag: ".jar", + }, + ], + } + `) + + moduleWithoutTag := ctx.ModuleForTests("foo_without_tag", "android_common").Module() + moduleWithTag := ctx.ModuleForTests("foo_with_tag", "android_common").Module() + + withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithoutTag) + withTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithTag) + + if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 { + t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries)) + } + + distFilesWithoutTag := withoutTagEntries[0].DistFiles + distFilesWithTag := withTagEntries[0].DistFiles + + if len(distFilesWithTag[".jar"]) != 1 || + !strings.Contains(distFilesWithTag[".jar"][0].String(), "/javac/foo_with_tag.jar") { + t.Errorf("expected foo_with_tag's .jar-tagged DistFiles to contain classes.jar, got %v", distFilesWithTag[".jar"]) + } + if len(distFilesWithoutTag[".jar"]) > 0 { + t.Errorf("did not expect foo_without_tag's .jar-tagged DistFiles to contain files, but got %v", distFilesWithoutTag[".jar"]) } } diff --git a/java/app.go b/java/app.go index 2ec27f3df..ff3b8a45f 100755 --- a/java/app.go +++ b/java/app.go @@ -267,6 +267,9 @@ type overridableAppProperties struct { // the logging parent of this app. Logging_parent *string + + // Whether to rename the package in resources to the override name rather than the base name. Defaults to true. + Rename_resources_package *bool } // runtime_resource_overlay properties that can be overridden by override_runtime_resource_overlay @@ -504,10 +507,23 @@ func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool { !a.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs } +func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string { + aaptFlags := []string{"--rename-manifest-package " + packageName} + if renameResourcesPackage { + // Required to rename the package name in the resources table. + aaptFlags = append(aaptFlags, "--rename-resources-package "+packageName) + } + return aaptFlags +} + func (a *AndroidApp) OverriddenManifestPackageName() string { return a.overriddenManifestPackageName } +func (a *AndroidApp) renameResourcesPackage() bool { + return proptools.BoolDefault(a.overridableAppProperties.Rename_resources_package, true) +} + func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis) @@ -540,7 +556,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { if !overridden { manifestPackageName = *a.overridableAppProperties.Package_name } - aaptLinkFlags = append(aaptLinkFlags, "--rename-manifest-package "+manifestPackageName) + aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, a.renameResourcesPackage())...) a.overriddenManifestPackageName = manifestPackageName } @@ -585,11 +601,11 @@ func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path { a.dexpreopter.installPath = a.installPath(ctx) - if a.deviceProperties.Uncompress_dex == nil { + if a.dexProperties.Uncompress_dex == nil { // If the value was not force-set by the user, use reasonable default based on the module. - a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx)) + a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx)) } - a.dexpreopter.uncompressedDex = *a.deviceProperties.Uncompress_dex + a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries() a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx) @@ -922,6 +938,13 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { depsInfo := android.DepNameToDepInfoMap{} a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) { depName := to.Name() + + // Skip dependencies that are only available to APEXes; they are developed with updatability + // in mind and don't need manual approval. + if to.(android.ApexModule).NotAvailableForPlatform() { + return + } + if info, exist := depsInfo[depName]; exist { info.From = append(info.From, from.Name()) info.IsExternal = info.IsExternal && externalDep @@ -1001,8 +1024,8 @@ var _ cc.Coverage = (*AndroidApp)(nil) func AndroidAppFactory() android.Module { module := &AndroidApp{} - module.Module.deviceProperties.Optimize.EnabledByDefault = true - module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true) + module.Module.dexProperties.Optimize.EnabledByDefault = true + module.Module.dexProperties.Optimize.Shrink = proptools.BoolPtr(true) module.Module.properties.Instrument = true module.Module.properties.Installable = proptools.BoolPtr(true) @@ -1119,7 +1142,7 @@ func (a *AndroidTest) OverridablePropertiesDepsMutator(ctx android.BottomUpMutat func AndroidTestFactory() android.Module { module := &AndroidTest{} - module.Module.deviceProperties.Optimize.EnabledByDefault = true + module.Module.dexProperties.Optimize.EnabledByDefault = true module.Module.properties.Instrument = true module.Module.properties.Installable = proptools.BoolPtr(true) @@ -1170,7 +1193,7 @@ func (a *AndroidTestHelperApp) InstallInTestcases() bool { func AndroidTestHelperAppFactory() android.Module { module := &AndroidTestHelperApp{} - module.Module.deviceProperties.Optimize.EnabledByDefault = true + module.Module.dexProperties.Optimize.EnabledByDefault = true module.Module.properties.Installable = proptools.BoolPtr(true) module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) @@ -1775,7 +1798,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC if !overridden { manifestPackageName = *r.overridableProperties.Package_name } - aaptLinkFlags = append(aaptLinkFlags, "--rename-manifest-package "+manifestPackageName) + aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, false)...) } if r.overridableProperties.Target_package_name != nil { aaptLinkFlags = append(aaptLinkFlags, diff --git a/java/app_test.go b/java/app_test.go index 8ef315206..620a8dd75 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1743,52 +1743,125 @@ func TestOverrideAndroidApp(t *testing.T) { base: "foo", package_name: "org.dandroid.bp", } + + override_android_app { + name: "baz_no_rename_resources", + base: "foo", + package_name: "org.dandroid.bp", + rename_resources_package: false, + } + + android_app { + name: "foo_no_rename_resources", + srcs: ["a.java"], + certificate: "expiredkey", + overrides: ["qux"], + rename_resources_package: false, + sdk_version: "current", + } + + override_android_app { + name: "baz_base_no_rename_resources", + base: "foo_no_rename_resources", + package_name: "org.dandroid.bp", + } + + override_android_app { + name: "baz_override_base_rename_resources", + base: "foo_no_rename_resources", + package_name: "org.dandroid.bp", + rename_resources_package: true, + } `) expectedVariants := []struct { - moduleName string - variantName string - apkName string - apkPath string - certFlag string - lineageFlag string - overrides []string - aaptFlag string - logging_parent string + name string + moduleName string + variantName string + apkName string + apkPath string + certFlag string + lineageFlag string + overrides []string + packageFlag string + renameResources bool + logging_parent string }{ { - moduleName: "foo", - variantName: "android_common", - apkPath: "/target/product/test_device/system/app/foo/foo.apk", - certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", - lineageFlag: "", - overrides: []string{"qux"}, - aaptFlag: "", - logging_parent: "", - }, - { - moduleName: "bar", - variantName: "android_common_bar", - apkPath: "/target/product/test_device/system/app/bar/bar.apk", - certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", - lineageFlag: "--lineage lineage.bin", - overrides: []string{"qux", "foo"}, - aaptFlag: "", - logging_parent: "bah", - }, - { - moduleName: "baz", - variantName: "android_common_baz", - apkPath: "/target/product/test_device/system/app/baz/baz.apk", - certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", - lineageFlag: "", - overrides: []string{"qux", "foo"}, - aaptFlag: "--rename-manifest-package org.dandroid.bp", - logging_parent: "", + name: "foo", + moduleName: "foo", + variantName: "android_common", + apkPath: "/target/product/test_device/system/app/foo/foo.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux"}, + packageFlag: "", + renameResources: false, + logging_parent: "", + }, + { + name: "foo", + moduleName: "bar", + variantName: "android_common_bar", + apkPath: "/target/product/test_device/system/app/bar/bar.apk", + certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", + lineageFlag: "--lineage lineage.bin", + overrides: []string{"qux", "foo"}, + packageFlag: "", + renameResources: false, + logging_parent: "bah", + }, + { + name: "foo", + moduleName: "baz", + variantName: "android_common_baz", + apkPath: "/target/product/test_device/system/app/baz/baz.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo"}, + packageFlag: "org.dandroid.bp", + renameResources: true, + logging_parent: "", + }, + { + name: "foo", + moduleName: "baz_no_rename_resources", + variantName: "android_common_baz_no_rename_resources", + apkPath: "/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo"}, + packageFlag: "org.dandroid.bp", + renameResources: false, + logging_parent: "", + }, + { + name: "foo_no_rename_resources", + moduleName: "baz_base_no_rename_resources", + variantName: "android_common_baz_base_no_rename_resources", + apkPath: "/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo_no_rename_resources"}, + packageFlag: "org.dandroid.bp", + renameResources: false, + logging_parent: "", + }, + { + name: "foo_no_rename_resources", + moduleName: "baz_override_base_rename_resources", + variantName: "android_common_baz_override_base_rename_resources", + apkPath: "/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk", + certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", + lineageFlag: "", + overrides: []string{"qux", "foo_no_rename_resources"}, + packageFlag: "org.dandroid.bp", + renameResources: true, + logging_parent: "", }, } for _, expected := range expectedVariants { - variant := ctx.ModuleForTests("foo", expected.variantName) + variant := ctx.ModuleForTests(expected.name, expected.variantName) // Check the final apk name outputs := variant.AllOutputs() @@ -1834,9 +1907,12 @@ func TestOverrideAndroidApp(t *testing.T) { // Check the package renaming flag, if exists. res := variant.Output("package-res.apk") aapt2Flags := res.Args["flags"] - if !strings.Contains(aapt2Flags, expected.aaptFlag) { - t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags) + checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) + expectedPackage := expected.packageFlag + if !expected.renameResources { + expectedPackage = "" } + checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expectedPackage) } } @@ -1973,6 +2049,7 @@ func TestOverrideAndroidTest(t *testing.T) { res := variant.Output("package-res.apk") aapt2Flags := res.Args["flags"] checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) + checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expected.packageFlag) checkAapt2LinkFlag(t, aapt2Flags, "rename-instrumentation-target-package", expected.targetPackageFlag) } } @@ -3190,6 +3267,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { res := variant.Output("package-res.apk") aapt2Flags := res.Args["flags"] checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) + checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "") checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag) } } diff --git a/java/dex.go b/java/dex.go index 10db1d333..a0a313d69 100644 --- a/java/dex.go +++ b/java/dex.go @@ -24,6 +24,61 @@ import ( "android/soong/remoteexec" ) +type DexProperties struct { + // If set to true, compile dex regardless of installable. Defaults to false. + Compile_dex *bool + + // list of module-specific flags that will be used for dex compiles + Dxflags []string `android:"arch_variant"` + + Optimize struct { + // If false, disable all optimization. Defaults to true for android_app and android_test + // modules, false for java_library and java_test modules. + Enabled *bool + // True if the module containing this has it set by default. + EnabledByDefault bool `blueprint:"mutated"` + + // If true, optimize for size by removing unused code. Defaults to true for apps, + // false for libraries and tests. + Shrink *bool + + // If true, optimize bytecode. Defaults to false. + Optimize *bool + + // If true, obfuscate bytecode. Defaults to false. + Obfuscate *bool + + // If true, do not use the flag files generated by aapt that automatically keep + // classes referenced by the app manifest. Defaults to false. + No_aapt_flags *bool + + // Flags to pass to proguard. + Proguard_flags []string + + // Specifies the locations of files containing proguard flags. + Proguard_flags_files []string `android:"path"` + } + + // Keep the data uncompressed. We always need uncompressed dex for execution, + // so this might actually save space by avoiding storing the same data twice. + // This defaults to reasonable value based on module and should not be set. + // It exists only to support ART tests. + Uncompress_dex *bool +} + +type dexer struct { + dexProperties DexProperties + + // list of extra proguard flag files + extraProguardFlagFiles android.Paths + proguardDictionary android.OptionalPath + proguardUsageZip android.OptionalPath +} + +func (d *dexer) effectiveOptimizeEnabled() bool { + return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault) +} + var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + @@ -55,13 +110,17 @@ var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8", var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `rm -f "$outDict" && ` + + `rm -f "$outDict" && rm -rf "${outUsageDir}" && ` + + `mkdir -p $$(dirname ${outUsage}) && ` + `$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` + `--force-proguard-compatibility ` + `--no-data-resources ` + - `-printmapping $outDict ` + + `-printmapping ${outDict} ` + + `-printusage ${outUsage} ` + `$r8Flags && ` + - `touch "$outDict" && ` + + `touch "${outDict}" "${outUsage}" && ` + + `${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` + + `rm -rf ${outUsageDir} && ` + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ @@ -84,10 +143,18 @@ var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8", ExecStrategy: "${config.RER8ExecStrategy}", Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, }, - }, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"}) + "$zipUsageTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "${outUsage}"}, + OutputFiles: []string{"${outUsageZip}"}, + ExecStrategy: "${config.RER8ExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + }, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir", + "r8Flags", "zipFlags"}, []string{"implicits"}) -func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string { - flags := j.deviceProperties.Dxflags +func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion sdkSpec) []string { + flags := d.dexProperties.Dxflags // Translate all the DX flags to D8 ones until all the build files have been migrated // to D8 flags. See: b/69377755 flags = android.RemoveListFromList(flags, @@ -103,30 +170,27 @@ func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string { "--verbose") } - minSdkVersion, err := j.minSdkVersion().effectiveVersion(ctx) + effectiveVersion, err := minSdkVersion.effectiveVersion(ctx) if err != nil { ctx.PropertyErrorf("min_sdk_version", "%s", err) } - flags = append(flags, "--min-api "+minSdkVersion.asNumberString()) + flags = append(flags, "--min-api "+effectiveVersion.asNumberString()) return flags } -func (j *Module) d8Flags(ctx android.ModuleContext, flags javaBuilderFlags) ([]string, android.Paths) { - d8Flags := j.dexCommonFlags(ctx) - +func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) { d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...) d8Flags = append(d8Flags, flags.classpath.FormRepeatedClassPath("--lib ")...) - var d8Deps android.Paths d8Deps = append(d8Deps, flags.bootClasspath...) d8Deps = append(d8Deps, flags.classpath...) return d8Flags, d8Deps } -func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) { - opt := j.deviceProperties.Optimize +func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) { + opt := d.dexProperties.Optimize // When an app contains references to APIs that are not in the SDK specified by // its LOCAL_SDK_VERSION for example added by support library or by runtime @@ -140,8 +204,6 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F proguardRaiseDeps = append(proguardRaiseDeps, dep.(Dependency).HeaderJars()...) }) - r8Flags = append(r8Flags, j.dexCommonFlags(ctx)...) - r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars")) r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars")) r8Flags = append(r8Flags, flags.classpath.FormJavaClassPath("-libraryjars")) @@ -154,15 +216,10 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F android.PathForSource(ctx, "build/make/core/proguard.flags"), } - if j.shouldInstrumentStatic(ctx) { - flagFiles = append(flagFiles, - android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags")) - } - - flagFiles = append(flagFiles, j.extraProguardFlagFiles...) + flagFiles = append(flagFiles, d.extraProguardFlagFiles...) // TODO(ccross): static android library proguard files - flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, j.deviceProperties.Optimize.Proguard_flags_files)...) + flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...) r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include ")) r8Deps = append(r8Deps, flagFiles...) @@ -171,7 +228,7 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F r8Deps = append(r8Deps, android.PathForSource(ctx, "build/make/core/proguard_basic_keeps.flags")) - r8Flags = append(r8Flags, j.deviceProperties.Optimize.Proguard_flags...) + r8Flags = append(r8Flags, opt.Proguard_flags...) // TODO(ccross): Don't shrink app instrumentation tests by default. if !Bool(opt.Shrink) { @@ -197,46 +254,55 @@ func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8F return r8Flags, r8Deps } -func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, +func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, minSdkVersion sdkSpec, classesJar android.Path, jarName string) android.ModuleOutPath { - useR8 := j.deviceProperties.EffectiveOptimizeEnabled() - // Compile classes.jar into classes.dex and then javalib.jar javalibJar := android.PathForModuleOut(ctx, "dex", jarName) outDir := android.PathForModuleOut(ctx, "dex") zipFlags := "--ignore_missing_files" - if proptools.Bool(j.deviceProperties.Uncompress_dex) { + if proptools.Bool(d.dexProperties.Uncompress_dex) { zipFlags += " -L 0" } + commonFlags := d.dexCommonFlags(ctx, minSdkVersion) + + useR8 := d.effectiveOptimizeEnabled() if useR8 { proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary") - j.proguardDictionary = proguardDictionary - r8Flags, r8Deps := j.r8Flags(ctx, flags) + d.proguardDictionary = android.OptionalPathForPath(proguardDictionary) + proguardUsageDir := android.PathForModuleOut(ctx, "proguard_usage") + proguardUsage := proguardUsageDir.Join(ctx, ctx.Namespace().Path, + android.ModuleNameWithPossibleOverride(ctx), "unused.txt") + proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip") + d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip) + r8Flags, r8Deps := d.r8Flags(ctx, flags) rule := r8 args := map[string]string{ - "r8Flags": strings.Join(r8Flags, " "), - "zipFlags": zipFlags, - "outDict": j.proguardDictionary.String(), - "outDir": outDir.String(), + "r8Flags": strings.Join(append(r8Flags, commonFlags...), " "), + "zipFlags": zipFlags, + "outDict": proguardDictionary.String(), + "outUsageDir": proguardUsageDir.String(), + "outUsage": proguardUsage.String(), + "outUsageZip": proguardUsageZip.String(), + "outDir": outDir.String(), } if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") { rule = r8RE args["implicits"] = strings.Join(r8Deps.Strings(), ",") } ctx.Build(pctx, android.BuildParams{ - Rule: rule, - Description: "r8", - Output: javalibJar, - ImplicitOutput: proguardDictionary, - Input: classesJar, - Implicits: r8Deps, - Args: args, + Rule: rule, + Description: "r8", + Output: javalibJar, + ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip}, + Input: classesJar, + Implicits: r8Deps, + Args: args, }) } else { - d8Flags, d8Deps := j.d8Flags(ctx, flags) + d8Flags, d8Deps := d8Flags(flags) rule := d8 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") { rule = d8RE @@ -248,13 +314,13 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, Input: classesJar, Implicits: d8Deps, Args: map[string]string{ - "d8Flags": strings.Join(d8Flags, " "), + "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "), "zipFlags": zipFlags, "outDir": outDir.String(), }, }) } - if proptools.Bool(j.deviceProperties.Uncompress_dex) { + if proptools.Bool(d.dexProperties.Uncompress_dex) { alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName) TransformZipAlign(ctx, alignedJavalibJar, javalibJar) javalibJar = alignedJavalibJar diff --git a/java/droiddoc.go b/java/droiddoc.go index b564fea01..66eec2cf9 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -191,7 +191,7 @@ type DroiddocProperties struct { // the generated removed Dex API filename by Doclava. Removed_dex_api_filename *string - // if set to false, don't allow droiddoc to generate stubs source files. Defaults to true. + // if set to false, don't allow droiddoc to generate stubs source files. Defaults to false. Create_stubs *bool Check_api struct { @@ -857,6 +857,10 @@ func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.Rule } } +func (d *Droiddoc) createStubs() bool { + return BoolDefault(d.properties.Create_stubs, false) +} + func (d *Droiddoc) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.WritablePath) { if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") || apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") || @@ -879,7 +883,7 @@ func (d *Droiddoc) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilde cmd.FlagWithOutput("-removedDexApi ", d.removedDexApiFile) } - if BoolDefault(d.properties.Create_stubs, true) { + if d.createStubs() { cmd.FlagWithArg("-stubs ", stubsDir.String()) } @@ -1510,7 +1514,9 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi cmd.Flag("--no-banner"). Flag("--color"). Flag("--quiet"). - Flag("--format=v2") + Flag("--format=v2"). + FlagWithArg("--repeat-errors-max ", "10"). + FlagWithArg("--hide ", "UnresolvedImport") return cmd } diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 95dd0bb09..e27519be2 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -92,31 +92,34 @@ func (h *hiddenAPISingleton) MakeVars(ctx android.MakeVarsContext) { // stubFlagsRule creates the rule to build hiddenapi-stub-flags.txt out of dex jars from stub modules and boot image // modules. func stubFlagsRule(ctx android.SingletonContext) { - // Public API stubs - publicStubModules := []string{ - "android_stubs_current", + var publicStubModules []string + var systemStubModules []string + var testStubModules []string + var corePlatformStubModules []string + + if ctx.Config().UnbundledBuildUsePrebuiltSdks() { + // Build configuration mandates using prebuilt stub modules + publicStubModules = append(publicStubModules, "sdk_public_current_android") + systemStubModules = append(systemStubModules, "sdk_system_current_android") + testStubModules = append(testStubModules, "sdk_test_current_android") + } else { + // Use stub modules built from source + publicStubModules = append(publicStubModules, "android_stubs_current") + systemStubModules = append(systemStubModules, "android_system_stubs_current") + testStubModules = append(testStubModules, "android_test_stubs_current") } + // We do not have prebuilts of the core platform api yet + corePlatformStubModules = append(corePlatformStubModules, "core.platform.api.stubs") // Add the android.test.base to the set of stubs only if the android.test.base module is on // the boot jars list as the runtime will only enforce hiddenapi access against modules on // that list. - if inList("android.test.base", ctx.Config().BootJars()) && !ctx.Config().UnbundledBuildUsePrebuiltSdks() { - publicStubModules = append(publicStubModules, "android.test.base.stubs") - } - - // System API stubs - systemStubModules := []string{ - "android_system_stubs_current", - } - - // Test API stubs - testStubModules := []string{ - "android_test_stubs_current", - } - - // Core Platform API stubs - corePlatformStubModules := []string{ - "core.platform.api.stubs", + if inList("android.test.base", ctx.Config().BootJars()) { + if ctx.Config().UnbundledBuildUsePrebuiltSdks() { + publicStubModules = append(publicStubModules, "sdk_public_current_android.test.base") + } else { + publicStubModules = append(publicStubModules, "android.test.base.stubs") + } } // Allow products to define their own stubs for custom product jars that apps can use. @@ -163,6 +166,7 @@ func stubFlagsRule(ctx android.SingletonContext) { return } } + bootDexJars = append(bootDexJars, jar) } } diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go new file mode 100644 index 000000000..2010bc97a --- /dev/null +++ b/java/hiddenapi_singleton_test.go @@ -0,0 +1,219 @@ +// Copyright 2020 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 java + +import ( + "android/soong/android" + "fmt" + "strings" + "testing" + + "github.com/google/blueprint/proptools" +) + +func testConfigWithBootJars(bp string, bootJars []string) android.Config { + config := testConfig(nil, bp, nil) + config.TestProductVariables.BootJars = bootJars + return config +} + +func testContextWithHiddenAPI() *android.TestContext { + ctx := testContext() + ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory) + return ctx +} + +func testHiddenAPIWithConfig(t *testing.T, config android.Config) *android.TestContext { + t.Helper() + + ctx := testContextWithHiddenAPI() + + run(t, ctx, config) + return ctx +} + +func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string) (*android.TestContext, android.Config) { + config := testConfigWithBootJars(bp, bootJars) + + return testHiddenAPIWithConfig(t, config), config +} + +func testHiddenAPIUnbundled(t *testing.T, unbundled bool) (*android.TestContext, android.Config) { + config := testConfig(nil, ``, nil) + config.TestProductVariables.Unbundled_build = proptools.BoolPtr(unbundled) + + return testHiddenAPIWithConfig(t, config), config +} + +func TestHiddenAPISingleton(t *testing.T) { + ctx, _ := testHiddenAPIBootJars(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + } + `, []string{"foo"}) + + hiddenAPI := ctx.SingletonForTests("hiddenapi") + hiddenapiRule := hiddenAPI.Rule("hiddenapi") + want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar" + if !strings.Contains(hiddenapiRule.RuleParams.Command, want) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command) + } +} + +func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { + ctx, _ := testHiddenAPIBootJars(t, ` + java_import { + name: "foo", + jars: ["a.jar"], + compile_dex: true, + } + `, []string{"foo"}) + + hiddenAPI := ctx.SingletonForTests("hiddenapi") + hiddenapiRule := hiddenAPI.Rule("hiddenapi") + want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/dex/foo.jar" + if !strings.Contains(hiddenapiRule.RuleParams.Command, want) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command) + } +} + +func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { + ctx, _ := testHiddenAPIBootJars(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + } + + java_import { + name: "foo", + jars: ["a.jar"], + compile_dex: true, + prefer: false, + } + `, []string{"foo"}) + + hiddenAPI := ctx.SingletonForTests("hiddenapi") + hiddenapiRule := hiddenAPI.Rule("hiddenapi") + fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar" + if !strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command) + } + + prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/dex/foo.jar" + if strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) { + t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command) + } +} + +func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { + ctx, _ := testHiddenAPIBootJars(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + } + + java_import { + name: "foo", + jars: ["a.jar"], + compile_dex: true, + prefer: true, + } + `, []string{"foo"}) + + hiddenAPI := ctx.SingletonForTests("hiddenapi") + hiddenapiRule := hiddenAPI.Rule("hiddenapi") + prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/prebuilt_foo/android_common/dex/foo.jar" + if !strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command) + } + + fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar" + if strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) { + t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command) + } +} + +func TestHiddenAPISingletonSdks(t *testing.T) { + testCases := []struct { + name string + unbundledBuild bool + publicStub string + systemStub string + testStub string + corePlatformStub string + }{ + { + name: "testBundled", + unbundledBuild: false, + publicStub: "android_stubs_current", + systemStub: "android_system_stubs_current", + testStub: "android_test_stubs_current", + corePlatformStub: "core.platform.api.stubs", + }, { + name: "testUnbundled", + unbundledBuild: true, + publicStub: "sdk_public_current_android", + systemStub: "sdk_system_current_android", + testStub: "sdk_test_current_android", + corePlatformStub: "core.platform.api.stubs", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ctx, _ := testHiddenAPIUnbundled(t, tc.unbundledBuild) + + hiddenAPI := ctx.SingletonForTests("hiddenapi") + hiddenapiRule := hiddenAPI.Rule("hiddenapi") + wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantPublicStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantPublicStubs, hiddenapiRule.RuleParams.Command) + } + + wantSystemStubs := "--system-stub-classpath=" + generateSdkDexPath(tc.systemStub, tc.unbundledBuild) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantSystemStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantSystemStubs, hiddenapiRule.RuleParams.Command) + } + + wantTestStubs := "--test-stub-classpath=" + generateSdkDexPath(tc.testStub, tc.unbundledBuild) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantTestStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantTestStubs, hiddenapiRule.RuleParams.Command) + } + + wantCorePlatformStubs := "--core-platform-stub-classpath=" + generateDexPath(tc.corePlatformStub) + if !strings.Contains(hiddenapiRule.RuleParams.Command, wantCorePlatformStubs) { + t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", wantCorePlatformStubs, hiddenapiRule.RuleParams.Command) + } + }) + } +} + +func generateDexedPath(subDir, dex, module string) string { + return fmt.Sprintf("%s/.intermediates/%s/android_common/%s/%s.jar", buildDir, subDir, dex, module) +} + +func generateDexPath(module string) string { + return generateDexedPath(module, "dex", module) +} + +func generateSdkDexPath(module string, unbundled bool) string { + if unbundled { + return generateDexedPath("prebuilts/sdk/"+module, "dex", module) + } + return generateDexPath(module) +} diff --git a/java/java.go b/java/java.go index 69826eec3..18def0b18 100644 --- a/java/java.go +++ b/java/java.go @@ -259,9 +259,6 @@ type CompilerProperties struct { } type CompilerDeviceProperties struct { - // list of module-specific flags that will be used for dex compiles - Dxflags []string `android:"arch_variant"` - // if not blank, set to the version of the sdk to compile against. // Defaults to compiling against the current platform. Sdk_version *string @@ -307,37 +304,6 @@ type CompilerDeviceProperties struct { } } - // If set to true, compile dex regardless of installable. Defaults to false. - Compile_dex *bool - - Optimize struct { - // If false, disable all optimization. Defaults to true for android_app and android_test - // modules, false for java_library and java_test modules. - Enabled *bool - // True if the module containing this has it set by default. - EnabledByDefault bool `blueprint:"mutated"` - - // If true, optimize for size by removing unused code. Defaults to true for apps, - // false for libraries and tests. - Shrink *bool - - // If true, optimize bytecode. Defaults to false. - Optimize *bool - - // If true, obfuscate bytecode. Defaults to false. - Obfuscate *bool - - // If true, do not use the flag files generated by aapt that automatically keep - // classes referenced by the app manifest. Defaults to false. - No_aapt_flags *bool - - // Flags to pass to proguard. - Proguard_flags []string - - // Specifies the locations of files containing proguard flags. - Proguard_flags_files []string `android:"path"` - } - // When targeting 1.9 and above, override the modules to use with --system, // otherwise provides defaults libraries to add to the bootclasspath. System_modules *string @@ -351,12 +317,6 @@ type CompilerDeviceProperties struct { // set the name of the output Stem *string - // Keep the data uncompressed. We always need uncompressed dex for execution, - // so this might actually save space by avoiding storing the same data twice. - // This defaults to reasonable value based on module and should not be set. - // It exists only to support ART tests. - Uncompress_dex *bool - IsSDKLibrary bool `blueprint:"mutated"` // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file. @@ -364,10 +324,6 @@ type CompilerDeviceProperties struct { V4_signature *bool } -func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { - return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault) -} - // Functionality common to Module and Import // // It is embedded in Module so its functionality can be used by methods in Module @@ -436,9 +392,6 @@ type Module struct { // output file containing uninstrumented classes that will be instrumented by jacoco jacocoReportClassesFile android.Path - // output file containing mapping of obfuscated names - proguardDictionary android.Path - // output file of the module, which may be a classes jar or a dex jar outputFile android.Path extraOutputFiles android.Paths @@ -454,9 +407,6 @@ type Module struct { compiledJavaSrcs android.Paths compiledSrcJars android.Paths - // list of extra progurad flag files - extraProguardFlagFiles android.Paths - // manifest file to use instead of properties.Manifest overrideManifest android.OptionalPath @@ -483,13 +433,14 @@ type Module struct { extraResources android.Paths hiddenAPI + dexer dexpreopter linter // list of the xref extraction files kytheFiles android.Paths - distFile android.Path + distFiles android.TaggedDistFiles } func (j *Module) addHostProperties() { @@ -503,6 +454,7 @@ func (j *Module) addHostAndDeviceProperties() { j.addHostProperties() j.AddProperties( &j.deviceProperties, + &j.dexer.dexProperties, &j.dexpreoptProperties, &j.linter.properties, ) @@ -515,7 +467,10 @@ func (j *Module) OutputFiles(tag string) (android.Paths, error) { case ".jar": return android.Paths{j.implementationAndResourcesJar}, nil case ".proguard_map": - return android.Paths{j.proguardDictionary}, nil + if j.dexer.proguardDictionary.Valid() { + return android.Paths{j.dexer.proguardDictionary.Path()}, nil + } + return nil, fmt.Errorf("%q was requested, but no output file was found.", tag) default: return nil, fmt.Errorf("unsupported module reference tag %q", tag) } @@ -680,28 +635,32 @@ func (j *Module) AvailableFor(what string) bool { return j.ApexModuleBase.AvailableFor(what) } +func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext sdkContext, d dexer) { + sdkDep := decodeSdkDep(ctx, sdkContext) + if sdkDep.useDefaultLibs { + ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...) + ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules) + if sdkDep.hasFrameworkLibs() { + ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...) + } + } else if sdkDep.useModule { + ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) + ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) + if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { + ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...) + ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...) + } + } + if sdkDep.systemModules != "" { + ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) + } +} + func (j *Module) deps(ctx android.BottomUpMutatorContext) { if ctx.Device() { j.linter.deps(ctx) - sdkDep := decodeSdkDep(ctx, sdkContext(j)) - if sdkDep.useDefaultLibs { - ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...) - ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules) - if sdkDep.hasFrameworkLibs() { - ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...) - } - } else if sdkDep.useModule { - ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) - ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) - if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { - ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...) - ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...) - } - } - if sdkDep.systemModules != "" { - ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) - } + sdkDeps(ctx, sdkContext(j), j.dexer) } syspropPublicStubs := syspropPublicStubs(ctx.Config()) @@ -1590,8 +1549,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Enable dex compilation for the APEX variants, unless it is disabled explicitly if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() { - if j.deviceProperties.Compile_dex == nil { - j.deviceProperties.Compile_dex = proptools.BoolPtr(true) + if j.dexProperties.Compile_dex == nil { + j.dexProperties.Compile_dex = proptools.BoolPtr(true) } if j.deviceProperties.Hostdex == nil { j.deviceProperties.Hostdex = proptools.BoolPtr(true) @@ -1599,20 +1558,27 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } if ctx.Device() && j.hasCode(ctx) && - (Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) { + (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) { + if j.shouldInstrumentStatic(ctx) { + j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles, + android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags")) + } // Dex compilation var dexOutputFile android.ModuleOutPath - dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName) + dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName) if ctx.Failed() { return } configurationName := j.ConfigurationName() primary := configurationName == ctx.ModuleName() + // If the prebuilt is being used rather than the from source, skip this + // module to prevent duplicated classes + primary = primary && !j.IsReplacedByPrebuilt() // Hidden API CSV generation and dex encoding dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile, - proptools.Bool(j.deviceProperties.Uncompress_dex)) + proptools.Bool(j.dexProperties.Uncompress_dex)) // merge dex jar with resources if necessary if j.resourceJar != nil { @@ -1620,7 +1586,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName) TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{}, false, nil, nil) - if *j.deviceProperties.Uncompress_dex { + if *j.dexProperties.Uncompress_dex { combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName) TransformZipAlign(ctx, combinedAlignedJar, combinedJar) dexOutputFile = combinedAlignedJar @@ -1884,18 +1850,9 @@ func (j *Module) IsInstallable() bool { // Java libraries (.jar file) // -type LibraryProperties struct { - Dist struct { - // The tag of the output of this module that should be output. - Tag *string `android:"arch_variant"` - } `android:"arch_variant"` -} - type Library struct { Module - libraryProperties LibraryProperties - InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths) } @@ -1937,11 +1894,11 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.checkSdkVersions(ctx) j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - if j.deviceProperties.Uncompress_dex == nil { + if j.dexProperties.Uncompress_dex == nil { // If the value was not force-set by the user, use reasonable default based on the module. - j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) + j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) } - j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex + j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex j.compile(ctx, nil) exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform() @@ -1954,14 +1911,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.Stem()+".jar", j.outputFile, extraInstallDeps...) } - // Verify Dist.Tag is set to a supported output - if j.libraryProperties.Dist.Tag != nil { - distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag) - if err != nil { - ctx.PropertyErrorf("dist.tag", "%s", err.Error()) - } - j.distFile = distFiles[0] - } + j.distFiles = j.GenerateTaggedDistFiles(ctx) } func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -2079,7 +2029,6 @@ func LibraryFactory() android.Module { module := &Library{} module.addHostAndDeviceProperties() - module.AddProperties(&module.libraryProperties) module.initModuleAndImport(&module.ModuleBase) @@ -2178,6 +2127,7 @@ type JavaTestImport struct { prebuiltTestProperties prebuiltTestProperties testConfig android.Path + dexJarFile android.Path } func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -2476,8 +2426,14 @@ type Import struct { // Functionality common to Module and Import. embeddableInModuleAndImport + hiddenAPI + dexer + properties ImportProperties + // output file containing classes.dex and resources + dexJarFile android.Path + combinedClasspathFile android.Path exportedSdkLibs []string } @@ -2486,10 +2442,22 @@ func (j *Import) sdkVersion() sdkSpec { return sdkSpecFrom(String(j.properties.Sdk_version)) } +func (j *Import) makeSdkVersion() string { + return j.sdkVersion().raw +} + +func (j *Import) systemModules() string { + return "none" +} + func (j *Import) minSdkVersion() sdkSpec { return j.sdkVersion() } +func (j *Import) targetSdkVersion() sdkSpec { + return j.sdkVersion() +} + func (j *Import) MinSdkVersion() string { return j.minSdkVersion().version.String() } @@ -2516,6 +2484,10 @@ func (a *Import) JacocoReportClassesFile() android.Path { func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...) + + if ctx.Device() && Bool(j.dexProperties.Compile_dex) { + sdkDeps(ctx, sdkContext(j), j.dexer) + } } func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -2538,6 +2510,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { // added to the Android manifest. j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + var flags javaBuilderFlags + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -2546,12 +2520,16 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { case Dependency: switch tag { case libTag, staticLibTag: + flags.classpath = append(flags.classpath, dep.HeaderJars()...) // sdk lib names from dependencies are re-exported j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...) + case bootClasspathTag: + flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...) } case SdkLibraryDependency: switch tag { case libTag: + flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) // names of sdk libs that are directly depended are exported j.exportedSdkLibs = append(j.exportedSdkLibs, otherName) } @@ -2563,6 +2541,39 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), jarName, outputFile) } + + // If this is a component library (impl, stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a <uses-library> element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + + if ctx.Device() && Bool(j.dexProperties.Compile_dex) { + sdkDep := decodeSdkDep(ctx, sdkContext(j)) + if sdkDep.invalidVersion { + ctx.AddMissingDependencies(sdkDep.bootclasspath) + ctx.AddMissingDependencies(sdkDep.java9Classpath) + } else if sdkDep.useFiles { + // sdkDep.jar is actually equivalent to turbine header.jar. + flags.classpath = append(flags.classpath, sdkDep.jars...) + } + + // Dex compilation + var dexOutputFile android.ModuleOutPath + dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName) + if ctx.Failed() { + return + } + + configurationName := j.BaseModuleName() + primary := j.Prebuilt().UsePrebuilt() + + // Hidden API CSV generation and dex encoding + dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, outputFile, + proptools.Bool(j.dexProperties.Uncompress_dex)) + + j.dexJarFile = dexOutputFile + } } var _ Dependency = (*Import)(nil) @@ -2593,7 +2604,7 @@ func (j *Import) ImplementationAndResourcesJars() android.Paths { } func (j *Import) DexJar() android.Path { - return nil + return j.dexJarFile } func (j *Import) AidlIncludeDirs() android.Paths { @@ -2652,10 +2663,15 @@ var _ android.PrebuiltInterface = (*Import)(nil) func ImportFactory() android.Module { module := &Import{} - module.AddProperties(&module.properties) + module.AddProperties( + &module.properties, + &module.dexer.dexProperties, + ) module.initModuleAndImport(&module.ModuleBase) + module.dexProperties.Optimize.EnabledByDefault = false + android.InitPrebuiltModule(module, &module.properties.Jars) android.InitApexModule(module) android.InitSdkAwareModule(module) @@ -2854,6 +2870,7 @@ func DefaultsFactory() android.Module { module.AddProperties( &CompilerProperties{}, &CompilerDeviceProperties{}, + &DexProperties{}, &DexpreoptProperties{}, &android.ProtoProperties{}, &aaptProperties{}, diff --git a/java/java_test.go b/java/java_test.go index 8797119b5..29daa67fb 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -138,7 +138,6 @@ func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config } t.Fatalf("missing expected error %q (0 errors are returned)", pattern) - return ctx, config } @@ -486,6 +485,8 @@ func TestPrebuilts(t *testing.T) { java_import { name: "baz", jars: ["b.jar"], + sdk_version: "current", + compile_dex: true, } dex_import { @@ -516,8 +517,10 @@ func TestPrebuilts(t *testing.T) { fooModule := ctx.ModuleForTests("foo", "android_common") javac := fooModule.Rule("javac") combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") - barJar := ctx.ModuleForTests("bar", "android_common").Rule("combineJar").Output - bazJar := ctx.ModuleForTests("baz", "android_common").Rule("combineJar").Output + barModule := ctx.ModuleForTests("bar", "android_common") + barJar := barModule.Rule("combineJar").Output + bazModule := ctx.ModuleForTests("baz", "android_common") + bazJar := bazModule.Rule("combineJar").Output sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output fooLibrary := fooModule.Module().(*Library) @@ -532,6 +535,11 @@ func TestPrebuilts(t *testing.T) { t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String()) } + barDexJar := barModule.Module().(*Import).DexJar() + if barDexJar != nil { + t.Errorf("bar dex jar build path expected to be nil, got %q", barDexJar) + } + if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) { t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String()) } @@ -540,6 +548,12 @@ func TestPrebuilts(t *testing.T) { t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String()) } + bazDexJar := bazModule.Module().(*Import).DexJar().String() + expectedDexJar := buildDir + "/.intermediates/baz/android_common/dex/baz.jar" + if bazDexJar != expectedDexJar { + t.Errorf("baz dex jar build path expected %q, got %q", expectedDexJar, bazDexJar) + } + ctx.ModuleForTests("qux", "android_common").Rule("Cp") } @@ -846,6 +860,110 @@ func TestIncludeSrcs(t *testing.T) { } } +func TestJavaLint(t *testing.T) { + ctx, _ := testJavaWithFS(t, ` + java_library { + name: "foo", + srcs: [ + "a.java", + "b.java", + "c.java", + ], + min_sdk_version: "29", + sdk_version: "system_current", + } + `, map[string][]byte{ + "lint-baseline.xml": nil, + }) + + foo := ctx.ModuleForTests("foo", "android_common") + rule := foo.Rule("lint") + + if !strings.Contains(rule.RuleParams.Command, "--baseline lint-baseline.xml") { + t.Error("did not pass --baseline flag") + } +} + +func TestJavaLintWithoutBaseline(t *testing.T) { + ctx, _ := testJavaWithFS(t, ` + java_library { + name: "foo", + srcs: [ + "a.java", + "b.java", + "c.java", + ], + min_sdk_version: "29", + sdk_version: "system_current", + } + `, map[string][]byte{}) + + foo := ctx.ModuleForTests("foo", "android_common") + rule := foo.Rule("lint") + + if strings.Contains(rule.RuleParams.Command, "--baseline") { + t.Error("passed --baseline flag for non existent file") + } +} + +func TestJavaLintRequiresCustomLintFileToExist(t *testing.T) { + config := testConfig( + nil, + ` + java_library { + name: "foo", + srcs: [ + ], + min_sdk_version: "29", + sdk_version: "system_current", + lint: { + baseline_filename: "mybaseline.xml", + }, + } + `, map[string][]byte{ + "build/soong/java/lint_defaults.txt": nil, + "prebuilts/cmdline-tools/tools/bin/lint": nil, + "prebuilts/cmdline-tools/tools/lib/lint-classpath.jar": nil, + "framework/aidl": nil, + "a.java": nil, + "AndroidManifest.xml": nil, + "build/make/target/product/security": nil, + }) + config.TestAllowNonExistentPaths = false + testJavaErrorWithConfig(t, + "source path \"mybaseline.xml\" does not exist", + config, + ) +} + +func TestJavaLintUsesCorrectBpConfig(t *testing.T) { + ctx, _ := testJavaWithFS(t, ` + java_library { + name: "foo", + srcs: [ + "a.java", + "b.java", + "c.java", + ], + min_sdk_version: "29", + sdk_version: "system_current", + lint: { + error_checks: ["SomeCheck"], + baseline_filename: "mybaseline.xml", + }, + } + `, map[string][]byte{ + "mybaseline.xml": nil, + }) + + foo := ctx.ModuleForTests("foo", "android_common") + rule := foo.Rule("lint") + + if !strings.Contains(rule.RuleParams.Command, "--baseline mybaseline.xml") { + t.Error("did not use the correct file for baseline") + } +} + func TestGeneratedSources(t *testing.T) { ctx, _ := testJavaWithFS(t, ` java_library { @@ -986,8 +1104,13 @@ func TestDroiddoc(t *testing.T) { "bar-doc/a.java": nil, "bar-doc/b.java": nil, }) + barDocModule := ctx.ModuleForTests("bar-doc", "android_common") + barDoc := barDocModule.Rule("javadoc") + notExpected := " -stubs " + if strings.Contains(barDoc.RuleParams.Command, notExpected) { + t.Errorf("bar-doc command contains flag %q to create stubs, but should not", notExpected) + } - barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc") var javaSrcs []string for _, i := range barDoc.Inputs { javaSrcs = append(javaSrcs, i.Base()) @@ -996,7 +1119,7 @@ func TestDroiddoc(t *testing.T) { t.Errorf("inputs of bar-doc must be []string{\"a.java\"}, but was %#v.", javaSrcs) } - aidl := ctx.ModuleForTests("bar-doc", "android_common").Rule("aidl") + aidl := barDocModule.Rule("aidl") if g, w := barDoc.Implicits.Strings(), aidl.Output.String(); !inList(w, g) { t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g) } @@ -1283,6 +1406,12 @@ func TestJavaSdkLibrary(t *testing.T) { libs: ["foo"], sdk_version: "system_29", } + java_library { + name: "baz-module-30", + srcs: ["c.java"], + libs: ["foo"], + sdk_version: "module_30", + } `) // check the existence of the internal modules @@ -1329,6 +1458,13 @@ func TestJavaSdkLibrary(t *testing.T) { "prebuilts/sdk/29/system/foo.jar") } + bazModule30Javac := ctx.ModuleForTests("baz-module-30", "android_common").Rule("javac") + // tests if "baz-module-30" is actually linked to the module 30 stubs lib + if !strings.Contains(bazModule30Javac.Args["classpath"], "prebuilts/sdk/30/module-lib/foo.jar") { + t.Errorf("baz-module-30 javac classpath %v does not contain %q", bazModule30Javac.Args["classpath"], + "prebuilts/sdk/30/module-lib/foo.jar") + } + // test if baz has exported SDK lib names foo and bar to qux qux := ctx.ModuleForTests("qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { diff --git a/java/lint.go b/java/lint.go index 639106793..71197247a 100644 --- a/java/lint.go +++ b/java/lint.go @@ -19,6 +19,8 @@ import ( "sort" "strings" + "github.com/google/blueprint/proptools" + "android/soong/android" ) @@ -46,6 +48,9 @@ type LintProperties struct { // Modules that provide extra lint checks Extra_check_modules []string + + // Name of the file that lint uses as the baseline. Defaults to "lint-baseline.xml". + Baseline_filename *string } } @@ -319,7 +324,7 @@ func (l *linter) lint(ctx android.ModuleContext) { cmd := rule.Command(). Text("("). - Flag("JAVA_OPTS=-Xmx2048m"). + Flag(`JAVA_OPTS=-"Xmx2048m --add-opens java.base/java.util=ALL-UNNAMED"`). FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()). FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath). FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath). @@ -343,6 +348,19 @@ func (l *linter) lint(ctx android.ModuleContext) { cmd.FlagWithArg("--check ", checkOnly) } + if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" { + var lintBaseline android.OptionalPath + if String(l.properties.Lint.Baseline_filename) != "" { + // if manually specified, we require the file to exist + lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename)) + } else { + lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename) + } + if lintBaseline.Valid() { + cmd.FlagWithInput("--baseline ", lintBaseline.Path()) + } + } + cmd.Text("|| (").Text("cat").Input(text).Text("; exit 7)").Text(")") rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String()) diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt index 0786b7c00..2de05b0a0 100644 --- a/java/lint_defaults.txt +++ b/java/lint_defaults.txt @@ -76,3 +76,5 @@ # TODO(b/158390965): remove this when lint doesn't crash --disable_check HardcodedDebugMode + +--warning_check QueryAllPackagesPermission diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go index 999c72f3c..bcc6cc0cf 100644 --- a/java/prebuilt_apis.go +++ b/java/prebuilt_apis.go @@ -34,6 +34,13 @@ func RegisterPrebuiltApisBuildComponents(ctx android.RegistrationContext) { type prebuiltApisProperties struct { // list of api version directories Api_dirs []string + + // The sdk_version of java_import modules generated based on jar files. + // Defaults to "current" + Imports_sdk_version *string + + // If set to true, compile dex for java_import modules. Defaults to false. + Imports_compile_dex *bool } type prebuiltApis struct { @@ -74,18 +81,19 @@ func prebuiltApiModuleName(mctx android.LoadHookContext, module string, scope st return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module } -func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) { +func createImport(mctx android.LoadHookContext, module, scope, apiver, path, sdkVersion string, compileDex bool) { props := struct { Name *string Jars []string Sdk_version *string Installable *bool + Compile_dex *bool }{} props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver)) props.Jars = append(props.Jars, path) - // TODO(hansson): change to scope after migration is done. - props.Sdk_version = proptools.StringPtr("current") + props.Sdk_version = proptools.StringPtr(sdkVersion) props.Installable = proptools.BoolPtr(false) + props.Compile_dex = proptools.BoolPtr(compileDex) mctx.CreateModule(ImportFactory, &props) } @@ -101,10 +109,10 @@ func createFilegroup(mctx android.LoadHookContext, module string, scope string, mctx.CreateModule(android.FileGroupFactory, &filegroupProps) } -func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string { +func getPrebuiltFiles(mctx android.LoadHookContext, p *prebuiltApis, name string) []string { mydir := mctx.ModuleDir() + "/" var files []string - for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs { + for _, apiver := range p.properties.Api_dirs { for _, scope := range []string{"public", "system", "test", "core", "module-lib", "system-server"} { vfiles, err := mctx.GlobWithDeps(mydir+apiver+"/"+scope+"/"+name, nil) if err != nil { @@ -116,16 +124,19 @@ func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string { return files } -func prebuiltSdkStubs(mctx android.LoadHookContext) { +func prebuiltSdkStubs(mctx android.LoadHookContext, p *prebuiltApis) { mydir := mctx.ModuleDir() + "/" // <apiver>/<scope>/<module>.jar - files := getPrebuiltFiles(mctx, "*.jar") + files := getPrebuiltFiles(mctx, p, "*.jar") + + sdkVersion := proptools.StringDefault(p.properties.Imports_sdk_version, "current") + compileDex := proptools.BoolDefault(p.properties.Imports_compile_dex, false) for _, f := range files { // create a Import module for each jar file localPath := strings.TrimPrefix(f, mydir) module, apiver, scope := parseJarPath(localPath) - createImport(mctx, module, scope, apiver, localPath) + createImport(mctx, module, scope, apiver, localPath, sdkVersion, compileDex) } } @@ -140,8 +151,8 @@ func createSystemModules(mctx android.LoadHookContext, apiver string) { mctx.CreateModule(SystemModulesFactory, &props) } -func prebuiltSdkSystemModules(mctx android.LoadHookContext) { - for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs { +func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) { + for _, apiver := range p.properties.Api_dirs { jar := android.ExistentPathForSource(mctx, mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar") if jar.Valid() { @@ -150,10 +161,10 @@ func prebuiltSdkSystemModules(mctx android.LoadHookContext) { } } -func prebuiltApiFiles(mctx android.LoadHookContext) { +func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) { mydir := mctx.ModuleDir() + "/" // <apiver>/<scope>/api/<module>.txt - files := getPrebuiltFiles(mctx, "api/*.txt") + files := getPrebuiltFiles(mctx, p, "api/*.txt") if len(files) == 0 { mctx.ModuleErrorf("no api file found under %q", mydir) @@ -201,10 +212,10 @@ func prebuiltApiFiles(mctx android.LoadHookContext) { } func createPrebuiltApiModules(mctx android.LoadHookContext) { - if _, ok := mctx.Module().(*prebuiltApis); ok { - prebuiltApiFiles(mctx) - prebuiltSdkStubs(mctx) - prebuiltSdkSystemModules(mctx) + if p, ok := mctx.Module().(*prebuiltApis); ok { + prebuiltApiFiles(mctx, p) + prebuiltSdkStubs(mctx, p) + prebuiltSdkSystemModules(mctx, p) } } diff --git a/java/sdk.go b/java/sdk.go index f96ecded4..5a6c53050 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -94,9 +94,9 @@ func (k sdkKind) String() string { case sdkCorePlatform: return "core_platform" case sdkModule: - return "module" + return "module-lib" case sdkSystemServer: - return "system_server" + return "system-server" default: return "invalid" } @@ -215,7 +215,7 @@ func (s sdkSpec) usePrebuilt(ctx android.EarlyModuleContext) bool { return ctx.Config().UnbundledBuildUsePrebuiltSdks() } else if s.version.isNumbered() { // sanity check - if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest { + if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest && s.kind != sdkModule { panic(fmt.Errorf("prebuilt SDK is not not available for sdkKind=%q", s.kind)) return false } diff --git a/java/sdk_library.go b/java/sdk_library.go index f2a509ad2..f26f61c77 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -120,24 +120,23 @@ type apiScope struct { // the prebuilt jar. sdkVersion string - // Extra arguments to pass to droidstubs for this scope. - droidstubsArgs []string + // The annotation that identifies this API level, empty for the public API scope. + annotation string - // The args that must be passed to droidstubs to generate the stubs source - // for this scope. + // Extra arguments to pass to droidstubs for this scope. // - // The stubs source must include the definitions of everything that is in this - // api scope and all the scopes that this one extends. - droidstubsArgsForGeneratingStubsSource []string + // This is not used directly but is used to construct the droidstubsArgs. + extraArgs []string - // The args that must be passed to droidstubs to generate the API for this scope. + // The args that must be passed to droidstubs to generate the API and stubs source + // for this scope, constructed dynamically by initApiScope(). // // The API only includes the additional members that this scope adds over the scope // that it extends. - droidstubsArgsForGeneratingApi []string - - // True if the stubs source and api can be created by the same metalava invocation. - createStubsSourceAndApiTogether bool + // + // The stubs source must include the definitions of everything that is in this + // api scope and all the scopes that this one extends. + droidstubsArgs []string // Whether the api scope can be treated as unstable, and should skip compat checks. unstable bool @@ -174,21 +173,23 @@ func initApiScope(scope *apiScope) *apiScope { // To get the args needed to generate the stubs source append all the args from // this scope and all the scopes it extends as each set of args adds additional // members to the stubs. - var stubsSourceArgs []string - for s := scope; s != nil; s = s.extends { - stubsSourceArgs = append(stubsSourceArgs, s.droidstubsArgs...) + var scopeSpecificArgs []string + if scope.annotation != "" { + scopeSpecificArgs = []string{"--show-annotation", scope.annotation} } - scope.droidstubsArgsForGeneratingStubsSource = stubsSourceArgs + for s := scope; s != nil; s = s.extends { + scopeSpecificArgs = append(scopeSpecificArgs, s.extraArgs...) - // Currently the args needed to generate the API are the same as the args - // needed to add additional members. - apiArgs := scope.droidstubsArgs - scope.droidstubsArgsForGeneratingApi = apiArgs + // Ensure that the generated stubs includes all the API elements from the API scope + // that this scope extends. + if s != scope && s.annotation != "" { + scopeSpecificArgs = append(scopeSpecificArgs, "--show-for-stub-purposes-annotation", s.annotation) + } + } - // If the args needed to generate the stubs and API are the same then they - // can be generated in a single invocation of metalava, otherwise they will - // need separate invocations. - scope.createStubsSourceAndApiTogether = reflect.DeepEqual(stubsSourceArgs, apiArgs) + // Escape any special characters in the arguments. This is needed because droidstubs + // passes these directly to the shell command. + scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs) return scope } @@ -243,23 +244,23 @@ var ( scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { return &module.sdkLibraryProperties.System }, - apiFilePrefix: "system-", - moduleSuffix: ".system", - sdkVersion: "system_current", - droidstubsArgs: []string{"-showAnnotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"}, + apiFilePrefix: "system-", + moduleSuffix: ".system", + sdkVersion: "system_current", + annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)", }) apiScopeTest = initApiScope(&apiScope{ name: "test", - extends: apiScopePublic, + extends: apiScopeSystem, legacyEnabledStatus: (*SdkLibrary).generateTestAndSystemScopesByDefault, scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties { return &module.sdkLibraryProperties.Test }, - apiFilePrefix: "test-", - moduleSuffix: ".test", - sdkVersion: "test_current", - droidstubsArgs: []string{"-showAnnotation android.annotation.TestApi"}, - unstable: true, + apiFilePrefix: "test-", + moduleSuffix: ".test", + sdkVersion: "test_current", + annotation: "android.annotation.TestApi", + unstable: true, }) apiScopeModuleLib = initApiScope(&apiScope{ name: "module-lib", @@ -276,9 +277,7 @@ var ( apiFilePrefix: "module-lib-", moduleSuffix: ".module_lib", sdkVersion: "module_current", - droidstubsArgs: []string{ - "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\)", - }, + annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)", }) apiScopeSystemServer = initApiScope(&apiScope{ name: "system-server", @@ -295,11 +294,11 @@ var ( apiFilePrefix: "system-server-", moduleSuffix: ".system_server", sdkVersion: "system_server_current", - droidstubsArgs: []string{ - "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\) ", - "--hide-annotation android.annotation.Hide", + annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.SYSTEM_SERVER)", + extraArgs: []string{ + "--hide-annotation", "android.annotation.Hide", // com.android.* classes are okay in this interface" - "--hide InternalClasses", + "--hide", "InternalClasses", }, }) allApiScopes = apiScopes{ @@ -981,16 +980,8 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { // Add dependencies to the stubs library ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope)) - // If the stubs source and API cannot be generated together then add an additional dependency on - // the API module. - if apiScope.createStubsSourceAndApiTogether { - // Add a dependency on the stubs source in order to access both stubs source and api information. - ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope)) - } else { - // Add separate dependencies on the creators of the stubs source files and the API. - ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope)) - ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.apiModuleName(apiScope)) - } + // Add a dependency on the stubs source in order to access both stubs source and api information. + ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope)) } if module.requiresRuntimeImplementationLibrary() { @@ -1086,11 +1077,25 @@ func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) stri return ":" + module.BaseModuleName() + "-removed.api." + apiScope.name + ".latest" } +func childModuleVisibility(childVisibility []string) []string { + if childVisibility == nil { + // No child visibility set. The child will use the visibility of the sdk_library. + return nil + } + + // Prepend an override to ignore the sdk_library's visibility, and rely on the child visibility. + var visibility []string + visibility = append(visibility, "//visibility:override") + visibility = append(visibility, childVisibility...) + return visibility +} + // Creates the implementation java library func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) { - moduleNamePtr := proptools.StringPtr(module.BaseModuleName()) + visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility) + props := struct { Name *string Visibility []string @@ -1098,7 +1103,7 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) ConfigurationName *string }{ Name: proptools.StringPtr(module.implLibraryModuleName()), - Visibility: module.sdkLibraryProperties.Impl_library_visibility, + Visibility: visibility, // Set the instrument property to ensure it is instrumented when instrumentation is required. Instrument: true, @@ -1110,6 +1115,7 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) &module.properties, &module.protoProperties, &module.deviceProperties, + &module.dexProperties, &module.dexpreoptProperties, &module.linter.properties, &props, @@ -1149,12 +1155,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext }{} props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) - - // If stubs_library_visibility is not set then the created module will use the - // visibility of this module. - visibility := module.sdkLibraryProperties.Stubs_library_visibility - props.Visibility = visibility - + props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) // sources are generated from the droiddoc props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)} sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) @@ -1174,8 +1175,8 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential // interop with older developer tools that don't support 1.9. props.Java_version = proptools.StringPtr("1.8") - if module.deviceProperties.Compile_dex != nil { - props.Compile_dex = module.deviceProperties.Compile_dex + if module.dexProperties.Compile_dex != nil { + props.Compile_dex = module.dexProperties.Compile_dex } // Dist the class jar artifact for sdk builds. @@ -1191,7 +1192,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext // Creates a droidstubs module that creates stubs source files from the given full source // files and also updates and checks the API specification files. -func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, createStubSources, createApi bool, scopeSpecificDroidstubsArgs []string) { +func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) { props := struct { Name *string Visibility []string @@ -1236,12 +1237,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC // * libs (static_libs/libs) props.Name = proptools.StringPtr(name) - - // If stubs_source_visibility is not set then the created module will use the - // visibility of this module. - visibility := module.sdkLibraryProperties.Stubs_source_visibility - props.Visibility = visibility - + props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility) props.Srcs = append(props.Srcs, module.properties.Srcs...) props.Sdk_version = module.deviceProperties.Sdk_version props.System_modules = module.deviceProperties.System_modules @@ -1280,64 +1276,57 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC } droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) - if !createStubSources { - // Stubs are not required. - props.Generate_stubs = proptools.BoolPtr(false) - } - // Add in scope specific arguments. droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...) props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " ")) - if createApi { - // List of APIs identified from the provided source files are created. They are later - // compared against to the not-yet-released (a.k.a current) list of APIs and to the - // last-released (a.k.a numbered) list of API. - currentApiFileName := apiScope.apiFilePrefix + "current.txt" - removedApiFileName := apiScope.apiFilePrefix + "removed.txt" - apiDir := module.getApiDir() - currentApiFileName = path.Join(apiDir, currentApiFileName) - removedApiFileName = path.Join(apiDir, removedApiFileName) - - // check against the not-yet-release API - props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) - props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) - - if !apiScope.unstable { - // check against the latest released API - latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) - props.Check_api.Last_released.Api_file = latestApiFilegroupName - props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( - module.latestRemovedApiFilegroupName(apiScope)) - props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true) - - if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) { - // Enable api lint. - props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true) - props.Check_api.Api_lint.New_since = latestApiFilegroupName - - // If it exists then pass a lint-baseline.txt through to droidstubs. - baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt") - baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath) - paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil) - if err != nil { - mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err) - } - if len(paths) == 1 { - props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath) - } else if len(paths) != 0 { - mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths) - } + // List of APIs identified from the provided source files are created. They are later + // compared against to the not-yet-released (a.k.a current) list of APIs and to the + // last-released (a.k.a numbered) list of API. + currentApiFileName := apiScope.apiFilePrefix + "current.txt" + removedApiFileName := apiScope.apiFilePrefix + "removed.txt" + apiDir := module.getApiDir() + currentApiFileName = path.Join(apiDir, currentApiFileName) + removedApiFileName = path.Join(apiDir, removedApiFileName) + + // check against the not-yet-release API + props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) + props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) + + if !apiScope.unstable { + // check against the latest released API + latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) + props.Check_api.Last_released.Api_file = latestApiFilegroupName + props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( + module.latestRemovedApiFilegroupName(apiScope)) + props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true) + + if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) { + // Enable api lint. + props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true) + props.Check_api.Api_lint.New_since = latestApiFilegroupName + + // If it exists then pass a lint-baseline.txt through to droidstubs. + baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt") + baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath) + paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil) + if err != nil { + mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err) + } + if len(paths) == 1 { + props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath) + } else if len(paths) != 0 { + mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths) } } + } - // Dist the api txt artifact for sdk builds. - if !Bool(module.sdkLibraryProperties.No_dist) { - props.Dist.Targets = []string{"sdk", "win_sdk"} - props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName())) - props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api")) - } + // Dist the api txt artifact for sdk builds. + if !Bool(module.sdkLibraryProperties.No_dist) { + props.Dist.Targets = []string{"sdk", "win_sdk"} + props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.txt", module.BaseModuleName())) + props.Dist.Dir = proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api")) } mctx.CreateModule(DroidstubsFactory, &props) @@ -1520,22 +1509,8 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont } for _, scope := range generatedScopes { - stubsSourceArgs := scope.droidstubsArgsForGeneratingStubsSource - stubsSourceModuleName := module.stubsSourceModuleName(scope) - - // If the args needed to generate the stubs and API are the same then they - // can be generated in a single invocation of metalava, otherwise they will - // need separate invocations. - if scope.createStubsSourceAndApiTogether { - // Use the stubs source name for legacy reasons. - module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, true, stubsSourceArgs) - } else { - module.createStubsSourcesAndApi(mctx, scope, stubsSourceModuleName, true, false, stubsSourceArgs) - - apiArgs := scope.droidstubsArgsForGeneratingApi - apiName := module.apiModuleName(scope) - module.createStubsSourcesAndApi(mctx, scope, apiName, false, true, apiArgs) - } + // Use the stubs source name for legacy reasons. + module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs) module.createStubsLibrary(mctx, scope) } diff --git a/java/system_modules.go b/java/system_modules.go index 7394fd547..5cc546d2e 100644 --- a/java/system_modules.go +++ b/java/system_modules.go @@ -192,6 +192,7 @@ func (system *SystemModules) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, name+":", "$("+makevar+")") fmt.Fprintln(w, ".PHONY:", name) + // TODO(b/151177513): Licenses: Doesn't go through base_rules. May have to generate meta_lic and meta_module here. }, } } diff --git a/java/testing.go b/java/testing.go index 48e449f34..f373d7718 100644 --- a/java/testing.go +++ b/java/testing.go @@ -46,6 +46,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "prebuilts/sdk/30/public/framework.aidl": nil, "prebuilts/sdk/30/system/android.jar": nil, "prebuilts/sdk/30/system/foo.jar": nil, + "prebuilts/sdk/30/module-lib/android.jar": nil, + "prebuilts/sdk/30/module-lib/foo.jar": nil, "prebuilts/sdk/30/public/core-for-system-modules.jar": nil, "prebuilts/sdk/current/core/android.jar": nil, "prebuilts/sdk/current/public/android.jar": nil, @@ -79,7 +81,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "prebuilts/sdk/30/system/api/bar-removed.txt": nil, "prebuilts/sdk/30/test/api/bar-removed.txt": nil, "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, - "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`), + "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"], imports_sdk_version: "none", imports_compile_dex:true,}`), // For java_sdk_library "api/module-lib-current.txt": nil, @@ -132,6 +134,7 @@ func GatherRequiredDepsForTest() string { srcs: ["a.java"], sdk_version: "none", system_modules: "core-platform-api-stubs-system-modules", + compile_dex: true, } `, extra) } diff --git a/licenses/Android.bp b/licenses/Android.bp new file mode 100644 index 000000000..c70d6bd55 --- /dev/null +++ b/licenses/Android.bp @@ -0,0 +1,1256 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// 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 { + default_visibility: ["//visibility:public"], + default_applicable_licenses: ["Android-Apache-2.0"], +} + +license { + name: "Android-Apache-2.0", + license_kinds: ["SPDX-license-identifier-Apache-2.0"], + copyright_notice: "Copyright (C) The Android Open Source Project", + license_text: ["LICENSE"], +} + +license_kind { + name: "SPDX-license-identifier-0BSD", + conditions: ["unencumbered"], + url: "https://spdx.org/licenses/0BSD", +} + +license_kind { + name: "SPDX-license-identifier-AFL-1.1", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/AFL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-1.2", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/AFL-1.2.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-2.0", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/AFL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-2.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/AFL-2.1.html", +} + +license_kind { + name: "SPDX-license-identifier-AFL-3.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/AFL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/AGPL.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-1.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/AGPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-1.0-only", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/AGPL-1.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-1.0-or-later", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/AGPL-1.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-3.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/AGPL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-3.0-only", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/AGPL-3.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-AGPL-3.0-or-later", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/AGPL-3.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-APSL-1.1", + conditions: [ + "reciprocal", + ], + url: "https://spdx.org/licenses/APSL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-APSL-2.0", + conditions: [ + "reciprocal", + ], + url: "https://spdx.org/licenses/APSL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Apache", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-Apache-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Apache-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Apache-1.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/Apache-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-Apache-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Apache-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-Artistic-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic-1.0-Perl", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-1.0-Perl.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic-1.0-cl8", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-1.0-cl8.html", +} + +license_kind { + name: "SPDX-license-identifier-Artistic-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Artistic-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-BSD-1-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-1-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause-FreeBSD", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause-NetBSD", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-2-Clause-Patent", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-2-Clause-Patent.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-Attribution", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-Attribution.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-Clear", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-Clear.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-LBNL", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-LBNL.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-License", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-License-2014", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-Warranty", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-3-Clause-Open-MPI", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-4-Clause", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-4-Clause.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-4-Clause-UC", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-4-Clause-UC.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-Protection", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-Protection.html", +} + +license_kind { + name: "SPDX-license-identifier-BSD-Source-Code", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSD-Source-Code.html", +} + +license_kind { + name: "SPDX-license-identifier-BSL-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/BSL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Beerware", + conditions: ["notice"], + url: "https://spdx.org/licenses/Beerware.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-2.5", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-3.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-4.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/CC-BY-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC", + conditions: [ + "by_exception_only", + "not_allowed", + ], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-1.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-2.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-2.5", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-3.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-4.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-1.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-2.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-2.5", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-3.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-ND-4.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-1.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-2.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-2.5", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-3.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-NC-SA-4.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-1.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-2.5", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-ND-4.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-ND-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-1.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-2.5", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-2.5.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-4.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/CC-BY-SA-4.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CC-BY-SA-ND", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-CC0-1.0", + conditions: ["unencumbered"], + url: "https://spdx.org/licenses/CC0-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CDDL", + conditions: ["reciprocal"], +} + +license_kind { + name: "SPDX-license-identifier-CDDL-1.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/CDLL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CDDL-1.1", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/CDLL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-CPAL-1.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/CPAL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-CPL-1.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/CPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EPL", + conditions: ["reciprocal"], +} + +license_kind { + name: "SPDX-license-identifier-EPL-1.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/EPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EPL-2.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/EPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EUPL", + conditions: [ + "by_exception_only", + "not_allowed", + ], +} + +license_kind { + name: "SPDX-license-identifier-EUPL-1.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/EUPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EUPL-1.1", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/EUPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-EUPL-1.2", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/EUPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-FSFAP", + conditions: ["notice"], + url: "https://spdx.org/licenses/FSFAP", +} + +license_kind { + name: "SPDX-license-identifier-FTL", + conditions: ["notice"], + url: "https://spdx.org/licenses/FTL.html", +} + +license_kind { + name: "SPDX-license-identifier-GFDL", + conditions: ["by_exception_only"], +} + +license_kind { + name: "SPDX-license-identifier-GPL", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-1.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-1.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-GCC-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-autoconf-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-bison-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-classpath-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-2.0-with-font-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-2.0-with-font-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-with-GCC-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-3.0-with-autoconf-exception", + conditions: ["restricted"], + url: "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-GPL-with-classpath-exception", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-HPND", + conditions: ["notice"], + url: "https://spdx.org/licenses/HPND.html", +} + +license_kind { + name: "SPDX-license-identifier-ICU", + conditions: ["notice"], + url: "https://spdx.org/licenses/ICU.html", +} + +license_kind { + name: "SPDX-license-identifier-ISC", + conditions: ["notice"], + url: "https://spdx.org/licenses/ISC.html", +} + +license_kind { + name: "SPDX-license-identifier-JSON", + conditions: ["notice"], + url: "https://spdx.org/licenses/JSON.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL", + conditions: ["restricted"], +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1+.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1-only.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-2.1-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-2.1-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0+", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0+.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0-only", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0-only.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPL-3.0-or-later", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPL-3.0-or-later.html", +} + +license_kind { + name: "SPDX-license-identifier-LGPLLR", + conditions: ["restricted"], + url: "https://spdx.org/licenses/LGPLLR.html", +} + +license_kind { + name: "SPDX-license-identifier-LPL-1.02", + conditions: ["notice"], + url: "https://spdx.org/licenses/LPL-1.02.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-MIT-0", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-0.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-CMU", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-CMU.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-advertising", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-advertising.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-enna", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-enna.html", +} + +license_kind { + name: "SPDX-license-identifier-MIT-feh", + conditions: ["notice"], + url: "https://spdx.org/licenses/MIT-feh.html", +} + +license_kind { + name: "SPDX-license-identifier-MITNFA", + conditions: ["notice"], + url: "https://spdx.org/licenses/MITNFA.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL", + conditions: ["reciprocal"], +} + +license_kind { + name: "SPDX-license-identifier-MPL-1.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL-1.1", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL-2.0", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-MPL-2.0-no-copyleft-exception", + conditions: ["reciprocal"], + url: "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html", +} + +license_kind { + name: "SPDX-license-identifier-MS-PL", + conditions: ["notice"], + url: "https://spdx.org/licenses/MS-PL.html", +} + +license_kind { + name: "SPDX-license-identifier-MS-RL", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/MS-RL.html", +} + +license_kind { + name: "SPDX-license-identifier-NCSA", + conditions: ["notice"], + url: "https://spdx.org/licenses/NCSA.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL", + conditions: ["by_exception_only"], +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.0", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.0-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.0-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.0-no-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.0-no-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.1", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.1-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.1-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OFL-1.1-no-RFN", + conditions: ["by_exception_only"], + url: "https://spdx.org/licenses/OFL-1.1-no-RFN.html", +} + +license_kind { + name: "SPDX-license-identifier-OpenSSL", + conditions: ["notice"], + url: "https://spdx.org/licenses/OpenSSL.html", +} + +license_kind { + name: "SPDX-license-identifier-PSF-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/PSF-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-SISSL", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/SISSL.html", +} + +license_kind { + name: "SPDX-license-identifier-SISSL-1.2", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/SISSL-1.2.html", +} + +license_kind { + name: "SPDX-license-identifier-SPL-1.0", + conditions: [ + "by_exception_only", + "reciprocal", + ], + url: "https://spdx.org/licenses/SPL-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-SSPL", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/SSPL.html", +} + +license_kind { + name: "SPDX-license-identifier-UPL-1.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/UPL-1.-.html", +} + +license_kind { + name: "SPDX-license-identifier-Unicode-DFS", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-Unicode-DFS-2015", + conditions: ["notice"], + url: "https://spdx.org/licenses/Unicode-DFS-2015.html", +} + +license_kind { + name: "SPDX-license-identifier-Unicode-DFS-2016", + conditions: ["notice"], + url: "https://spdx.org/licenses/Unicode-DFS-2016.html", +} + +license_kind { + name: "SPDX-license-identifier-Unlicense", + conditions: ["unencumbered"], + url: "https://spdx.org/licenses/Unlicense.html", +} + +license_kind { + name: "SPDX-license-identifier-W3C", + conditions: ["notice"], + url: "https://spdx.org/licenses/W3C.html", +} + +license_kind { + name: "SPDX-license-identifier-W3C-19980720", + conditions: ["notice"], + url: "https://spdx.org/licenses/W3C-19980720.html", +} + +license_kind { + name: "SPDX-license-identifier-W3C-20150513", + conditions: ["notice"], + url: "https://spdx.org/licenses/W3C-20150513.html", +} + +license_kind { + name: "SPDX-license-identifier-WTFPL", + conditions: ["notice"], + url: "https://spdx.org/licenses/WTFPL.html", +} + +license_kind { + name: "SPDX-license-identifier-Watcom-1.0", + conditions: [ + "by_exception_only", + "not_allowed", + ], + url: "https://spdx.org/licenses/Watcom-1.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Xnet", + conditions: ["notice"], + url: "https://spdx.org/licenses/Xnet.html", +} + +license_kind { + name: "SPDX-license-identifier-ZPL", + conditions: ["notice"], +} + +license_kind { + name: "SPDX-license-identifier-ZPL-1.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/ZPL-1.1.html", +} + +license_kind { + name: "SPDX-license-identifier-ZPL-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/ZPL-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-ZPL-2.1", + conditions: ["notice"], + url: "https://spdx.org/licenses/ZPL-2.1.html", +} + +license_kind { + name: "SPDX-license-identifier-Zend-2.0", + conditions: ["notice"], + url: "https://spdx.org/licenses/Zend-2.0.html", +} + +license_kind { + name: "SPDX-license-identifier-Zlib", + conditions: ["notice"], + url: "https://spdx.org/licenses/Zlib.html", +} + +license_kind { + name: "SPDX-license-identifier-libtiff", + conditions: ["notice"], + url: "https://spdx.org/licenses/libtiff.html", +} + +// Legacy license kinds -- do not add new references -- use an spdx kind instead. +license_kind { + name: "legacy_unknown", + conditions: ["by_exception_only"], +} + +license_kind { + name: "legacy_unencumbered", + conditions: ["unencumbered"], +} + +license_kind { + name: "legacy_permissive", + conditions: ["permissive"], +} + +license_kind { + name: "legacy_notice", + conditions: ["notice"], +} + +license_kind { + name: "legacy_reciprocal", + conditions: ["reciprocal"], +} + +license_kind { + name: "legacy_restricted", + conditions: ["restricted"], +} + +license_kind { + name: "legacy_by_exception_only", + conditions: ["by_exception_only"], +} + +license_kind { + name: "legacy_not_a_contribution", + conditions: [ + "by_exception_only", + "not_allowed", + ], +} + +license_kind { + name: "legacy_not_allowed", + conditions: [ + "by_exception_only", + "not_allowed", + ], +} + +license_kind { + name: "legacy_proprietary", + conditions: [ + "by_exception_only", + "not_allowed", + "proprietary", + ], +} diff --git a/licenses/LICENSE b/licenses/LICENSE new file mode 100644 index 000000000..dae04065f --- /dev/null +++ b/licenses/LICENSE @@ -0,0 +1,214 @@ + + Copyright (c) The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/python/androidmk.go b/python/androidmk.go index 247b80dc0..648b14d7f 100644 --- a/python/androidmk.go +++ b/python/androidmk.go @@ -16,84 +16,74 @@ package python import ( "android/soong/android" - "fmt" - "io" "path/filepath" "strings" ) type subAndroidMkProvider interface { - AndroidMk(*Module, *android.AndroidMkData) + AndroidMk(*Module, *android.AndroidMkEntries) } -func (p *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) { +func (p *Module) subAndroidMk(entries *android.AndroidMkEntries, obj interface{}) { if p.subAndroidMkOnce == nil { p.subAndroidMkOnce = make(map[subAndroidMkProvider]bool) } if androidmk, ok := obj.(subAndroidMkProvider); ok { if !p.subAndroidMkOnce[androidmk] { p.subAndroidMkOnce[androidmk] = true - androidmk.AndroidMk(p, data) + androidmk.AndroidMk(p, entries) } } } -func (p *Module) AndroidMk() android.AndroidMkData { - ret := android.AndroidMkData{OutputFile: p.installSource} +func (p *Module) AndroidMkEntries() []android.AndroidMkEntries { + entries := android.AndroidMkEntries{OutputFile: p.installSource} - p.subAndroidMk(&ret, p.installer) + p.subAndroidMk(&entries, p.installer) - return ret + return []android.AndroidMkEntries{entries} } -func (p *binaryDecorator) AndroidMk(base *Module, ret *android.AndroidMkData) { - ret.Class = "EXECUTABLES" +func (p *binaryDecorator) AndroidMk(base *Module, entries *android.AndroidMkEntries) { + entries.Class = "EXECUTABLES" - ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { - if len(p.binaryProperties.Test_suites) > 0 { - fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=", - strings.Join(p.binaryProperties.Test_suites, " ")) - } + entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { + entries.AddCompatibilityTestSuites(p.binaryProperties.Test_suites...) }) - base.subAndroidMk(ret, p.pythonInstaller) + base.subAndroidMk(entries, p.pythonInstaller) } -func (p *testDecorator) AndroidMk(base *Module, ret *android.AndroidMkData) { - ret.Class = "NATIVE_TESTS" +func (p *testDecorator) AndroidMk(base *Module, entries *android.AndroidMkEntries) { + entries.Class = "NATIVE_TESTS" - ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { - if len(p.binaryDecorator.binaryProperties.Test_suites) > 0 { - fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=", - strings.Join(p.binaryDecorator.binaryProperties.Test_suites, " ")) - } + entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { + entries.AddCompatibilityTestSuites(p.binaryDecorator.binaryProperties.Test_suites...) if p.testConfig != nil { - fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", - p.testConfig.String()) + entries.SetString("LOCAL_FULL_TEST_CONFIG", p.testConfig.String()) } - if !BoolDefault(p.binaryProperties.Auto_gen_config, true) { - fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true") - } + entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true)) + }) - base.subAndroidMk(ret, p.binaryDecorator.pythonInstaller) + base.subAndroidMk(entries, p.binaryDecorator.pythonInstaller) } -func (installer *pythonInstaller) AndroidMk(base *Module, ret *android.AndroidMkData) { +func (installer *pythonInstaller) AndroidMk(base *Module, entries *android.AndroidMkEntries) { // Soong installation is only supported for host modules. Have Make // installation trigger Soong installation. if base.Target().Os.Class == android.Host { - ret.OutputFile = android.OptionalPathForPath(installer.path) + entries.OutputFile = android.OptionalPathForPath(installer.path) } - ret.Required = append(ret.Required, "libc++") - ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { + entries.Required = append(entries.Required, "libc++") + entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { path, file := filepath.Split(installer.path.ToMakePath().String()) stem := strings.TrimSuffix(file, filepath.Ext(file)) - fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+filepath.Ext(file)) - fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path) - fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem) - fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(installer.androidMkSharedLibs, " ")) - fmt.Fprintln(w, "LOCAL_CHECK_ELF_FILES := false") + entries.SetString("LOCAL_MODULE_SUFFIX", filepath.Ext(file)) + entries.SetString("LOCAL_MODULE_PATH", path) + entries.SetString("LOCAL_MODULE_STEM", stem) + entries.AddStrings("LOCAL_SHARED_LIBRARIES", installer.androidMkSharedLibs...) + entries.SetBool("LOCAL_CHECK_ELF_FILES", false) }) } diff --git a/python/python.go b/python/python.go index 8b912be17..83ce42d02 100644 --- a/python/python.go +++ b/python/python.go @@ -185,7 +185,7 @@ func (p *Module) GetSrcsZip() android.Path { var _ PythonDependency = (*Module)(nil) -var _ android.AndroidMkDataProvider = (*Module)(nil) +var _ android.AndroidMkEntriesProvider = (*Module)(nil) func (p *Module) Init() android.Module { @@ -251,6 +251,18 @@ func (p *Module) HostToolPath() android.OptionalPath { return android.OptionalPathForPath(p.installer.(*binaryDecorator).path) } +func (p *Module) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "": + if outputFile := p.installSource; outputFile.Valid() { + return android.Paths{outputFile.Path()}, nil + } + return android.Paths{}, nil + default: + return nil, fmt.Errorf("unsupported module reference tag %q", tag) + } +} + func (p *Module) isEmbeddedLauncherEnabled(actual_version string) bool { switch actual_version { case pyVersion2: diff --git a/rust/androidmk.go b/rust/androidmk.go index 0fba739a2..758e63fef 100644 --- a/rust/androidmk.go +++ b/rust/androidmk.go @@ -15,10 +15,7 @@ package rust import ( - "fmt" - "io" "path/filepath" - "strings" "android/soong/android" ) @@ -26,14 +23,14 @@ import ( type AndroidMkContext interface { Name() string Target() android.Target - subAndroidMk(*android.AndroidMkData, interface{}) + subAndroidMk(*android.AndroidMkEntries, interface{}) } type subAndroidMkProvider interface { - AndroidMk(AndroidMkContext, *android.AndroidMkData) + AndroidMk(AndroidMkContext, *android.AndroidMkEntries) } -func (mod *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) { +func (mod *Module) subAndroidMk(data *android.AndroidMkEntries, obj interface{}) { if mod.subAndroidMkOnce == nil { mod.subAndroidMkOnce = make(map[subAndroidMkProvider]bool) } @@ -45,27 +42,17 @@ func (mod *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) { } } -func (mod *Module) AndroidMk() android.AndroidMkData { - ret := android.AndroidMkData{ +func (mod *Module) AndroidMkEntries() []android.AndroidMkEntries { + ret := android.AndroidMkEntries{ OutputFile: mod.outputFile, Include: "$(BUILD_SYSTEM)/soong_rust_prebuilt.mk", - Extra: []android.AndroidMkExtraFunc{ - func(w io.Writer, outputFile android.Path) { - if len(mod.Properties.AndroidMkRlibs) > 0 { - fmt.Fprintln(w, "LOCAL_RLIB_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkRlibs, " ")) - } - if len(mod.Properties.AndroidMkDylibs) > 0 { - fmt.Fprintln(w, "LOCAL_DYLIB_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkDylibs, " ")) - } - if len(mod.Properties.AndroidMkProcMacroLibs) > 0 { - fmt.Fprintln(w, "LOCAL_PROC_MACRO_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkProcMacroLibs, " ")) - } - if len(mod.Properties.AndroidMkSharedLibs) > 0 { - fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkSharedLibs, " ")) - } - if len(mod.Properties.AndroidMkStaticLibs) > 0 { - fmt.Fprintln(w, "LOCAL_STATIC_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkStaticLibs, " ")) - } + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(entries *android.AndroidMkEntries) { + entries.AddStrings("LOCAL_RLIB_LIBRARIES", mod.Properties.AndroidMkRlibs...) + entries.AddStrings("LOCAL_DYLIB_LIBRARIES", mod.Properties.AndroidMkDylibs...) + entries.AddStrings("LOCAL_PROC_MACRO_LIBRARIES", mod.Properties.AndroidMkProcMacroLibs...) + entries.AddStrings("LOCAL_SHARED_LIBRARIES", mod.Properties.AndroidMkSharedLibs...) + entries.AddStrings("LOCAL_STATIC_LIBRARIES", mod.Properties.AndroidMkStaticLibs...) }, }, } @@ -74,39 +61,37 @@ func (mod *Module) AndroidMk() android.AndroidMkData { ret.SubName += mod.Properties.SubName - return ret + return []android.AndroidMkEntries{ret} } -func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { +func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) { ctx.subAndroidMk(ret, binary.baseCompiler) + if binary.distFile.Valid() { + ret.DistFiles = android.MakeDefaultDistFiles(binary.distFile.Path()) + } + ret.Class = "EXECUTABLES" - ret.DistFile = binary.distFile - ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { - fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", binary.unstrippedOutputFile.String()) + ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) { + entries.SetPath("LOCAL_SOONG_UNSTRIPPED_BINARY", binary.unstrippedOutputFile) }) } -func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { +func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) { test.binaryDecorator.AndroidMk(ctx, ret) ret.Class = "NATIVE_TESTS" ret.SubName = test.getMutatedModuleSubName(ctx.Name()) - ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { - if len(test.Properties.Test_suites) > 0 { - fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=", - strings.Join(test.Properties.Test_suites, " ")) - } + ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) { + entries.AddCompatibilityTestSuites(test.Properties.Test_suites...) if test.testConfig != nil { - fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=", test.testConfig.String()) - } - if !BoolDefault(test.Properties.Auto_gen_config, true) { - fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true") + entries.SetString("LOCAL_FULL_TEST_CONFIG", test.testConfig.String()) } + entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(test.Properties.Auto_gen_config, true)) }) // TODO(chh): add test data with androidMkWriteTestData(test.data, ctx, ret) } -func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { +func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) { ctx.subAndroidMk(ret, library.baseCompiler) if library.rlib() { @@ -119,33 +104,38 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An ret.Class = "SHARED_LIBRARIES" } - ret.DistFile = library.distFile - ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { + if library.distFile.Valid() { + ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path()) + } + + ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) { if !library.rlib() { - fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", library.unstrippedOutputFile.String()) + entries.SetPath("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile) } }) } -func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { +func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) { ctx.subAndroidMk(ret, procMacro.baseCompiler) ret.Class = "PROC_MACRO_LIBRARIES" - ret.DistFile = procMacro.distFile + if procMacro.distFile.Valid() { + ret.DistFiles = android.MakeDefaultDistFiles(procMacro.distFile.Path()) + } } -func (compiler *baseCompiler) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { +func (compiler *baseCompiler) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) { // Soong installation is only supported for host modules. Have Make // installation trigger Soong installation. if ctx.Target().Os.Class == android.Host { ret.OutputFile = android.OptionalPathForPath(compiler.path) } - ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { + ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) { path, file := filepath.Split(compiler.path.ToMakePath().String()) stem, suffix, _ := android.SplitFileExt(file) - fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix) - fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path) - fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem) + entries.SetString("LOCAL_MODULE_SUFFIX", suffix) + entries.SetString("LOCAL_MODULE_PATH", path) + entries.SetString("LOCAL_MODULE_STEM", stem) }) } diff --git a/scripts/OWNERS b/scripts/OWNERS index 9e97a6011..8751e753f 100644 --- a/scripts/OWNERS +++ b/scripts/OWNERS @@ -1,2 +1,3 @@ per-file system-clang-format,system-clang-format-2 = enh@google.com,smoreland@google.com per-file build-mainline-modules.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com +per-file gen_ndk*.sh = sophiez@google.com, allenhair@google.com diff --git a/scripts/check_do_not_merge.sh b/scripts/check_do_not_merge.sh new file mode 100755 index 000000000..ad6a0a969 --- /dev/null +++ b/scripts/check_do_not_merge.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright (C) 2021 The Android Open Source Project +# +# 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. + +if git show -s --format=%s $1 | grep -qE '(DO NOT MERGE)|(RESTRICT AUTOMERGE)'; then + cat >&2 <<EOF +DO NOT MERGE and RESTRICT AUTOMERGE very often lead to unintended results +and are not allowed to be used in this project. +Please use the Merged-In tag to be more explicit about where this change +should merge to. Google-internal documentation exists at go/merged-in + +If this check is mis-triggering or you know Merged-In is incorrect in this +situation you can bypass this check with \`repo upload --no-verify\`. +EOF + exit 1 +fi diff --git a/scripts/gen_ndk_backedby_apex.sh b/scripts/gen_ndk_backedby_apex.sh new file mode 100755 index 000000000..4abaaba41 --- /dev/null +++ b/scripts/gen_ndk_backedby_apex.sh @@ -0,0 +1,72 @@ +#!/bin/bash -e + +# Copyright 2020 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. + +# Generates NDK API txt file used by Mainline modules. NDK APIs would have value +# "UND" in Ndx column and have suffix "@LIB_NAME" in Name column. +# For example, current line llvm-readelf output is: +# 1: 00000000 0 FUNC GLOBAL DEFAULT UND dlopen@LIBC +# After the parse function below "dlopen" would be write to the output file. +printHelp() { + echo "**************************** Usage Instructions ****************************" + echo "This script is used to generate the Mainline modules backed-by NDK symbols." + echo "" + echo "To run this script use: ./gen_ndk_backed_by_apex.sh \$OUTPUT_FILE_PATH \$NDK_LIB_NAME_LIST \$MODULE_LIB1 \$MODULE_LIB2..." + echo "For example: If output write to /backedby.txt then the command would be:" + echo "./gen_ndk_backed_by_apex.sh /backedby.txt /ndkLibList.txt lib1.so lib2.so" + echo "If the module1 is backing lib1 then the backedby.txt would contains: " + echo "lib1" +} + +contains() { + val="$1" + shift + for x in "$@"; do + if [ "$x" = "$val" ]; then + return 0 + fi + done + return 1 +} + + +genBackedByList() { + out="$1" + shift + ndk_list="$1" + shift + rm -f "$out" + touch "$out" + while IFS= read -r line + do + soFileName=$(echo "$line" | sed 's/\(.*so\).*/\1/') + if [[ ! -z "$soFileName" && "$soFileName" != *"#"* ]] + then + if contains "$soFileName" "$@"; then + echo "$soFileName" >> "$out" + fi + fi + done < "$ndk_list" +} + +if [[ "$1" == "help" ]] +then + printHelp +elif [[ "$#" -lt 2 ]] +then + echo "Wrong argument length. Expecting at least 2 argument representing output path, path to ndk library list, followed by a list of libraries in the Mainline module." +else + genBackedByList "$@" +fi diff --git a/scripts/gen_ndk_usedby_apex.sh b/scripts/gen_ndk_usedby_apex.sh new file mode 100755 index 000000000..0d3ed5a29 --- /dev/null +++ b/scripts/gen_ndk_usedby_apex.sh @@ -0,0 +1,72 @@ +#!/bin/bash -e + +# Copyright 2020 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. + +# Generates NDK API txt file used by Mainline modules. NDK APIs would have value +# "UND" in Ndx column and have suffix "@LIB_NAME" in Name column. +# For example, current line llvm-readelf output is: +# 1: 00000000 0 FUNC GLOBAL DEFAULT UND dlopen@LIBC +# After the parse function below "dlopen" would be write to the output file. +printHelp() { + echo "**************************** Usage Instructions ****************************" + echo "This script is used to generate the Mainline modules used-by NDK symbols." + echo "" + echo "To run this script use: ./ndk_usedby_module.sh \$BINARY_IMAGE_DIRECTORY \$BINARY_LLVM_PATH \$OUTPUT_FILE_PATH" + echo "For example: If all the module image files that you would like to run is under directory '/myModule' and output write to /myModule.txt then the command would be:" + echo "./ndk_usedby_module.sh /myModule \$BINARY_LLVM_PATH /myModule.txt" +} + +parseReadelfOutput() { + while IFS= read -r line + do + if [[ $line = *FUNC*GLOBAL*UND*@* ]] ; + then + echo "$line" | sed -r 's/.*UND (.*@.*)/\1/g' >> "$2" + fi + done < "$1" + echo "" >> "$2" +} + +unzipJarAndApk() { + tmpUnzippedDir="$1"/tmpUnzipped + [[ -e "$tmpUnzippedDir" ]] && rm -rf "$tmpUnzippedDir" + mkdir -p "$tmpUnzippedDir" + find "$1" -name "*.jar" -exec unzip -o {} -d "$tmpUnzippedDir" \; + find "$1" -name "*.apk" -exec unzip -o {} -d "$tmpUnzippedDir" \; + find "$tmpUnzippedDir" -name "*.MF" -exec rm {} \; +} + +lookForExecFile() { + dir="$1" + readelf="$2" + find "$dir" -type f -name "*.so" -exec "$2" --dyn-symbols {} >> "$dir"/../tmpReadelf.txt \; + find "$dir" -type f -perm /111 ! -name "*.so" -exec "$2" --dyn-symbols {} >> "$dir"/../tmpReadelf.txt \; +} + +if [[ "$1" == "help" ]] +then + printHelp +elif [[ "$#" -ne 3 ]] +then + echo "Wrong argument length. Expecting 3 argument representing image file directory, llvm-readelf tool path, output path." +else + unzipJarAndApk "$1" + lookForExecFile "$1" "$2" + tmpReadelfOutput="$1/../tmpReadelf.txt" + [[ -e "$3" ]] && rm "$3" + parseReadelfOutput "$tmpReadelfOutput" "$3" + [[ -e "$tmpReadelfOutput" ]] && rm "$tmpReadelfOutput" + rm -rf "$1/tmpUnzipped" +fi
\ No newline at end of file diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index db395c582..95b57d92e 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -1392,8 +1392,8 @@ sdk_snapshot { .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt .intermediates/myjavalib.stubs.module_lib/android_common/javac/myjavalib.stubs.module_lib.jar -> sdk_library/module-lib/myjavalib-stubs.jar -.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt -.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_removed.txt -> sdk_library/module-lib/myjavalib-removed.txt +.intermediates/myjavalib.stubs.source.module_lib/android_common/myjavalib.stubs.source.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt +.intermediates/myjavalib.stubs.source.module_lib/android_common/myjavalib.stubs.source.module_lib_removed.txt -> sdk_library/module-lib/myjavalib-removed.txt `), checkMergeZips( ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip", diff --git a/sdk/sdk.go b/sdk/sdk.go index cb5a6053d..b9b8199d3 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -291,7 +291,7 @@ func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "FAKE", OutputFile: s.snapshotFile, - DistFile: s.snapshotFile, + DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path()), Include: "$(BUILD_PHONY_PACKAGE)", ExtraFooters: []android.AndroidMkExtraFootersFunc{ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) { diff --git a/sh/Android.bp b/sh/Android.bp index 0f40c5f68..e5ffeefb4 100644 --- a/sh/Android.bp +++ b/sh/Android.bp @@ -5,6 +5,7 @@ bootstrap_go_package { "blueprint", "soong", "soong-android", + "soong-cc", "soong-tradefed", ], srcs: [ diff --git a/sh/sh_binary.go b/sh/sh_binary.go index ab0490ac1..5272d41a7 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -17,11 +17,14 @@ package sh import ( "fmt" "path/filepath" + "sort" "strings" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/cc" "android/soong/tradefed" ) @@ -88,6 +91,20 @@ type TestProperties struct { // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true // explicitly. Auto_gen_config *bool + + // list of binary modules that should be installed alongside the test + Data_bins []string `android:"path,arch_variant"` + + // list of library modules that should be installed alongside the test + Data_libs []string `android:"path,arch_variant"` + + // list of device binary modules that should be installed alongside the test. + // Only available for host sh_test modules. + Data_device_bins []string `android:"path,arch_variant"` + + // list of device library modules that should be installed alongside the test. + // Only available for host sh_test modules. + Data_device_libs []string `android:"path,arch_variant"` } type ShBinary struct { @@ -109,6 +126,8 @@ type ShTest struct { data android.Paths testConfig android.Path + + dataModules map[string]android.Path } func (s *ShBinary) HostToolPath() android.OptionalPath { @@ -190,6 +209,50 @@ func (s *ShBinary) customAndroidMkEntries(entries *android.AndroidMkEntries) { } } +type dependencyTag struct { + blueprint.BaseDependencyTag + name string +} + +var ( + shTestDataBinsTag = dependencyTag{name: "dataBins"} + shTestDataLibsTag = dependencyTag{name: "dataLibs"} + shTestDataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"} + shTestDataDeviceLibsTag = dependencyTag{name: "dataDeviceLibs"} +) + +var sharedLibVariations = []blueprint.Variation{{Mutator: "link", Variation: "shared"}} + +func (s *ShTest) DepsMutator(ctx android.BottomUpMutatorContext) { + s.ShBinary.DepsMutator(ctx) + + ctx.AddFarVariationDependencies(ctx.Target().Variations(), shTestDataBinsTag, s.testProperties.Data_bins...) + ctx.AddFarVariationDependencies(append(ctx.Target().Variations(), sharedLibVariations...), + shTestDataLibsTag, s.testProperties.Data_libs...) + if ctx.Target().Os.Class == android.Host && len(ctx.Config().Targets[android.Android]) > 0 { + deviceVariations := ctx.Config().Targets[android.Android][0].Variations() + ctx.AddFarVariationDependencies(deviceVariations, shTestDataDeviceBinsTag, s.testProperties.Data_device_bins...) + ctx.AddFarVariationDependencies(append(deviceVariations, sharedLibVariations...), + shTestDataDeviceLibsTag, s.testProperties.Data_device_libs...) + } else if ctx.Target().Os.Class != android.Host { + if len(s.testProperties.Data_device_bins) > 0 { + ctx.PropertyErrorf("data_device_bins", "only available for host modules") + } + if len(s.testProperties.Data_device_libs) > 0 { + ctx.PropertyErrorf("data_device_libs", "only available for host modules") + } + } +} + +func (s *ShTest) addToDataModules(ctx android.ModuleContext, relPath string, path android.Path) { + if _, exists := s.dataModules[relPath]; exists { + ctx.ModuleErrorf("data modules have a conflicting installation path, %v - %s, %s", + relPath, s.dataModules[relPath].String(), path.String()) + return + } + s.dataModules[relPath] = path +} + func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { s.ShBinary.generateAndroidBuildActions(ctx) testDir := "nativetest" @@ -215,6 +278,43 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { } s.testConfig = tradefed.AutoGenShellTestConfig(ctx, s.testProperties.Test_config, s.testProperties.Test_config_template, s.testProperties.Test_suites, configs, s.testProperties.Auto_gen_config, s.outputFilePath.Base()) + + s.dataModules = make(map[string]android.Path) + ctx.VisitDirectDeps(func(dep android.Module) { + depTag := ctx.OtherModuleDependencyTag(dep) + switch depTag { + case shTestDataBinsTag, shTestDataDeviceBinsTag: + path := android.OutputFileForModule(ctx, dep, "") + s.addToDataModules(ctx, path.Base(), path) + case shTestDataLibsTag, shTestDataDeviceLibsTag: + if cc, isCc := dep.(*cc.Module); isCc { + // Copy to an intermediate output directory to append "lib[64]" to the path, + // so that it's compatible with the default rpath values. + var relPath string + if cc.Arch().ArchType.Multilib == "lib64" { + relPath = filepath.Join("lib64", cc.OutputFile().Path().Base()) + } else { + relPath = filepath.Join("lib", cc.OutputFile().Path().Base()) + } + if _, exist := s.dataModules[relPath]; exist { + return + } + relocatedLib := android.PathForModuleOut(ctx, "relocated", relPath) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: cc.OutputFile().Path(), + Output: relocatedLib, + }) + s.addToDataModules(ctx, relPath, relocatedLib) + return + } + property := "data_libs" + if depTag == shTestDataDeviceBinsTag { + property = "data_device_libs" + } + ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep)) + } + }) } func (s *ShTest) InstallInData() bool { @@ -229,8 +329,7 @@ func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries { ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(entries *android.AndroidMkEntries) { s.customAndroidMkEntries(entries) - - entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...) + entries.AddCompatibilityTestSuites(s.testProperties.Test_suites...) if s.testConfig != nil { entries.SetPath("LOCAL_FULL_TEST_CONFIG", s.testConfig) } @@ -243,6 +342,15 @@ func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries { path = strings.TrimSuffix(path, rel) entries.AddStrings("LOCAL_TEST_DATA", path+":"+rel) } + relPaths := make([]string, 0) + for relPath, _ := range s.dataModules { + relPaths = append(relPaths, relPath) + } + sort.Strings(relPaths) + for _, relPath := range relPaths { + dir := strings.TrimSuffix(s.dataModules[relPath].String(), relPath) + entries.AddStrings("LOCAL_TEST_DATA", dir+":"+relPath) + } }, }, }} diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go index 6c0d96abe..232a28133 100644 --- a/sh/sh_binary_test.go +++ b/sh/sh_binary_test.go @@ -3,10 +3,12 @@ package sh import ( "io/ioutil" "os" + "path/filepath" "reflect" "testing" "android/soong/android" + "android/soong/cc" ) var buildDir string @@ -46,6 +48,9 @@ func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config ctx := android.NewTestArchContext() ctx.RegisterModuleType("sh_test", ShTestFactory) ctx.RegisterModuleType("sh_test_host", ShTestHostFactory) + + cc.RegisterRequiredBuildComponentsForTest(ctx) + ctx.Register(config) _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) android.FailIfErrored(t, errs) @@ -78,6 +83,65 @@ func TestShTestTestData(t *testing.T) { } } +func TestShTest_dataModules(t *testing.T) { + ctx, config := testShBinary(t, ` + sh_test { + name: "foo", + src: "test.sh", + host_supported: true, + data_bins: ["bar"], + data_libs: ["libbar"], + } + + cc_binary { + name: "bar", + host_supported: true, + shared_libs: ["libbar"], + no_libcrt: true, + nocrt: true, + system_shared_libs: [], + stl: "none", + } + + cc_library { + name: "libbar", + host_supported: true, + no_libcrt: true, + nocrt: true, + system_shared_libs: [], + stl: "none", + } + `) + + buildOS := android.BuildOs.String() + arches := []string{"android_arm64_armv8-a", buildOS + "_x86_64"} + for _, arch := range arches { + variant := ctx.ModuleForTests("foo", arch) + + libExt := ".so" + if arch == "darwin_x86_64" { + libExt = ".dylib" + } + relocated := variant.Output("relocated/lib64/libbar" + libExt) + expectedInput := filepath.Join(buildDir, ".intermediates/libbar/"+arch+"_shared/libbar"+libExt) + if relocated.Input.String() != expectedInput { + t.Errorf("Unexpected relocation input, expected: %q, actual: %q", + expectedInput, relocated.Input.String()) + } + + mod := variant.Module().(*ShTest) + entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] + expectedData := []string{ + filepath.Join(buildDir, ".intermediates/bar", arch, ":bar"), + filepath.Join(buildDir, ".intermediates/foo", arch, "relocated/:lib64/libbar"+libExt), + } + actualData := entries.EntryMap["LOCAL_TEST_DATA"] + if !reflect.DeepEqual(expectedData, actualData) { + t.Errorf("Unexpected test data, expected: %q, actual: %q", expectedData, actualData) + } + } +} + func TestShTestHost(t *testing.T) { ctx, _ := testShBinary(t, ` sh_test_host { @@ -97,3 +161,53 @@ func TestShTestHost(t *testing.T) { t.Errorf("host bit is not set for a sh_test_host module.") } } + +func TestShTestHost_dataDeviceModules(t *testing.T) { + ctx, config := testShBinary(t, ` + sh_test_host { + name: "foo", + src: "test.sh", + data_device_bins: ["bar"], + data_device_libs: ["libbar"], + } + + cc_binary { + name: "bar", + shared_libs: ["libbar"], + no_libcrt: true, + nocrt: true, + system_shared_libs: [], + stl: "none", + } + + cc_library { + name: "libbar", + no_libcrt: true, + nocrt: true, + system_shared_libs: [], + stl: "none", + } + `) + + buildOS := android.BuildOs.String() + variant := ctx.ModuleForTests("foo", buildOS+"_x86_64") + + relocated := variant.Output("relocated/lib64/libbar.so") + expectedInput := filepath.Join(buildDir, ".intermediates/libbar/android_arm64_armv8-a_shared/libbar.so") + if relocated.Input.String() != expectedInput { + t.Errorf("Unexpected relocation input, expected: %q, actual: %q", + expectedInput, relocated.Input.String()) + } + + mod := variant.Module().(*ShTest) + entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0] + expectedData := []string{ + filepath.Join(buildDir, ".intermediates/bar/android_arm64_armv8-a/:bar"), + // libbar has been relocated, and so has a variant that matches the host arch. + filepath.Join(buildDir, ".intermediates/foo/"+buildOS+"_x86_64/relocated/:lib64/libbar.so"), + } + actualData := entries.EntryMap["LOCAL_TEST_DATA"] + if !reflect.DeepEqual(expectedData, actualData) { + t.Errorf("Unexpected test data, expected: %q, actual: %q", expectedData, actualData) + } +} diff --git a/tradefed/Android.bp b/tradefed/Android.bp index 6e5e5330e..f4e8334f0 100644 --- a/tradefed/Android.bp +++ b/tradefed/Android.bp @@ -12,3 +12,20 @@ bootstrap_go_package { ], pluginFor: ["soong_build"], } + +bootstrap_go_package { + name: "soong-suite-harness", + pkgPath: "android/soong/suite_harness", + deps: [ + "blueprint", + "blueprint-pathtools", + "blueprint-proptools", + "soong", + "soong-android", + "soong-java", + ], + srcs: [ + "tradefed_binary.go", + ], + pluginFor: ["soong_build"], +} diff --git a/tradefed/tradefed_binary.go b/tradefed/tradefed_binary.go new file mode 100644 index 000000000..7960fdc88 --- /dev/null +++ b/tradefed/tradefed_binary.go @@ -0,0 +1,164 @@ +// Copyright 2018 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 suite_harness + +import ( + "strings" + + "github.com/google/blueprint" + + "android/soong/android" + "android/soong/java" +) + +var pctx = android.NewPackageContext("android/soong/suite_harness") + +func init() { + android.RegisterModuleType("tradefed_binary_host", tradefedBinaryFactory) + + pctx.Import("android/soong/android") +} + +type TradefedBinaryProperties struct { + Short_name string + Full_name string + Version string + Prepend_platform_version_name bool +} + +// tradefedBinaryFactory creates an empty module for the tradefed_binary module type, +// which is a java_binary with some additional processing in tradefedBinaryLoadHook. +func tradefedBinaryFactory() android.Module { + props := &TradefedBinaryProperties{} + module := java.BinaryHostFactory() + module.AddProperties(props) + android.AddLoadHook(module, tradefedBinaryLoadHook(props)) + + return module +} + +const genSuffix = "-gen" + +// tradefedBinaryLoadHook adds extra resources and libraries to tradefed_binary modules. +func tradefedBinaryLoadHook(tfb *TradefedBinaryProperties) func(ctx android.LoadHookContext) { + return func(ctx android.LoadHookContext) { + genName := ctx.ModuleName() + genSuffix + version := tfb.Version + if tfb.Prepend_platform_version_name { + version = ctx.Config().PlatformVersionName() + tfb.Version + } + + // Create a submodule that generates the test-suite-info.properties file + // and copies DynamicConfig.xml if it is present. + ctx.CreateModule(tradefedBinaryGenFactory, + &TradefedBinaryGenProperties{ + Name: &genName, + Short_name: tfb.Short_name, + Full_name: tfb.Full_name, + Version: version, + }) + + props := struct { + Java_resources []string + Libs []string + }{} + + // Add dependencies required by all tradefed_binary modules. + props.Libs = []string{ + "tradefed", + "tradefed-test-framework", + "loganalysis", + "hosttestlib", + "compatibility-host-util", + } + + // Add the files generated by the submodule created above to the resources. + props.Java_resources = []string{":" + genName} + + ctx.AppendProperties(&props) + + } +} + +type TradefedBinaryGenProperties struct { + Name *string + Short_name string + Full_name string + Version string +} + +type tradefedBinaryGen struct { + android.ModuleBase + + properties TradefedBinaryGenProperties + + gen android.Paths +} + +func tradefedBinaryGenFactory() android.Module { + tfg := &tradefedBinaryGen{} + tfg.AddProperties(&tfg.properties) + android.InitAndroidModule(tfg) + return tfg +} + +func (tfg *tradefedBinaryGen) DepsMutator(android.BottomUpMutatorContext) {} + +var tradefedBinaryGenRule = pctx.StaticRule("tradefedBinaryGenRule", blueprint.RuleParams{ + Command: `rm -f $out && touch $out && ` + + `echo "# This file is auto generated by Android.mk. Do not modify." >> $out && ` + + `echo "build_number = $$(cat ${buildNumberFile})" >> $out && ` + + `echo "target_arch = ${arch}" >> $out && ` + + `echo "name = ${name}" >> $out && ` + + `echo "fullname = ${fullname}" >> $out && ` + + `echo "version = ${version}" >> $out`, +}, "buildNumberFile", "arch", "name", "fullname", "version") + +func (tfg *tradefedBinaryGen) GenerateAndroidBuildActions(ctx android.ModuleContext) { + buildNumberFile := ctx.Config().BuildNumberFile(ctx) + outputFile := android.PathForModuleOut(ctx, "test-suite-info.properties") + ctx.Build(pctx, android.BuildParams{ + Rule: tradefedBinaryGenRule, + Output: outputFile, + OrderOnly: android.Paths{buildNumberFile}, + Args: map[string]string{ + "buildNumberFile": buildNumberFile.String(), + "arch": ctx.Config().DevicePrimaryArchType().String(), + "name": tfg.properties.Short_name, + "fullname": tfg.properties.Full_name, + "version": tfg.properties.Version, + }, + }) + + tfg.gen = append(tfg.gen, outputFile) + + dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml") + if dynamicConfig.Valid() { + outputFile := android.PathForModuleOut(ctx, strings.TrimSuffix(ctx.ModuleName(), genSuffix)+".dynamic") + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: dynamicConfig.Path(), + Output: outputFile, + }) + + tfg.gen = append(tfg.gen, outputFile) + } +} + +func (tfg *tradefedBinaryGen) Srcs() android.Paths { + return append(android.Paths(nil), tfg.gen...) +} + +var _ android.SourceFileProducer = (*tradefedBinaryGen)(nil) diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go index 0bcdccb7b..594aeffd6 100644 --- a/ui/build/cleanbuild.go +++ b/ui/build/cleanbuild.go @@ -131,7 +131,8 @@ func installClean(ctx Context, config Config, what int) { productOut("installer"), productOut("odm"), productOut("sysloader"), - productOut("testcases")) + productOut("testcases"), + productOut("symbols")) } // Since products and build variants (unfortunately) shared the same diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go index ab57ee59b..1018eb31e 100644 --- a/ui/metrics/metrics.go +++ b/ui/metrics/metrics.go @@ -18,7 +18,6 @@ import ( "io/ioutil" "os" "runtime" - "strings" "time" "github.com/golang/protobuf/proto" @@ -139,10 +138,6 @@ func (m *Metrics) SetBuildDateTime(buildTimestamp time.Time) { m.metrics.BuildDateTimestamp = proto.Int64(buildTimestamp.UnixNano() / int64(time.Second)) } -func (m *Metrics) SetBuildCommand(cmd []string) { - m.metrics.BuildCommand = proto.String(strings.Join(cmd, " ")) -} - // exports the output to the file at outputPath func (m *Metrics) Dump(outputPath string) error { // ignore the error if the hostname could not be retrieved as it diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go index a2cfe5d60..5e214a884 100644 --- a/ui/metrics/metrics_proto/metrics.pb.go +++ b/ui/metrics/metrics_proto/metrics.pb.go @@ -200,9 +200,7 @@ type MetricsBase struct { Total *PerfInfo `protobuf:"bytes,21,opt,name=total" json:"total,omitempty"` BuildConfig *BuildConfig `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"` // The hostname of the machine. - Hostname *string `protobuf:"bytes,24,opt,name=hostname" json:"hostname,omitempty"` - // The build command that the user entered to the build system. - BuildCommand *string `protobuf:"bytes,26,opt,name=build_command,json=buildCommand" json:"build_command,omitempty"` + Hostname *string `protobuf:"bytes,24,opt,name=hostname" json:"hostname,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -399,13 +397,6 @@ func (m *MetricsBase) GetHostname() string { return "" } -func (m *MetricsBase) GetBuildCommand() string { - if m != nil && m.BuildCommand != nil { - return *m.BuildCommand - } - return "" -} - type BuildConfig struct { UseGoma *bool `protobuf:"varint,1,opt,name=use_goma,json=useGoma" json:"use_goma,omitempty"` UseRbe *bool `protobuf:"varint,2,opt,name=use_rbe,json=useRbe" json:"use_rbe,omitempty"` @@ -703,65 +694,64 @@ func init() { func init() { proto.RegisterFile("metrics.proto", fileDescriptor_6039342a2ba47b72) } var fileDescriptor_6039342a2ba47b72 = []byte{ - // 951 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xdf, 0x4e, 0xdb, 0x48, - 0x17, 0xaf, 0x49, 0x20, 0xf1, 0x71, 0x92, 0xba, 0x03, 0x15, 0x2e, 0x15, 0xfa, 0x22, 0x7f, 0xdb, - 0x15, 0x17, 0x5b, 0x5a, 0xb1, 0x15, 0xaa, 0x50, 0xb5, 0x12, 0x04, 0x84, 0xba, 0x08, 0x52, 0x0d, - 0xa4, 0x5b, 0xed, 0x5e, 0x58, 0x13, 0x7b, 0x02, 0xee, 0xc6, 0x9e, 0x68, 0x66, 0x5c, 0x2d, 0x0f, - 0xb1, 0x8f, 0xb9, 0xda, 0xd7, 0x58, 0xcd, 0x19, 0xdb, 0x18, 0x29, 0x55, 0x51, 0xef, 0xec, 0xf3, - 0xfb, 0x33, 0xbf, 0x33, 0x9e, 0x39, 0x32, 0xf4, 0x33, 0xae, 0x65, 0x1a, 0xab, 0xdd, 0x85, 0x14, - 0x5a, 0x90, 0x75, 0x25, 0x44, 0x7e, 0x1d, 0x4d, 0x8b, 0x74, 0x9e, 0x44, 0x25, 0x14, 0xfe, 0x0b, - 0xe0, 0x9d, 0xdb, 0xe7, 0x23, 0xa6, 0x38, 0x79, 0x0d, 0x1b, 0x96, 0x90, 0x30, 0xcd, 0x23, 0x9d, - 0x66, 0x5c, 0x69, 0x96, 0x2d, 0x02, 0x67, 0xe8, 0xec, 0xb4, 0x28, 0x41, 0xec, 0x98, 0x69, 0x7e, - 0x55, 0x21, 0xe4, 0x19, 0x74, 0xad, 0x22, 0x4d, 0x82, 0x95, 0xa1, 0xb3, 0xe3, 0xd2, 0x0e, 0xbe, - 0xbf, 0x4f, 0xc8, 0x01, 0x3c, 0x5b, 0xcc, 0x99, 0x9e, 0x09, 0x99, 0x45, 0x5f, 0xb8, 0x54, 0xa9, - 0xc8, 0xa3, 0x58, 0x24, 0x3c, 0x67, 0x19, 0x0f, 0x5a, 0xc8, 0xdd, 0xac, 0x08, 0x1f, 0x2d, 0x3e, - 0x2a, 0x61, 0xf2, 0x02, 0x06, 0x9a, 0xc9, 0x6b, 0xae, 0xa3, 0x85, 0x14, 0x49, 0x11, 0xeb, 0xa0, - 0x8d, 0x82, 0xbe, 0xad, 0x7e, 0xb0, 0x45, 0x92, 0xc0, 0x46, 0x49, 0xb3, 0x21, 0xbe, 0x30, 0x99, - 0xb2, 0x5c, 0x07, 0xab, 0x43, 0x67, 0x67, 0xb0, 0xf7, 0x72, 0x77, 0x49, 0xcf, 0xbb, 0x8d, 0x7e, - 0x77, 0x8f, 0x0c, 0xf2, 0xd1, 0x8a, 0x0e, 0x5a, 0x27, 0x17, 0xa7, 0x94, 0x58, 0xbf, 0x26, 0x40, - 0xc6, 0xe0, 0x95, 0xab, 0x30, 0x19, 0xdf, 0x04, 0x6b, 0x68, 0xfe, 0xe2, 0x9b, 0xe6, 0x87, 0x32, - 0xbe, 0x39, 0xe8, 0x4c, 0x2e, 0xce, 0x2e, 0xc6, 0xbf, 0x5d, 0x50, 0xb0, 0x16, 0xa6, 0x48, 0x76, - 0x61, 0xbd, 0x61, 0x58, 0xa7, 0xee, 0x60, 0x8b, 0x4f, 0xee, 0x88, 0x55, 0x80, 0x9f, 0xa0, 0x8c, - 0x15, 0xc5, 0x8b, 0xa2, 0xa6, 0x77, 0x91, 0xee, 0x5b, 0x64, 0xb4, 0x28, 0x2a, 0xf6, 0x19, 0xb8, - 0x37, 0x42, 0x95, 0x61, 0xdd, 0xef, 0x0a, 0xdb, 0x35, 0x06, 0x18, 0x95, 0x42, 0x1f, 0xcd, 0xf6, - 0xf2, 0xc4, 0x1a, 0xc2, 0x77, 0x19, 0x7a, 0xc6, 0x64, 0x2f, 0x4f, 0xd0, 0x73, 0x13, 0x3a, 0xe8, - 0x29, 0x54, 0xe0, 0x61, 0x0f, 0x6b, 0xe6, 0x75, 0xac, 0x48, 0x58, 0x2e, 0x26, 0x54, 0xc4, 0xff, - 0xd2, 0x92, 0x05, 0x3d, 0x84, 0x3d, 0x0b, 0x9f, 0x98, 0x52, 0xcd, 0x89, 0xa5, 0x50, 0xca, 0x58, - 0xf4, 0xef, 0x38, 0x23, 0x53, 0x1b, 0x2b, 0xf2, 0x23, 0x3c, 0x6e, 0x70, 0x30, 0xf6, 0xc0, 0x1e, - 0x9f, 0x9a, 0x85, 0x41, 0x5e, 0xc2, 0x7a, 0x83, 0x57, 0xb7, 0xf8, 0xd8, 0x6e, 0x6c, 0xcd, 0x6d, - 0xe4, 0x16, 0x85, 0x8e, 0x92, 0x54, 0x06, 0xbe, 0xcd, 0x2d, 0x0a, 0x7d, 0x9c, 0x4a, 0xf2, 0x0b, - 0x78, 0x8a, 0xeb, 0x62, 0x11, 0x69, 0x21, 0xe6, 0x2a, 0x78, 0x32, 0x6c, 0xed, 0x78, 0x7b, 0xdb, - 0x4b, 0xb7, 0xe8, 0x03, 0x97, 0xb3, 0xf7, 0xf9, 0x4c, 0x50, 0x40, 0xc5, 0x95, 0x11, 0x90, 0x03, - 0x70, 0xff, 0x64, 0x3a, 0x8d, 0x64, 0x91, 0xab, 0x80, 0x3c, 0x44, 0xdd, 0x35, 0x7c, 0x5a, 0xe4, - 0x8a, 0xbc, 0x03, 0xb0, 0x4c, 0x14, 0xaf, 0x3f, 0x44, 0xec, 0x22, 0x5a, 0xa9, 0xf3, 0x34, 0xff, - 0xcc, 0xac, 0x7a, 0xe3, 0x41, 0x6a, 0x14, 0xa0, 0xfa, 0x67, 0x58, 0xd5, 0x42, 0xb3, 0x79, 0xf0, - 0x74, 0xe8, 0x7c, 0x5b, 0x68, 0xb9, 0x64, 0x04, 0x3d, 0x4b, 0x88, 0x45, 0x3e, 0x4b, 0xaf, 0x83, - 0x4d, 0xd4, 0x0e, 0x97, 0x6a, 0xf1, 0x1a, 0x8e, 0x90, 0x47, 0xbd, 0xe9, 0xdd, 0x0b, 0xd9, 0x02, - 0x3c, 0xa2, 0x38, 0x4a, 0x02, 0xfc, 0x16, 0xf5, 0x3b, 0xf9, 0x3f, 0xf4, 0xab, 0x05, 0xb2, 0x8c, - 0xe5, 0x49, 0xb0, 0x85, 0x84, 0x5e, 0xa9, 0xc7, 0x5a, 0xf8, 0x1a, 0x7a, 0xf7, 0xee, 0x78, 0x17, - 0xda, 0x93, 0xcb, 0x13, 0xea, 0x3f, 0x22, 0x7d, 0x70, 0xcd, 0xd3, 0xf1, 0xc9, 0xd1, 0xe4, 0xd4, - 0x77, 0x48, 0x07, 0xcc, 0x5c, 0xf0, 0x57, 0xc2, 0x77, 0xd0, 0xc6, 0x53, 0xe0, 0x41, 0x75, 0xaa, - 0xfd, 0x47, 0x06, 0x3d, 0xa4, 0xe7, 0xbe, 0x43, 0x5c, 0x58, 0x3d, 0xa4, 0xe7, 0xfb, 0x6f, 0xfc, - 0x15, 0x53, 0xfb, 0xf4, 0x76, 0xdf, 0x6f, 0x11, 0x80, 0xb5, 0x4f, 0x6f, 0xf7, 0xa3, 0xfd, 0x37, - 0x7e, 0x3b, 0xbc, 0x06, 0xaf, 0xd1, 0x8c, 0x19, 0x9b, 0x85, 0xe2, 0xd1, 0xb5, 0xc8, 0x18, 0x0e, - 0xd7, 0x2e, 0xed, 0x14, 0x8a, 0x9f, 0x8a, 0x8c, 0x99, 0x53, 0x66, 0x20, 0x39, 0xe5, 0x38, 0x50, - 0xbb, 0x74, 0xad, 0x50, 0x9c, 0x4e, 0x39, 0xf9, 0x01, 0x06, 0x33, 0x21, 0x63, 0x1e, 0xd5, 0xca, - 0x16, 0xe2, 0x3d, 0xac, 0x4e, 0xac, 0x3c, 0xfc, 0xdb, 0x81, 0x6e, 0xb5, 0xe5, 0x84, 0x40, 0x3b, - 0xe1, 0x2a, 0xc6, 0x25, 0x5c, 0x8a, 0xcf, 0xa6, 0x86, 0xdb, 0x66, 0xa7, 0x35, 0x3e, 0x93, 0x6d, - 0x00, 0xa5, 0x99, 0xd4, 0x38, 0xf2, 0xd1, 0xb6, 0x4d, 0x5d, 0xac, 0x98, 0x49, 0x4f, 0x9e, 0x83, - 0x2b, 0x39, 0x9b, 0x5b, 0xb4, 0x8d, 0x68, 0xd7, 0x14, 0x10, 0xdc, 0x06, 0xc8, 0x78, 0x26, 0xe4, - 0xad, 0xc9, 0x85, 0x93, 0xb7, 0x4d, 0x5d, 0x5b, 0x99, 0x28, 0x1e, 0xfe, 0xe3, 0xc0, 0xe0, 0x5c, - 0x24, 0xc5, 0x9c, 0x5f, 0xdd, 0x2e, 0x38, 0xa6, 0xfa, 0xa3, 0x3a, 0x01, 0xea, 0x56, 0x69, 0x9e, - 0x61, 0xba, 0xc1, 0xde, 0xab, 0xe5, 0x23, 0xe5, 0x9e, 0xd4, 0x1e, 0x88, 0x4b, 0x94, 0x35, 0x86, - 0xcb, 0xf4, 0xae, 0x4a, 0xfe, 0x07, 0x5e, 0x86, 0x9a, 0x48, 0xdf, 0x2e, 0xaa, 0x2e, 0x21, 0xab, - 0x6d, 0xcc, 0x36, 0xe6, 0x45, 0x16, 0x89, 0x59, 0x64, 0x8b, 0x0a, 0xfb, 0xed, 0xd3, 0x5e, 0x5e, - 0x64, 0xe3, 0x99, 0x5d, 0x4f, 0x85, 0xaf, 0xca, 0xef, 0x55, 0xba, 0xde, 0xfb, 0xe8, 0x2e, 0xac, - 0x5e, 0x8e, 0xc7, 0x17, 0xe6, 0x74, 0x74, 0xa1, 0x7d, 0x7e, 0x78, 0x76, 0xe2, 0xaf, 0x84, 0x73, - 0xd8, 0x1a, 0xc9, 0x54, 0xa7, 0x31, 0x9b, 0x4f, 0x14, 0x97, 0xbf, 0x8a, 0x42, 0xe6, 0xfc, 0xb6, - 0x9c, 0x88, 0xf5, 0xa6, 0x3b, 0x8d, 0x4d, 0x3f, 0x80, 0x4e, 0xd9, 0x25, 0xa6, 0xfc, 0xda, 0x1d, - 0x68, 0x0c, 0x55, 0x5a, 0x09, 0xc2, 0x29, 0x3c, 0x5f, 0xb2, 0x9a, 0xaa, 0x96, 0x1b, 0x41, 0x3b, - 0x2e, 0x3e, 0xab, 0xc0, 0xc1, 0x0b, 0xbd, 0x7c, 0x67, 0xbf, 0x9e, 0x96, 0xa2, 0xf8, 0xe8, 0xe9, - 0xef, 0xe5, 0x3f, 0x43, 0xa9, 0x88, 0xf0, 0x47, 0xe2, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x94, - 0x52, 0xed, 0xc2, 0x58, 0x08, 0x00, 0x00, + // 934 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x6f, 0x6b, 0xdb, 0x46, + 0x18, 0xaf, 0x62, 0x25, 0x96, 0x1e, 0xc5, 0xae, 0x7a, 0x69, 0x89, 0xda, 0x12, 0x66, 0xc4, 0x3a, + 0xf2, 0x62, 0x4d, 0x4b, 0x56, 0x42, 0x09, 0x65, 0x90, 0x38, 0x21, 0x74, 0x21, 0x71, 0xb9, 0xc4, + 0x5d, 0xd9, 0x5e, 0x08, 0x59, 0x3a, 0x3b, 0xea, 0x2c, 0x9d, 0xb9, 0x3b, 0x95, 0xf9, 0x43, 0xec, + 0x4b, 0xed, 0xbb, 0xec, 0x7b, 0x8c, 0x7b, 0x4e, 0x52, 0x14, 0x70, 0x69, 0xe8, 0x3b, 0xe9, 0xf9, + 0xfd, 0xb9, 0xdf, 0x3d, 0x77, 0x7a, 0x10, 0xf4, 0x72, 0xa6, 0x44, 0x96, 0xc8, 0xbd, 0x85, 0xe0, + 0x8a, 0x93, 0x2d, 0xc9, 0x79, 0x31, 0x8b, 0x26, 0x65, 0x36, 0x4f, 0xa3, 0x0a, 0x0a, 0xff, 0x05, + 0xf0, 0x2e, 0xcc, 0xf3, 0x71, 0x2c, 0x19, 0x79, 0x0d, 0x8f, 0x0d, 0x21, 0x8d, 0x15, 0x8b, 0x54, + 0x96, 0x33, 0xa9, 0xe2, 0x7c, 0x11, 0x58, 0x03, 0x6b, 0xb7, 0x43, 0x09, 0x62, 0x27, 0xb1, 0x62, + 0xd7, 0x35, 0x42, 0x9e, 0x82, 0x63, 0x14, 0x59, 0x1a, 0xac, 0x0d, 0xac, 0x5d, 0x97, 0x76, 0xf1, + 0xfd, 0x7d, 0x4a, 0x0e, 0xe1, 0xe9, 0x62, 0x1e, 0xab, 0x29, 0x17, 0x79, 0xf4, 0x85, 0x09, 0x99, + 0xf1, 0x22, 0x4a, 0x78, 0xca, 0x8a, 0x38, 0x67, 0x41, 0x07, 0xb9, 0xdb, 0x35, 0xe1, 0xa3, 0xc1, + 0x87, 0x15, 0x4c, 0x5e, 0x40, 0x5f, 0xc5, 0x62, 0xc6, 0x54, 0xb4, 0x10, 0x3c, 0x2d, 0x13, 0x15, + 0xd8, 0x28, 0xe8, 0x99, 0xea, 0x07, 0x53, 0x24, 0x29, 0x3c, 0xae, 0x68, 0x26, 0xc4, 0x97, 0x58, + 0x64, 0x71, 0xa1, 0x82, 0xf5, 0x81, 0xb5, 0xdb, 0xdf, 0x7f, 0xb9, 0xb7, 0x62, 0xcf, 0x7b, 0xad, + 0xfd, 0xee, 0x1d, 0x6b, 0xe4, 0xa3, 0x11, 0x1d, 0x76, 0x4e, 0x2f, 0xcf, 0x28, 0x31, 0x7e, 0x6d, + 0x80, 0x8c, 0xc0, 0xab, 0x56, 0x89, 0x45, 0x72, 0x13, 0x6c, 0xa0, 0xf9, 0x8b, 0x6f, 0x9a, 0x1f, + 0x89, 0xe4, 0xe6, 0xb0, 0x3b, 0xbe, 0x3c, 0xbf, 0x1c, 0xfd, 0x7e, 0x49, 0xc1, 0x58, 0xe8, 0x22, + 0xd9, 0x83, 0xad, 0x96, 0x61, 0x93, 0xba, 0x8b, 0x5b, 0x7c, 0x74, 0x4b, 0xac, 0x03, 0xfc, 0x0c, + 0x55, 0xac, 0x28, 0x59, 0x94, 0x0d, 0xdd, 0x41, 0xba, 0x6f, 0x90, 0xe1, 0xa2, 0xac, 0xd9, 0xe7, + 0xe0, 0xde, 0x70, 0x59, 0x85, 0x75, 0xbf, 0x2b, 0xac, 0xa3, 0x0d, 0x30, 0x2a, 0x85, 0x1e, 0x9a, + 0xed, 0x17, 0xa9, 0x31, 0x84, 0xef, 0x32, 0xf4, 0xb4, 0xc9, 0x7e, 0x91, 0xa2, 0xe7, 0x36, 0x74, + 0xd1, 0x93, 0xcb, 0xc0, 0xc3, 0x3d, 0x6c, 0xe8, 0xd7, 0x91, 0x24, 0x61, 0xb5, 0x18, 0x97, 0x11, + 0xfb, 0x5b, 0x89, 0x38, 0xd8, 0x44, 0xd8, 0x33, 0xf0, 0xa9, 0x2e, 0x35, 0x9c, 0x44, 0x70, 0x29, + 0xb5, 0x45, 0xef, 0x96, 0x33, 0xd4, 0xb5, 0x91, 0x24, 0x3f, 0xc1, 0xc3, 0x16, 0x07, 0x63, 0xf7, + 0xcd, 0xf5, 0x69, 0x58, 0x18, 0xe4, 0x25, 0x6c, 0xb5, 0x78, 0xcd, 0x16, 0x1f, 0x9a, 0xc6, 0x36, + 0xdc, 0x56, 0x6e, 0x5e, 0xaa, 0x28, 0xcd, 0x44, 0xe0, 0x9b, 0xdc, 0xbc, 0x54, 0x27, 0x99, 0x20, + 0xbf, 0x82, 0x27, 0x99, 0x2a, 0x17, 0x91, 0xe2, 0x7c, 0x2e, 0x83, 0x47, 0x83, 0xce, 0xae, 0xb7, + 0xbf, 0xb3, 0xb2, 0x45, 0x1f, 0x98, 0x98, 0xbe, 0x2f, 0xa6, 0x9c, 0x02, 0x2a, 0xae, 0xb5, 0x80, + 0x1c, 0x82, 0xfb, 0x57, 0xac, 0xb2, 0x48, 0x94, 0x85, 0x0c, 0xc8, 0x7d, 0xd4, 0x8e, 0xe6, 0xd3, + 0xb2, 0x90, 0xe4, 0x1d, 0x80, 0x61, 0xa2, 0x78, 0xeb, 0x3e, 0x62, 0x17, 0xd1, 0x5a, 0x5d, 0x64, + 0xc5, 0xe7, 0xd8, 0xa8, 0x1f, 0xdf, 0x4b, 0x8d, 0x02, 0x54, 0xff, 0x02, 0xeb, 0x8a, 0xab, 0x78, + 0x1e, 0x3c, 0x19, 0x58, 0xdf, 0x16, 0x1a, 0x2e, 0x19, 0xc2, 0xa6, 0x21, 0x24, 0xbc, 0x98, 0x66, + 0xb3, 0x60, 0x1b, 0xb5, 0x83, 0x95, 0x5a, 0xfc, 0x0c, 0x87, 0xc8, 0xa3, 0xde, 0xe4, 0xf6, 0x85, + 0x3c, 0x03, 0xbc, 0xa2, 0x38, 0x4a, 0x02, 0x3c, 0x8b, 0xe6, 0x3d, 0x7c, 0x0d, 0x9b, 0x77, 0x3e, + 0x5f, 0x07, 0xec, 0xf1, 0xd5, 0x29, 0xf5, 0x1f, 0x90, 0x1e, 0xb8, 0xfa, 0xe9, 0xe4, 0xf4, 0x78, + 0x7c, 0xe6, 0x5b, 0xa4, 0x0b, 0xfa, 0x93, 0xf7, 0xd7, 0xc2, 0x77, 0x60, 0xe3, 0x01, 0x7b, 0x50, + 0x5f, 0x58, 0xff, 0x81, 0x46, 0x8f, 0xe8, 0x85, 0x6f, 0x11, 0x17, 0xd6, 0x8f, 0xe8, 0xc5, 0xc1, + 0x1b, 0x7f, 0x4d, 0xd7, 0x3e, 0xbd, 0x3d, 0xf0, 0x3b, 0x04, 0x60, 0xe3, 0xd3, 0xdb, 0x83, 0xe8, + 0xe0, 0x8d, 0x6f, 0x87, 0x33, 0xf0, 0x5a, 0x39, 0xf5, 0x44, 0x2c, 0x25, 0x8b, 0x66, 0x3c, 0x8f, + 0x71, 0x6e, 0x3a, 0xb4, 0x5b, 0x4a, 0x76, 0xc6, 0xf3, 0x58, 0x5f, 0x20, 0x0d, 0x89, 0x09, 0xc3, + 0x59, 0xe9, 0xd0, 0x8d, 0x52, 0x32, 0x3a, 0x61, 0xe4, 0x47, 0xe8, 0x4f, 0xb9, 0x48, 0x58, 0xd4, + 0x28, 0x3b, 0x88, 0x6f, 0x62, 0x75, 0x6c, 0xe4, 0xe1, 0x3f, 0x16, 0x38, 0x75, 0x37, 0x09, 0x01, + 0x3b, 0x65, 0x32, 0xc1, 0x25, 0x5c, 0x8a, 0xcf, 0xba, 0x86, 0x1d, 0x31, 0x83, 0x18, 0x9f, 0xc9, + 0x0e, 0x80, 0x54, 0xb1, 0x50, 0x38, 0xcd, 0xd1, 0xd6, 0xa6, 0x2e, 0x56, 0xf4, 0x10, 0x27, 0xcf, + 0xc1, 0x15, 0x2c, 0x9e, 0x1b, 0xd4, 0x46, 0xd4, 0xd1, 0x05, 0x04, 0x77, 0x00, 0x72, 0x96, 0x73, + 0xb1, 0xd4, 0xb9, 0x70, 0xa8, 0xda, 0xd4, 0x35, 0x95, 0xb1, 0x64, 0xe1, 0x7f, 0x16, 0xf4, 0x2f, + 0x78, 0x5a, 0xce, 0xd9, 0xf5, 0x72, 0xc1, 0x30, 0xd5, 0x9f, 0xf5, 0xe1, 0xca, 0xa5, 0x54, 0x2c, + 0xc7, 0x74, 0xfd, 0xfd, 0x57, 0xab, 0xa7, 0xc5, 0x1d, 0xa9, 0x39, 0xeb, 0x2b, 0x94, 0xb5, 0xe6, + 0xc6, 0xe4, 0xb6, 0x4a, 0x7e, 0x00, 0x2f, 0x47, 0x4d, 0xa4, 0x96, 0x8b, 0x7a, 0x97, 0x90, 0x37, + 0x36, 0xba, 0x8d, 0x45, 0x99, 0x47, 0x7c, 0x1a, 0x99, 0xa2, 0xc4, 0xfd, 0xf6, 0xe8, 0x66, 0x51, + 0xe6, 0xa3, 0xa9, 0x59, 0x4f, 0x86, 0xaf, 0xaa, 0xf3, 0xaa, 0x5c, 0xef, 0x1c, 0xba, 0x0b, 0xeb, + 0x57, 0xa3, 0xd1, 0xa5, 0xbe, 0x1d, 0x0e, 0xd8, 0x17, 0x47, 0xe7, 0xa7, 0xfe, 0x5a, 0x38, 0x87, + 0x67, 0x43, 0x91, 0xa9, 0x2c, 0x89, 0xe7, 0x63, 0xc9, 0xc4, 0x6f, 0xbc, 0x14, 0x05, 0x5b, 0x56, + 0xc3, 0xae, 0x69, 0xba, 0xd5, 0x6a, 0xfa, 0x21, 0x74, 0xab, 0x5d, 0x62, 0xca, 0xaf, 0x5d, 0xef, + 0xd6, 0xbc, 0xa4, 0xb5, 0x20, 0x9c, 0xc0, 0xf3, 0x15, 0xab, 0xc9, 0x7a, 0xb9, 0x21, 0xd8, 0x49, + 0xf9, 0x59, 0x06, 0x16, 0x7e, 0xab, 0xab, 0x3b, 0xfb, 0xf5, 0xb4, 0x14, 0xc5, 0xc7, 0x4f, 0xfe, + 0xa8, 0x7e, 0x07, 0x2a, 0x45, 0x84, 0xff, 0x08, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x7d, 0x7b, + 0xda, 0x72, 0x33, 0x08, 0x00, 0x00, } diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto index bbb3021b8..e96a2e9b2 100644 --- a/ui/metrics/metrics_proto/metrics.proto +++ b/ui/metrics/metrics_proto/metrics.proto @@ -97,9 +97,6 @@ message MetricsBase { // The hostname of the machine. optional string hostname = 24; - - // The build command that the user entered to the build system. - optional string build_command = 26; } message BuildConfig { @@ -156,4 +153,4 @@ message CriticalUserJourneyMetrics { message CriticalUserJourneysMetrics { // A set of metrics from a run of the critical user journey tests. repeated CriticalUserJourneyMetrics cujs = 1; -} +}
\ No newline at end of file |