diff options
53 files changed, 619 insertions, 302 deletions
diff --git a/android/Android.bp b/android/Android.bp index 6ddcc14a2..50faa4436 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -24,6 +24,7 @@ bootstrap_go_package { "filegroup.go", "hooks.go", "image.go", + "makefile_goal.go", "makevars.go", "metrics.go", "module.go", diff --git a/android/config.go b/android/config.go index cafc71b75..33877066c 100644 --- a/android/config.go +++ b/android/config.go @@ -337,8 +337,8 @@ func NewConfig(srcDir, buildDir string, moduleListFile string) (Config, error) { config: config, } - // Sanity check the build and source directories. This won't catch strange - // configurations with symlinks, but at least checks the obvious cases. + // Soundness check of the build and source directories. This won't catch strange + // configurations with symlinks, but at least checks the obvious case. absBuildDir, err := filepath.Abs(buildDir) if err != nil { return Config{}, err @@ -1271,3 +1271,7 @@ func (c *deviceConfig) DeviceSecondaryArchVariant() string { func (c *deviceConfig) BoardUsesRecoveryAsBoot() bool { return Bool(c.config.productVariables.BoardUsesRecoveryAsBoot) } + +func (c *deviceConfig) BoardKernelBinaries() []string { + return c.config.productVariables.BoardKernelBinaries +} diff --git a/android/makefile_goal.go b/android/makefile_goal.go new file mode 100644 index 000000000..eae3976a8 --- /dev/null +++ b/android/makefile_goal.go @@ -0,0 +1,99 @@ +// 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 ( + "fmt" + "io" + "path/filepath" + + "github.com/google/blueprint/proptools" +) + +func init() { + RegisterModuleType("makefile_goal", MakefileGoalFactory) +} + +type makefileGoalProperties struct { + // Sources. + + // Makefile goal output file path, relative to PRODUCT_OUT. + Product_out_path *string +} + +type makefileGoal struct { + ModuleBase + + properties makefileGoalProperties + + // Destination. Output file path of this module. + outputFilePath OutputPath +} + +var _ AndroidMkEntriesProvider = (*makefileGoal)(nil) +var _ OutputFileProducer = (*makefileGoal)(nil) + +// Input file of this makefile_goal module. Nil if none specified. May use variable names in makefiles. +func (p *makefileGoal) inputPath() *string { + if p.properties.Product_out_path != nil { + return proptools.StringPtr(filepath.Join("$(PRODUCT_OUT)", proptools.String(p.properties.Product_out_path))) + } + return nil +} + +// OutputFileProducer +func (p *makefileGoal) OutputFiles(tag string) (Paths, error) { + if tag != "" { + return nil, fmt.Errorf("unsupported tag %q", tag) + } + return Paths{p.outputFilePath}, nil +} + +// AndroidMkEntriesProvider +func (p *makefileGoal) DepsMutator(ctx BottomUpMutatorContext) { + if p.inputPath() == nil { + ctx.PropertyErrorf("product_out_path", "Path relative to PRODUCT_OUT required") + } +} + +func (p *makefileGoal) GenerateAndroidBuildActions(ctx ModuleContext) { + filename := filepath.Base(proptools.String(p.inputPath())) + p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath + + ctx.InstallFile(PathForModuleInstall(ctx, "etc"), ctx.ModuleName(), p.outputFilePath) +} + +func (p *makefileGoal) AndroidMkEntries() []AndroidMkEntries { + return []AndroidMkEntries{AndroidMkEntries{ + Class: "ETC", + OutputFile: OptionalPathForPath(p.outputFilePath), + ExtraFooters: []AndroidMkExtraFootersFunc{ + func(w io.Writer, name, prefix, moduleDir string, entries *AndroidMkEntries) { + // Can't use Cp because inputPath() is not a valid Path. + fmt.Fprintf(w, "$(eval $(call copy-one-file,%s,%s))\n", proptools.String(p.inputPath()), p.outputFilePath) + }, + }, + }} +} + +// Import a Makefile goal to Soong by copying the file built by +// the goal to a path visible to Soong. This rule only works on boot images. +func MakefileGoalFactory() Module { + module := &makefileGoal{} + module.AddProperties(&module.properties) + // This module is device-only + InitAndroidArchModule(module, DeviceSupported, MultilibFirst) + return module +} diff --git a/android/module.go b/android/module.go index 2062a4d4d..a12cd9b10 100644 --- a/android/module.go +++ b/android/module.go @@ -548,6 +548,9 @@ type commonProperties struct { SkipInstall bool `blueprint:"mutated"` + // Disabled by mutators. If set to true, it overrides Enabled property. + ForcedDisabled bool `blueprint:"mutated"` + NamespaceExportedToMake bool `blueprint:"mutated"` MissingDeps []string `blueprint:"mutated"` @@ -1022,6 +1025,9 @@ func (m *ModuleBase) PartitionTag(config DeviceConfig) string { } func (m *ModuleBase) Enabled() bool { + if m.commonProperties.ForcedDisabled { + return false + } if m.commonProperties.Enabled == nil { return !m.Os().DefaultDisabled } @@ -1029,7 +1035,7 @@ func (m *ModuleBase) Enabled() bool { } func (m *ModuleBase) Disable() { - m.commonProperties.Enabled = proptools.BoolPtr(false) + m.commonProperties.ForcedDisabled = true } func (m *ModuleBase) SkipInstall() { diff --git a/android/neverallow.go b/android/neverallow.go index 526d39949..73829f137 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -56,6 +56,7 @@ func init() { AddNeverAllowRules(createJavaDeviceForHostRules()...) AddNeverAllowRules(createCcSdkVariantRules()...) AddNeverAllowRules(createUncompressDexRules()...) + AddNeverAllowRules(createMakefileGoalRules()...) } // Add a NeverAllow rule to the set of rules to apply. @@ -231,6 +232,15 @@ func createUncompressDexRules() []Rule { } } +func createMakefileGoalRules() []Rule { + return []Rule{ + NeverAllow(). + ModuleType("makefile_goal"). + WithoutMatcher("product_out_path", Regexp("^boot[0-9a-zA-Z.-]*[.]img$")). + Because("Only boot images may be imported as a makefile goal."), + } +} + func neverallowMutator(ctx BottomUpMutatorContext) { m, ok := ctx.Module().(Module) if !ok { diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 45d36a69b..56a07dc9d 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -326,6 +326,20 @@ var neverallowTests = []struct { "module \"outside_art_libraries\": violates neverallow", }, }, + { + name: "disallowed makefile_goal", + fs: map[string][]byte{ + "Android.bp": []byte(` + makefile_goal { + name: "foo", + product_out_path: "boot/trap.img" + } + `), + }, + expectedErrors: []string{ + "Only boot images may be imported as a makefile goal.", + }, + }, } func TestNeverallow(t *testing.T) { @@ -350,6 +364,7 @@ func testNeverallow(config Config) (*TestContext, []error) { ctx.RegisterModuleType("java_library", newMockJavaLibraryModule) ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule) ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule) + ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule) ctx.PostDepsMutators(RegisterNeverallowMutator) ctx.Register(config) @@ -438,3 +453,22 @@ func newMockJavaLibraryModule() Module { func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) { } + +type mockMakefileGoalProperties struct { + Product_out_path *string +} + +type mockMakefileGoalModule struct { + ModuleBase + properties mockMakefileGoalProperties +} + +func newMockMakefileGoalModule() Module { + m := &mockMakefileGoalModule{} + m.AddProperties(&m.properties) + InitAndroidModule(m) + return m +} + +func (p *mockMakefileGoalModule) GenerateAndroidBuildActions(ModuleContext) { +} diff --git a/android/variable.go b/android/variable.go index 582613815..c1e1b42be 100644 --- a/android/variable.go +++ b/android/variable.go @@ -344,6 +344,8 @@ type productVariables struct { InstallExtraFlattenedApexes *bool `json:",omitempty"` BoardUsesRecoveryAsBoot *bool `json:",omitempty"` + + BoardKernelBinaries []string `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/apex/androidmk.go b/apex/androidmk.go index 82a902b50..5c6d6ccfe 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -50,6 +50,11 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo return moduleNames } + // b/162366062. Prevent GKI APEXes to emit make rules to avoid conflicts. + if strings.HasPrefix(apexName, "com.android.gki.") && apexType != flattenedApex { + return moduleNames + } + // b/140136207. When there are overriding APEXes for a VNDK APEX, the symbols file for the overridden // APEX and the overriding APEX will have the same installation paths at /apex/com.android.vndk.v<ver> // as their apexName will be the same. To avoid the path conflicts, skip installing the symbol files @@ -209,7 +214,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo if !ok { panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module)) } - fmt.Fprintln(w, "LOCAL_APK_SET_MASTER_FILE :=", as.MasterFile()) + fmt.Fprintln(w, "LOCAL_APK_SET_INSTALL_FILE :=", as.InstallFile()) fmt.Fprintln(w, "LOCAL_APKCERTS_FILE :=", as.APKCertsFile().String()) fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk") case nativeSharedLib, nativeExecutable, nativeTest: diff --git a/apex/apex.go b/apex/apex.go index f9c902cf2..9905b7954 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -704,7 +704,7 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { if !ok || !am.CanHaveApexVariants() { return false } - if !parent.(android.DepIsInSameApex).DepIsInSameApex(mctx, child) && !inAnySdk(child) { + if !parent.(android.DepIsInSameApex).DepIsInSameApex(mctx, child) { return false } if excludeVndkLibs { @@ -2162,10 +2162,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { return false } if cc.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && cc.IsVndk() { - // For vendor APEX with use_vndk_as_stable: true, we don't include VNDK libs - // and use them from VNDK APEX. - // TODO(b/159576928): add "vndk" as requiredDeps so that linkerconfig can make "vndk" - // linker namespace avaiable to this apex. + requireNativeLibs = append(requireNativeLibs, ":vndk") return false } af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs) diff --git a/apex/apex_test.go b/apex/apex_test.go index 690c2f5fd..a6f380513 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -236,13 +236,15 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr ctx.PreArchMutators(android.RegisterComponentsMutator) ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators) - cc.RegisterRequiredBuildComponentsForTest(ctx) + android.RegisterPrebuiltMutators(ctx) - // Register this after the prebuilt mutators have been registered (in - // cc.RegisterRequiredBuildComponentsForTest) to match what happens at runtime. + // Register these after the prebuilt mutators have been registered to match what + // happens at runtime. ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer) ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer) + cc.RegisterRequiredBuildComponentsForTest(ctx) + ctx.RegisterModuleType("cc_test", cc.TestFactory) ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory) ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory) @@ -2208,6 +2210,10 @@ func TestVendorApex(t *testing.T) { data.Custom(&builder, name, prefix, "", data) androidMk := builder.String() ensureContains(t, androidMk, `LOCAL_MODULE_PATH := /tmp/target/product/test_device/vendor/apex`) + + apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule") + requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"]) + ensureListNotContains(t, requireNativeLibs, ":vndk") } func TestVendorApex_use_vndk_as_stable(t *testing.T) { @@ -2257,6 +2263,10 @@ func TestVendorApex_use_vndk_as_stable(t *testing.T) { "bin/mybin", "lib64/libvendor.so", }) + + apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule") + requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"]) + ensureListContains(t, requireNativeLibs, ":vndk") } func TestAndroidMk_UseVendorRequired(t *testing.T) { @@ -5541,6 +5551,7 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpre ctx.RegisterModuleType("apex_key", ApexKeyFactory) ctx.RegisterModuleType("filegroup", android.FileGroupFactory) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) + android.RegisterPrebuiltMutators(ctx) cc.RegisterRequiredBuildComponentsForTest(ctx) java.RegisterJavaBuildComponents(ctx) java.RegisterSystemModulesBuildComponents(ctx) @@ -3034,7 +3034,7 @@ func squashRecoverySrcs(m *Module) { var _ android.ImageInterface = (*Module)(nil) func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { - // Sanity check + // Validation check vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() productSpecific := mctx.ProductSpecific() diff --git a/cc/testing.go b/cc/testing.go index 4d0b28b7f..c2353d8e6 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -20,8 +20,6 @@ import ( func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterPrebuiltBuildComponents(ctx) - android.RegisterPrebuiltMutators(ctx) - RegisterCCBuildComponents(ctx) RegisterBinaryBuildComponents(ctx) RegisterLibraryBuildComponents(ctx) @@ -570,6 +568,7 @@ func CreateTestContext() *android.TestContext { ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) ctx.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) + android.RegisterPrebuiltMutators(ctx) RegisterRequiredBuildComponentsForTest(ctx) ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton) ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton) diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index fec0c8bb6..0af22580a 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -552,6 +552,13 @@ func isVendorSnapshotModule(m *Module, moduleDir string) bool { if _, ok := m.linker.(*kernelHeadersDecorator); ok { return false } + // skip llndk_library and llndk_headers which are backward compatible + if _, ok := m.linker.(*llndkStubDecorator); ok { + return false + } + if _, ok := m.linker.(*llndkHeadersDecorator); ok { + return false + } // Libraries if l, ok := m.linker.(snapshotLibraryInterface); ok { diff --git a/cc/vndk.go b/cc/vndk.go index 15843c6c6..f9adec73a 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -340,7 +340,7 @@ func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { } } -// Sanity check for modules that mustn't be VNDK +// Check for modules that mustn't be VNDK func shouldSkipVndkMutator(m *Module) bool { if !m.Enabled() { return true diff --git a/cmd/diff_target_files/Android.bp b/cmd/diff_target_files/Android.bp index 5397f4b74..bc6b068b9 100644 --- a/cmd/diff_target_files/Android.bp +++ b/cmd/diff_target_files/Android.bp @@ -5,12 +5,12 @@ blueprint_go_binary { "diff_target_files.go", "glob.go", "target_files.go", - "whitelist.go", + "allow_list.go", "zip_artifact.go", ], testSrcs: [ "compare_test.go", "glob_test.go", - "whitelist_test.go", + "allow_list_test.go", ], } diff --git a/cmd/diff_target_files/whitelist.go b/cmd/diff_target_files/allow_list.go index f00fc1ee2..ca55b43e1 100644 --- a/cmd/diff_target_files/whitelist.go +++ b/cmd/diff_target_files/allow_list.go @@ -25,18 +25,13 @@ import ( "unicode" ) -type jsonWhitelist struct { - Paths []string - IgnoreMatchingLines []string -} - -type whitelist struct { +type allowList struct { path string ignoreMatchingLines []string } -func parseWhitelists(whitelists []string, whitelistFiles []string) ([]whitelist, error) { - var ret []whitelist +func parseAllowLists(allowLists []string, allowListFiles []string) ([]allowList, error) { + var ret []allowList add := func(path string, ignoreMatchingLines []string) { for _, x := range ret { @@ -46,24 +41,24 @@ func parseWhitelists(whitelists []string, whitelistFiles []string) ([]whitelist, } } - ret = append(ret, whitelist{ + ret = append(ret, allowList{ path: path, ignoreMatchingLines: ignoreMatchingLines, }) } - for _, file := range whitelistFiles { - newWhitelists, err := parseWhitelistFile(file) + for _, file := range allowListFiles { + newAllowlists, err := parseAllowListFile(file) if err != nil { return nil, err } - for _, w := range newWhitelists { + for _, w := range newAllowlists { add(w.path, w.ignoreMatchingLines) } } - for _, s := range whitelists { + for _, s := range allowLists { colon := strings.IndexRune(s, ':') var ignoreMatchingLines []string if colon >= 0 { @@ -75,7 +70,7 @@ func parseWhitelists(whitelists []string, whitelistFiles []string) ([]whitelist, return ret, nil } -func parseWhitelistFile(file string) ([]whitelist, error) { +func parseAllowListFile(file string) ([]allowList, error) { r, err := os.Open(file) if err != nil { return nil, err @@ -84,27 +79,32 @@ func parseWhitelistFile(file string) ([]whitelist, error) { d := json.NewDecoder(newJSONCommentStripper(r)) - var jsonWhitelists []jsonWhitelist + var jsonAllowLists []struct { + Paths []string + IgnoreMatchingLines []string + } - err = d.Decode(&jsonWhitelists) + if err := d.Decode(&jsonAllowLists); err != nil { + return nil, err + } - var whitelists []whitelist - for _, w := range jsonWhitelists { + var allowLists []allowList + for _, w := range jsonAllowLists { for _, p := range w.Paths { - whitelists = append(whitelists, whitelist{ + allowLists = append(allowLists, allowList{ path: p, ignoreMatchingLines: w.IgnoreMatchingLines, }) } } - return whitelists, err + return allowLists, err } -func filterModifiedPaths(l [][2]*ZipArtifactFile, whitelists []whitelist) ([][2]*ZipArtifactFile, error) { +func filterModifiedPaths(l [][2]*ZipArtifactFile, allowLists []allowList) ([][2]*ZipArtifactFile, error) { outer: for i := 0; i < len(l); i++ { - for _, w := range whitelists { + for _, w := range allowLists { if match, err := Match(w.path, l[i][0].Name); err != nil { return l, err } else if match { @@ -126,10 +126,10 @@ outer: return l, nil } -func filterNewPaths(l []*ZipArtifactFile, whitelists []whitelist) ([]*ZipArtifactFile, error) { +func filterNewPaths(l []*ZipArtifactFile, allowLists []allowList) ([]*ZipArtifactFile, error) { outer: for i := 0; i < len(l); i++ { - for _, w := range whitelists { + for _, w := range allowLists { if match, err := Match(w.path, l[i].Name); err != nil { return l, err } else if match && len(w.ignoreMatchingLines) == 0 { @@ -192,18 +192,18 @@ func diffIgnoringMatchingLines(a *ZipArtifactFile, b *ZipArtifactFile, ignoreMat return bytes.Compare(bufA, bufB) == 0, nil } -func applyWhitelists(diff zipDiff, whitelists []whitelist) (zipDiff, error) { +func applyAllowLists(diff zipDiff, allowLists []allowList) (zipDiff, error) { var err error - diff.modified, err = filterModifiedPaths(diff.modified, whitelists) + diff.modified, err = filterModifiedPaths(diff.modified, allowLists) if err != nil { return diff, err } - diff.onlyInA, err = filterNewPaths(diff.onlyInA, whitelists) + diff.onlyInA, err = filterNewPaths(diff.onlyInA, allowLists) if err != nil { return diff, err } - diff.onlyInB, err = filterNewPaths(diff.onlyInB, whitelists) + diff.onlyInB, err = filterNewPaths(diff.onlyInB, allowLists) if err != nil { return diff, err } diff --git a/cmd/diff_target_files/whitelist_test.go b/cmd/diff_target_files/allow_list_test.go index 4b19fdd21..8410e5acc 100644 --- a/cmd/diff_target_files/whitelist_test.go +++ b/cmd/diff_target_files/allow_list_test.go @@ -57,10 +57,10 @@ c var f2 = bytesToZipArtifactFile("dir/f2", nil) -func Test_applyWhitelists(t *testing.T) { +func Test_applyAllowLists(t *testing.T) { type args struct { diff zipDiff - whitelists []whitelist + allowLists []allowList } tests := []struct { name string @@ -74,7 +74,7 @@ func Test_applyWhitelists(t *testing.T) { diff: zipDiff{ onlyInA: []*ZipArtifactFile{f1a, f2}, }, - whitelists: []whitelist{{path: "dir/f1"}}, + allowLists: []allowList{{path: "dir/f1"}}, }, want: zipDiff{ onlyInA: []*ZipArtifactFile{f2}, @@ -86,7 +86,7 @@ func Test_applyWhitelists(t *testing.T) { diff: zipDiff{ onlyInA: []*ZipArtifactFile{f1a, f2}, }, - whitelists: []whitelist{{path: "dir/*"}}, + allowLists: []allowList{{path: "dir/*"}}, }, want: zipDiff{}, }, @@ -96,7 +96,7 @@ func Test_applyWhitelists(t *testing.T) { diff: zipDiff{ modified: [][2]*ZipArtifactFile{{f1a, f1b}}, }, - whitelists: []whitelist{{path: "dir/*"}}, + allowLists: []allowList{{path: "dir/*"}}, }, want: zipDiff{}, }, @@ -106,20 +106,20 @@ func Test_applyWhitelists(t *testing.T) { diff: zipDiff{ modified: [][2]*ZipArtifactFile{{f1a, f1b}}, }, - whitelists: []whitelist{{path: "dir/*", ignoreMatchingLines: []string{"foo: .*"}}}, + allowLists: []allowList{{path: "dir/*", ignoreMatchingLines: []string{"foo: .*"}}}, }, want: zipDiff{}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := applyWhitelists(tt.args.diff, tt.args.whitelists) + got, err := applyAllowLists(tt.args.diff, tt.args.allowLists) if (err != nil) != tt.wantErr { - t.Errorf("applyWhitelists() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("Test_applyAllowLists() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("applyWhitelists() = %v, want %v", got, tt.want) + t.Errorf("Test_applyAllowLists() = %v, want %v", got, tt.want) } }) } diff --git a/cmd/diff_target_files/compare.go b/cmd/diff_target_files/compare.go index 00cd9ca10..45b6d6b1c 100644 --- a/cmd/diff_target_files/compare.go +++ b/cmd/diff_target_files/compare.go @@ -21,7 +21,7 @@ import ( // compareTargetFiles takes two ZipArtifacts and compares the files they contain by examining // the path, size, and CRC of each file. -func compareTargetFiles(priZip, refZip ZipArtifact, artifact string, whitelists []whitelist, filters []string) (zipDiff, error) { +func compareTargetFiles(priZip, refZip ZipArtifact, artifact string, allowLists []allowList, filters []string) (zipDiff, error) { priZipFiles, err := priZip.Files() if err != nil { return zipDiff{}, fmt.Errorf("error fetching target file lists from primary zip %v", err) @@ -45,7 +45,7 @@ func compareTargetFiles(priZip, refZip ZipArtifact, artifact string, whitelists // Compare the file lists from both builds diff := diffTargetFilesLists(refZipFiles, priZipFiles) - return applyWhitelists(diff, whitelists) + return applyAllowLists(diff, allowLists) } // zipDiff contains the list of files that differ between two zip files. diff --git a/cmd/diff_target_files/diff_target_files.go b/cmd/diff_target_files/diff_target_files.go index 75bc8ee4e..634565bca 100644 --- a/cmd/diff_target_files/diff_target_files.go +++ b/cmd/diff_target_files/diff_target_files.go @@ -22,8 +22,8 @@ import ( ) var ( - whitelists = newMultiString("whitelist", "whitelist patterns in the form <pattern>[:<regex of line to ignore>]") - whitelistFiles = newMultiString("whitelist_file", "files containing whitelist definitions") + allowLists = newMultiString("allowlist", "allowlist patterns in the form <pattern>[:<regex of line to ignore>]") + allowListFiles = newMultiString("allowlist_file", "files containing allowlist definitions") filters = newMultiString("filter", "filter patterns to apply to files in target-files.zip before comparing") ) @@ -47,9 +47,9 @@ func main() { os.Exit(1) } - whitelists, err := parseWhitelists(*whitelists, *whitelistFiles) + allowLists, err := parseAllowLists(*allowLists, *allowListFiles) if err != nil { - fmt.Fprintf(os.Stderr, "Error parsing whitelists: %v\n", err) + fmt.Fprintf(os.Stderr, "Error parsing allowlists: %v\n", err) os.Exit(1) } @@ -67,7 +67,7 @@ func main() { } defer refZip.Close() - diff, err := compareTargetFiles(priZip, refZip, targetFilesPattern, whitelists, *filters) + diff, err := compareTargetFiles(priZip, refZip, targetFilesPattern, allowLists, *filters) if err != nil { fmt.Fprintf(os.Stderr, "Error comparing zip files: %v\n", err) os.Exit(1) diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go index a95aca9f0..274c8eee5 100644 --- a/cmd/merge_zips/merge_zips.go +++ b/cmd/merge_zips/merge_zips.go @@ -429,7 +429,7 @@ func NewInputZipsManager(nInputZips, maxOpenZips int) *InputZipsManager { if maxOpenZips < 3 { panic(fmt.Errorf("open zips limit should be above 3")) } - // In the dummy element .older points to the most recently opened InputZip, and .newer points to the oldest. + // In the fake element .older points to the most recently opened InputZip, and .newer points to the oldest. head := new(ManagedInputZip) head.older = head head.newer = head diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go index e485c60e0..69e4f696c 100644 --- a/cmd/soong_ui/main.go +++ b/cmd/soong_ui/main.go @@ -35,14 +35,14 @@ import ( // A command represents an operation to be executed in the soong build // system. type command struct { - // the flag name (must have double dashes) + // The flag name (must have double dashes). flag string - // description for the flag (to display when running help) + // Description for the flag (to display when running help). description string - // Forces the status output into dumb terminal mode. - forceDumbOutput bool + // Stream the build status output into the simple terminal mode. + simpleOutput bool // Sets a prefix string to use for filenames of log files. logsPrefix string @@ -70,21 +70,21 @@ var commands []command = []command{ stdio: stdio, run: make, }, { - flag: "--dumpvar-mode", - description: "print the value of the legacy make variable VAR to stdout", - forceDumbOutput: true, - logsPrefix: "dumpvars-", - config: dumpVarConfig, - stdio: customStdio, - run: dumpVar, + flag: "--dumpvar-mode", + description: "print the value of the legacy make variable VAR to stdout", + simpleOutput: true, + logsPrefix: "dumpvars-", + config: dumpVarConfig, + stdio: customStdio, + run: dumpVar, }, { - flag: "--dumpvars-mode", - description: "dump the values of one or more legacy make variables, in shell syntax", - forceDumbOutput: true, - logsPrefix: "dumpvars-", - config: dumpVarConfig, - stdio: customStdio, - run: dumpVars, + flag: "--dumpvars-mode", + description: "dump the values of one or more legacy make variables, in shell syntax", + simpleOutput: true, + logsPrefix: "dumpvars-", + config: dumpVarConfig, + stdio: customStdio, + run: dumpVars, }, { flag: "--build-mode", description: "build modules based on the specified build action", @@ -125,7 +125,7 @@ func main() { os.Exit(1) } - output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.forceDumbOutput, + output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput, build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")) log := logger.New(output) @@ -172,7 +172,7 @@ func main() { buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error") rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb") soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics") - defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile) + defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile) os.MkdirAll(logsDir, 0777) log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log")) diff --git a/java/androidmk.go b/java/androidmk.go index 25dd32931..081fcb25d 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -728,7 +728,7 @@ func (apkSet *AndroidAppSet) AndroidMkEntries() []android.AndroidMkEntries { ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(entries *android.AndroidMkEntries) { entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged()) - entries.SetString("LOCAL_APK_SET_MASTER_FILE", apkSet.masterFile) + entries.SetString("LOCAL_APK_SET_INSTALL_FILE", apkSet.InstallFile()) entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile) entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...) }, diff --git a/java/app.go b/java/app.go index 4031cfeb1..1ede34ebc 100755 --- a/java/app.go +++ b/java/app.go @@ -78,7 +78,7 @@ type AndroidAppSet struct { properties AndroidAppSetProperties packedOutput android.WritablePath - masterFile string + installFile string apkcertsFile android.ModuleOutPath } @@ -102,8 +102,8 @@ func (as *AndroidAppSet) OutputFile() android.Path { return as.packedOutput } -func (as *AndroidAppSet) MasterFile() string { - return as.masterFile +func (as *AndroidAppSet) InstallFile() string { + return as.installFile } func (as *AndroidAppSet) APKCertsFile() android.Path { @@ -136,10 +136,10 @@ func SupportedAbis(ctx android.ModuleContext) []string { func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip") as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt") - // We are assuming here that the master file in the APK + // We are assuming here that the install file in the APK // set has `.apk` suffix. If it doesn't the build will fail. // APK sets containing APEX files are handled elsewhere. - as.masterFile = as.BaseModuleName() + ".apk" + as.installFile = as.BaseModuleName() + ".apk" screenDensities := "all" if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 { screenDensities = strings.ToUpper(strings.Join(dpis, ",")) @@ -167,7 +167,7 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) // android_app_set extracts a set of APKs based on the target device // configuration and installs this set as "split APKs". -// The extracted set always contains 'master' APK whose name is +// The extracted set always contains an APK whose name is // _module_name_.apk and every split APK matching target device. // The extraction of the density-specific splits depends on // PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should diff --git a/java/app_test.go b/java/app_test.go index d4323bbdc..efb4fd2a6 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -161,11 +161,11 @@ func TestAndroidAppSet(t *testing.T) { t.Errorf("wrong partition value: '%s', expected 'system'", s) } mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0] - actualMaster := mkEntries.EntryMap["LOCAL_APK_SET_MASTER_FILE"] - expectedMaster := []string{"foo.apk"} - if !reflect.DeepEqual(actualMaster, expectedMaster) { - t.Errorf("Unexpected LOCAL_APK_SET_MASTER_FILE value: '%s', expected: '%s',", - actualMaster, expectedMaster) + actualInstallFile := mkEntries.EntryMap["LOCAL_APK_SET_INSTALL_FILE"] + expectedInstallFile := []string{"foo.apk"} + if !reflect.DeepEqual(actualInstallFile, expectedInstallFile) { + t.Errorf("Unexpected LOCAL_APK_SET_INSTALL_FILE value: '%s', expected: '%s',", + actualInstallFile, expectedInstallFile) } } diff --git a/java/droiddoc.go b/java/droiddoc.go index 935b83915..d2f8d8331 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -198,7 +198,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 { @@ -870,6 +870,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") || @@ -892,7 +896,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()) } diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index bff591cb0..7afba2a79 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -208,7 +208,7 @@ func stubFlagsRule(ctx android.SingletonContext) { } // flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and -// the greylists. +// the unsupported API. func flagsRule(ctx android.SingletonContext) android.Path { var flagsCSV android.Paths var greylistRemovedApis android.Paths @@ -247,18 +247,18 @@ func flagsRule(ctx android.SingletonContext) android.Path { Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py")). FlagWithInput("--csv ", stubFlags). Inputs(flagsCSV). - FlagWithInput("--greylist ", + FlagWithInput("--unsupported ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist.txt")). - FlagWithInput("--greylist-ignore-conflicts ", combinedRemovedApis). - FlagWithInput("--greylist-max-q ", + FlagWithInput("--unsupported-ignore-conflicts ", combinedRemovedApis). + FlagWithInput("--max-target-q ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-q.txt")). - FlagWithInput("--greylist-max-p ", + FlagWithInput("--max-target-p ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-p.txt")). - FlagWithInput("--greylist-max-o-ignore-conflicts ", + FlagWithInput("--max-target-o-ignore-conflicts ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-o.txt")). - FlagWithInput("--blacklist ", + FlagWithInput("--blocked ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blacklist.txt")). - FlagWithInput("--greylist-packages ", + FlagWithInput("--unsupported-packages ", android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-packages.txt")). FlagWithOutput("--output ", tempPath) diff --git a/java/java_test.go b/java/java_test.go index 73e6792b4..a3c78540f 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -96,6 +96,8 @@ func testContext() *android.TestContext { ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory)) ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory)) + android.RegisterPrebuiltMutators(ctx) + // Register module types and mutators from cc needed for JNI testing cc.RegisterRequiredBuildComponentsForTest(ctx) @@ -489,7 +491,7 @@ func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { ctx, _ := testJavaWithConfig(t, config) - // first, sanity check that the -g flag is added to target modules + // first, check that the -g flag is added to target modules targetLibrary := ctx.ModuleForTests("target_library", "android_common") targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"] if !strings.Contains(targetJavaFlags, "-g:source,lines") { @@ -1107,8 +1109,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()) @@ -1117,7 +1124,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) } diff --git a/rust/androidmk.go b/rust/androidmk.go index babbf9123..580601734 100644 --- a/rust/androidmk.go +++ b/rust/androidmk.go @@ -55,7 +55,6 @@ func (mod *Module) AndroidMk() android.AndroidMkData { ret := android.AndroidMkData{ OutputFile: mod.outputFile, Include: "$(BUILD_SYSTEM)/soong_rust_prebuilt.mk", - SubName: mod.subName, Extra: []android.AndroidMkExtraFunc{ func(w io.Writer, outputFile android.Path) { if len(mod.Properties.AndroidMkRlibs) > 0 { @@ -76,9 +75,11 @@ func (mod *Module) AndroidMk() android.AndroidMkData { }, }, } - if mod.compiler != nil { + + if mod.compiler != nil && !mod.compiler.Disabled() { mod.subAndroidMk(&ret, mod.compiler) } else if mod.sourceProvider != nil { + // If the compiler is disabled, this is a SourceProvider. mod.subAndroidMk(&ret, mod.sourceProvider) } ret.SubName += mod.Properties.SubName @@ -162,6 +163,7 @@ func (sourceProvider *baseSourceProvider) AndroidMk(ctx AndroidMkContext, ret *a outFile := sourceProvider.outputFile ret.Class = "ETC" ret.OutputFile = android.OptionalPathForPath(outFile) + ret.SubName += sourceProvider.subName ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { _, file := filepath.Split(outFile.String()) stem, suffix, _ := android.SplitFileExt(file) diff --git a/rust/bindgen.go b/rust/bindgen.go index e8bbb35f1..304f8ec38 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -61,7 +61,7 @@ type BindgenProperties struct { Wrapper_src *string `android:"path,arch_variant"` // list of bindgen-specific flags and options - Flags []string `android:"arch_variant"` + Bindgen_flags []string `android:"arch_variant"` // list of clang flags required to correctly interpret the headers. Cflags []string `android:"arch_variant"` @@ -121,7 +121,7 @@ func (b *bindgenDecorator) generateSource(ctx android.ModuleContext, deps PathDe } bindgenFlags := defaultBindgenFlags - bindgenFlags = append(bindgenFlags, strings.Join(b.Properties.Flags, " ")) + bindgenFlags = append(bindgenFlags, strings.Join(b.Properties.Bindgen_flags, " ")) wrapperFile := android.OptionalPathForModuleSrc(ctx, b.Properties.Wrapper_src) if !wrapperFile.Valid() { @@ -170,7 +170,13 @@ func NewRustBindgen(hod android.HostOrDeviceSupported) (*Module, *bindgenDecorat baseSourceProvider: NewSourceProvider(), Properties: BindgenProperties{}, } + + _, library := NewRustLibrary(hod) + library.BuildOnlyRust() + library.sourceProvider = bindgen + module.sourceProvider = bindgen + module.compiler = library return module, bindgen } diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go index 2122ec12c..c42834843 100644 --- a/rust/bindgen_test.go +++ b/rust/bindgen_test.go @@ -24,8 +24,10 @@ func TestRustBindgen(t *testing.T) { rust_bindgen { name: "libbindgen", wrapper_src: "src/any.h", - stem: "bindings", - flags: ["--bindgen-flag"], + crate_name: "bindgen", + stem: "libbindgen", + source_stem: "bindings", + bindgen_flags: ["--bindgen-flag"], cflags: ["--clang-flag"], shared_libs: ["libfoo_shared"], static_libs: ["libfoo_static"], @@ -38,7 +40,6 @@ func TestRustBindgen(t *testing.T) { name: "libfoo_static", export_include_dirs: ["static_include"], } - `) libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a").Output("bindings.rs") if !strings.Contains(libbindgen.Args["flags"], "--bindgen-flag") { diff --git a/rust/builder_test.go b/rust/builder_test.go index 04b67d9bd..5c11cb7b5 100644 --- a/rust/builder_test.go +++ b/rust/builder_test.go @@ -28,12 +28,14 @@ func TestSourceProviderCollision(t *testing.T) { } rust_bindgen { name: "libbindings1", - stem: "bindings", + source_stem: "bindings", + crate_name: "bindings1", wrapper_src: "src/any.h", } rust_bindgen { name: "libbindings2", - stem: "bindings", + source_stem: "bindings", + crate_name: "bindings2", wrapper_src: "src/any.h", } `) diff --git a/rust/compiler.go b/rust/compiler.go index 040219dc4..c2b7e569c 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -24,7 +24,7 @@ import ( "android/soong/rust/config" ) -func getEdition(compiler *baseCompiler) string { +func (compiler *baseCompiler) edition() string { return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition) } @@ -81,7 +81,10 @@ type BaseCompilerProperties struct { // list of C static library dependencies Static_libs []string `android:"arch_variant"` - // crate name, required for libraries. This must be the expected extern crate name used in source + // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider + // modules which create library variants (rust_bindgen). This must be the expected extern crate name used in + // source, and is required to conform to an enforced format matching library output files (if the output file is + // lib<someName><suffix>, the crate_name property must be <someName>). Crate_name string `android:"arch_variant"` // list of features to enable for this crate @@ -120,6 +123,14 @@ type baseCompiler struct { distFile android.OptionalPath } +func (compiler *baseCompiler) Disabled() bool { + return false +} + +func (compiler *baseCompiler) SetDisabled() { + panic("baseCompiler does not implement SetDisabled()") +} + func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath { panic("baseCompiler does not implement coverageOutputZipPath()") } @@ -149,7 +160,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flag } flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...) flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...) - flags.RustFlags = append(flags.RustFlags, "--edition="+getEdition(compiler)) + flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition()) flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...) flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...) flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags()) diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go index 0204cd2e7..9c9a136d7 100644 --- a/rust/config/allowed_list.go +++ b/rust/config/allowed_list.go @@ -7,6 +7,7 @@ var ( "external/crosvm", "external/adhd", "prebuilts/rust", + "system/security", } RustModuleTypes = []string{ diff --git a/rust/library.go b/rust/library.go index 4c6da9d86..6766d618b 100644 --- a/rust/library.go +++ b/rust/library.go @@ -69,6 +69,10 @@ type LibraryMutatedProperties struct { VariantIsShared bool `blueprint:"mutated"` // This variant is a static library VariantIsStatic bool `blueprint:"mutated"` + + // This variant is disabled and should not be compiled + // (used for SourceProvider variants that produce only source) + VariantIsDisabled bool `blueprint:"mutated"` } type libraryDecorator struct { @@ -78,6 +82,7 @@ type libraryDecorator struct { Properties LibraryCompilerProperties MutatedProperties LibraryMutatedProperties includeDirs android.Paths + sourceProvider SourceProvider } type libraryInterface interface { @@ -367,8 +372,13 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) F func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { var outputFile android.WritablePath + var srcPath android.Path - srcPath, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs) + if library.sourceProvider != nil { + srcPath = library.sourceProvider.Srcs()[0] + } else { + srcPath, _ = srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs) + } flags.RustFlags = append(flags.RustFlags, deps.depFlags...) @@ -430,6 +440,14 @@ func (library *libraryDecorator) getStem(ctx ModuleContext) string { return stem + String(library.baseCompiler.Properties.Suffix) } +func (library *libraryDecorator) Disabled() bool { + return library.MutatedProperties.VariantIsDisabled +} + +func (library *libraryDecorator) SetDisabled() { + library.MutatedProperties.VariantIsDisabled = true +} + var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+") func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) { @@ -454,25 +472,35 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { if m, ok := mctx.Module().(*Module); ok && m.compiler != nil { switch library := m.compiler.(type) { case libraryInterface: - - // We only build the rust library variants here. This assumes that - // LinkageMutator runs first and there's an empty variant - // if rust variants are required. - if !library.static() && !library.shared() { - if library.buildRlib() && library.buildDylib() { - modules := mctx.CreateLocalVariations("rlib", "dylib") - rlib := modules[0].(*Module) - dylib := modules[1].(*Module) - - rlib.compiler.(libraryInterface).setRlib() - dylib.compiler.(libraryInterface).setDylib() - } else if library.buildRlib() { - modules := mctx.CreateLocalVariations("rlib") - modules[0].(*Module).compiler.(libraryInterface).setRlib() - } else if library.buildDylib() { - modules := mctx.CreateLocalVariations("dylib") - modules[0].(*Module).compiler.(libraryInterface).setDylib() + if library.buildRlib() && library.buildDylib() { + variants := []string{"rlib", "dylib"} + if m.sourceProvider != nil { + variants = append(variants, "") + } + modules := mctx.CreateLocalVariations(variants...) + + rlib := modules[0].(*Module) + dylib := modules[1].(*Module) + rlib.compiler.(libraryInterface).setRlib() + dylib.compiler.(libraryInterface).setDylib() + + if m.sourceProvider != nil { + // This library is SourceProvider generated, so the non-library-producing + // variant needs to disable it's compiler and skip installation. + sourceProvider := modules[2].(*Module) + sourceProvider.compiler.SetDisabled() } + } else if library.buildRlib() { + modules := mctx.CreateLocalVariations("rlib") + modules[0].(*Module).compiler.(libraryInterface).setRlib() + } else if library.buildDylib() { + modules := mctx.CreateLocalVariations("dylib") + modules[0].(*Module).compiler.(libraryInterface).setDylib() + } + + if m.sourceProvider != nil { + // Alias the non-library variant to the empty-string variant. + mctx.AliasVariation("") } } } diff --git a/rust/project_json.go b/rust/project_json.go index a50e73a95..41dd194ee 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -92,7 +92,7 @@ func mergeDependencies(ctx android.SingletonContext, project *rustProjectJson, // appendLibraryAndDeps creates a rustProjectCrate for the module argument and // appends it to the rustProjectJson struct. It visits the dependencies of the // module depth-first. If the current module is already in knownCrates, its -// its dependencies are merged. Returns a tuple (id, crate_name, ok). +// dependencies are merged. Returns a tuple (id, crate_name, ok). func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson, knownCrates map[string]crateInfo, module android.Module) (int, string, bool) { rModule, ok := module.(*Module) @@ -111,12 +111,13 @@ func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson // We have seen this crate already; merge any new dependencies. crate := project.Crates[cInfo.ID] mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps) + project.Crates[cInfo.ID] = crate return cInfo.ID, crateName, true } crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)} src := rustLib.baseCompiler.Properties.Srcs[0] crate.RootModule = path.Join(ctx.ModuleDir(rModule), src) - crate.Edition = getEdition(rustLib.baseCompiler) + crate.Edition = rustLib.baseCompiler.edition() deps := make(map[string]int) mergeDependencies(ctx, project, knownCrates, module, &crate, deps) diff --git a/rust/rust.go b/rust/rust.go index 78bf7ada9..1192836a5 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -63,7 +63,8 @@ type BaseProperties struct { AndroidMkSharedLibs []string AndroidMkStaticLibs []string - SubName string `blueprint:"mutated"` + SubName string `blueprint:"mutated"` + PreventInstall bool HideFromMake bool } @@ -83,9 +84,9 @@ type Module struct { cachedToolchain config.Toolchain sourceProvider SourceProvider subAndroidMkOnce map[subAndroidMkProvider]bool - outputFile android.OptionalPath - subName string + outputFile android.OptionalPath + generatedFile android.OptionalPath } func (mod *Module) OutputFiles(tag string) (android.Paths, error) { @@ -141,12 +142,8 @@ func (mod *Module) SelectedStl() string { func (mod *Module) NonCcVariants() bool { if mod.compiler != nil { - if library, ok := mod.compiler.(libraryInterface); ok { - if library.buildRlib() || library.buildDylib() { - return true - } else { - return false - } + if _, ok := mod.compiler.(libraryInterface); ok { + return false } } panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName())) @@ -162,16 +159,16 @@ func (mod *Module) Static() bool { return library.static() } } - panic(fmt.Errorf("Static called on non-library module: %q", mod.BaseModuleName())) + return false } func (mod *Module) Shared() bool { if mod.compiler != nil { if library, ok := mod.compiler.(libraryInterface); ok { - return library.static() + return library.shared() } } - panic(fmt.Errorf("Shared called on non-library module: %q", mod.BaseModuleName())) + return false } func (mod *Module) Toc() android.OptionalPath { @@ -289,6 +286,9 @@ type compiler interface { relativeInstallPath() string nativeCoverage() bool + + Disabled() bool + SetDisabled() } type exportedFlagsProducer interface { @@ -399,7 +399,9 @@ func (mod *Module) CcLibrary() bool { func (mod *Module) CcLibraryInterface() bool { if mod.compiler != nil { - if _, ok := mod.compiler.(libraryInterface); ok { + // use build{Static,Shared}() instead of {static,shared}() here because this might be called before + // VariantIs{Static,Shared} is set. + if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic()) { return true } } @@ -669,16 +671,21 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { flags, deps = mod.clippy.flags(ctx, flags, deps) } - if mod.compiler != nil { + // SourceProvider needs to call generateSource() before compiler calls compile() so it can provide the source. + // TODO(b/162588681) This shouldn't have to run for every variant. + if mod.sourceProvider != nil { + generatedFile := mod.sourceProvider.generateSource(ctx, deps) + mod.generatedFile = android.OptionalPathForPath(generatedFile) + mod.sourceProvider.setSubName(ctx.ModuleSubDir()) + } + + if mod.compiler != nil && !mod.compiler.Disabled() { outputFile := mod.compiler.compile(ctx, flags, deps) + mod.outputFile = android.OptionalPathForPath(outputFile) - if !mod.Properties.PreventInstall { + if mod.outputFile.Valid() && !mod.Properties.PreventInstall { mod.compiler.install(ctx, mod.outputFile.Path()) } - } else if mod.sourceProvider != nil { - outputFile := mod.sourceProvider.generateSource(ctx, deps) - mod.outputFile = android.OptionalPathForPath(outputFile) - mod.subName = ctx.ModuleSubDir() } } @@ -687,7 +694,8 @@ func (mod *Module) deps(ctx DepsContext) Deps { if mod.compiler != nil { deps = mod.compiler.compilerDeps(ctx, deps) - } else if mod.sourceProvider != nil { + } + if mod.sourceProvider != nil { deps = mod.sourceProvider.sourceProviderDeps(ctx, deps) } @@ -754,14 +762,9 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { ctx.VisitDirectDeps(func(dep android.Module) { depName := ctx.OtherModuleName(dep) depTag := ctx.OtherModuleDependencyTag(dep) - if rustDep, ok := dep.(*Module); ok { + if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() { //Handle Rust Modules - linkFile := rustDep.outputFile - if !linkFile.Valid() { - ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName()) - } - switch depTag { case dylibDepTag: dylib, ok := rustDep.compiler.(libraryInterface) @@ -810,23 +813,19 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { + linkFile := rustDep.outputFile + if !linkFile.Valid() { + ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", + depName, ctx.ModuleName()) + return + } linkDir := linkPathFromFilePath(linkFile.Path()) if lib, ok := mod.compiler.(exportedFlagsProducer); ok { lib.exportLinkDirs(linkDir) } } - } - - if srcDep, ok := dep.(android.SourceFileProducer); ok { - switch depTag { - case android.SourceDepTag: - // These are usually genrules which don't have per-target variants. - directSrcDeps = append(directSrcDeps, srcDep) - } - } - - if ccDep, ok := dep.(cc.LinkableInterface); ok { + } else if ccDep, ok := dep.(cc.LinkableInterface); ok { //Handle C dependencies if _, ok := ccDep.(*Module); !ok { if ccDep.Module().Target().Os != ctx.Os() { @@ -838,7 +837,6 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } } - linkFile := ccDep.OutputFile() linkPath := linkPathFromFilePath(linkFile.Path()) libName := libNameFromFilePath(linkFile.Path()) @@ -886,6 +884,14 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { lib.exportDepFlags(depFlag) } } + + if srcDep, ok := dep.(android.SourceFileProducer); ok { + switch depTag { + case android.SourceDepTag: + // These are usually genrules which don't have per-target variants. + directSrcDeps = append(directSrcDeps, srcDep) + } + } }) var rlibDepFiles RustLibraries @@ -974,21 +980,18 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { } actx.AddVariationDependencies( append(commonDepVariations, []blueprint.Variation{ - {Mutator: "rust_libraries", Variation: "rlib"}, - {Mutator: "link", Variation: ""}}...), + {Mutator: "rust_libraries", Variation: "rlib"}}...), rlibDepTag, deps.Rlibs...) actx.AddVariationDependencies( append(commonDepVariations, []blueprint.Variation{ - {Mutator: "rust_libraries", Variation: "dylib"}, - {Mutator: "link", Variation: ""}}...), + {Mutator: "rust_libraries", Variation: "dylib"}}...), dylibDepTag, deps.Dylibs...) if deps.Rustlibs != nil { autoDep := mod.compiler.(autoDeppable).autoDep() actx.AddVariationDependencies( append(commonDepVariations, []blueprint.Variation{ - {Mutator: "rust_libraries", Variation: autoDep.variation}, - {Mutator: "link", Variation: ""}}...), + {Mutator: "rust_libraries", Variation: autoDep.variation}}...), autoDep.depTag, deps.Rustlibs...) } diff --git a/rust/rust_test.go b/rust/rust_test.go index b3bbddbc6..04de48b19 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -233,6 +233,7 @@ func TestSourceProviderDeps(t *testing.T) { ":my_generator", ":libbindings", ], + rlibs: ["libbindings"], } rust_proc_macro { name: "libprocmacro", @@ -241,6 +242,7 @@ func TestSourceProviderDeps(t *testing.T) { ":my_generator", ":libbindings", ], + rlibs: ["libbindings"], crate_name: "procmacro", } rust_library { @@ -248,7 +250,9 @@ func TestSourceProviderDeps(t *testing.T) { srcs: [ "foo.rs", ":my_generator", - ":libbindings"], + ":libbindings", + ], + rlibs: ["libbindings"], crate_name: "foo", } genrule { @@ -260,7 +264,8 @@ func TestSourceProviderDeps(t *testing.T) { } rust_bindgen { name: "libbindings", - stem: "bindings", + crate_name: "bindings", + source_stem: "bindings", host_supported: true, wrapper_src: "src/any.h", } @@ -289,6 +294,21 @@ func TestSourceProviderDeps(t *testing.T) { if !android.SuffixInList(libprocmacro.Implicits.Strings(), "/out/any.rs") { t.Errorf("genrule generated source not included as implicit input for libprocmacro; Implicits %#v", libfoo.Implicits.Strings()) } + + // Check that our bindings are picked up as crate dependencies as well + libfooMod := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module) + if !android.InList("libbindings", libfooMod.Properties.AndroidMkRlibs) { + t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)") + } + fizzBuzzMod := ctx.ModuleForTests("fizz-buzz-dep", "android_arm64_armv8-a").Module().(*Module) + if !android.InList("libbindings", fizzBuzzMod.Properties.AndroidMkRlibs) { + t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)") + } + libprocmacroMod := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Module().(*Module) + if !android.InList("libbindings", libprocmacroMod.Properties.AndroidMkRlibs) { + t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)") + } + } func TestSourceProviderTargetMismatch(t *testing.T) { @@ -305,7 +325,8 @@ func TestSourceProviderTargetMismatch(t *testing.T) { } rust_bindgen { name: "libbindings", - stem: "bindings", + crate_name: "bindings", + source_stem: "bindings", wrapper_src: "src/any.h", } `) diff --git a/rust/source_provider.go b/rust/source_provider.go index da6147a15..8bb784951 100644 --- a/rust/source_provider.go +++ b/rust/source_provider.go @@ -19,8 +19,13 @@ import ( ) type SourceProviderProperties struct { - // sets name of the output - Stem *string `android:"arch_variant"` + // name for the generated source file. Defaults to module name (e.g. moduleNameFoo.rs is produced by default). + // Importantly, the inherited "stem" property for this module sets the output filename for the generated library + // variants only + Source_stem *string `android:"arch_variant"` + + // crate name, used for the library variant of this source provider. See additional details in rust_library. + Crate_name string `android:"arch_variant"` } type baseSourceProvider struct { @@ -28,6 +33,7 @@ type baseSourceProvider struct { outputFile android.Path subAndroidMkOnce map[subAndroidMkProvider]bool + subName string } var _ SourceProvider = (*baseSourceProvider)(nil) @@ -37,6 +43,7 @@ type SourceProvider interface { Srcs() android.Paths sourceProviderProps() []interface{} sourceProviderDeps(ctx DepsContext, deps Deps) Deps + setSubName(subName string) } func (sp *baseSourceProvider) Srcs() android.Paths { @@ -59,8 +66,8 @@ func NewSourceProvider() *baseSourceProvider { func (sp *baseSourceProvider) getStem(ctx android.ModuleContext) string { stem := ctx.ModuleName() - if String(sp.Properties.Stem) != "" { - stem = String(sp.Properties.Stem) + if String(sp.Properties.Source_stem) != "" { + stem = String(sp.Properties.Source_stem) } return stem } @@ -68,3 +75,7 @@ func (sp *baseSourceProvider) getStem(ctx android.ModuleContext) string { func (sp *baseSourceProvider) sourceProviderDeps(ctx DepsContext, deps Deps) Deps { return deps } + +func (sp *baseSourceProvider) setSubName(subName string) { + sp.subName = subName +} diff --git a/rust/testing.go b/rust/testing.go index f2d4c5eba..83b2828e5 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -77,6 +77,7 @@ func GatherRequiredDepsForTest() string { func CreateTestContext() *android.TestContext { ctx := android.NewTestArchContext() + android.RegisterPrebuiltMutators(ctx) cc.RegisterRequiredBuildComponentsForTest(ctx) ctx.RegisterModuleType("genrule", genrule.GenRuleFactory) ctx.RegisterModuleType("rust_binary", RustBinaryFactory) diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh index 1bc78e6ba..c7baca70d 100755 --- a/scripts/build-mainline-modules.sh +++ b/scripts/build-mainline-modules.sh @@ -24,7 +24,6 @@ MODULES_SDK_AND_EXPORTS=( i18n-module-test-exports i18n-module-sdk platform-mainline-sdk - platform-mainline-host-exports ) # List of libraries installed on the platform that are needed for ART chroot @@ -52,6 +51,13 @@ echo_and_run() { "$@" } +lib_dir() { + case $1 in + (aosp_arm|aosp_x86) echo "lib";; + (aosp_arm64|aosp_x86_64) echo "lib64";; + esac +} + OUT_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var OUT_DIR) DIST_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var DIST_DIR) @@ -69,7 +75,8 @@ for product in "${PRODUCTS[@]}"; do echo_and_run cp ${PWD}/${PRODUCT_OUT}/system/apex/${module}.apex ${DIST_DIR}/${TARGET_ARCH}/ done for library in "${PLATFORM_LIBRARIES[@]}"; do - echo_and_run cp ${PWD}/${PRODUCT_OUT}/system/lib/${library}.so ${DIST_DIR}/${TARGET_ARCH}/ + libdir=$(lib_dir $product) + echo_and_run cp ${PWD}/${PRODUCT_OUT}/system/${libdir}/${library}.so ${DIST_DIR}/${TARGET_ARCH}/ done done diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go index 497f14bde..17afdb804 100644 --- a/sdk/cc_sdk_test.go +++ b/sdk/cc_sdk_test.go @@ -73,7 +73,6 @@ func TestSdkCompileMultilibOverride(t *testing.T) { result := testSdkWithCc(t, ` sdk { name: "mysdk", - device_supported: false, host_supported: true, native_shared_libs: ["sdkmember"], compile_multilib: "64", @@ -81,7 +80,6 @@ func TestSdkCompileMultilibOverride(t *testing.T) { cc_library_shared { name: "sdkmember", - device_supported: false, host_supported: true, srcs: ["Test.cpp"], stl: "none", @@ -96,14 +94,16 @@ func TestSdkCompileMultilibOverride(t *testing.T) { cc_prebuilt_library_shared { name: "mysdk_sdkmember@current", sdk_member_name: "sdkmember", - device_supported: false, host_supported: true, installable: false, stl: "none", compile_multilib: "64", - arch: { - x86_64: { - srcs: ["x86_64/lib/sdkmember.so"], + target: { + android_arm64: { + srcs: ["android/arm64/lib/sdkmember.so"], + }, + linux_glibc_x86_64: { + srcs: ["linux_glibc/x86_64/lib/sdkmember.so"], }, }, } @@ -111,31 +111,29 @@ cc_prebuilt_library_shared { cc_prebuilt_library_shared { name: "sdkmember", prefer: false, - device_supported: false, host_supported: true, stl: "none", compile_multilib: "64", - arch: { - x86_64: { - srcs: ["x86_64/lib/sdkmember.so"], + target: { + android_arm64: { + srcs: ["android/arm64/lib/sdkmember.so"], + }, + linux_glibc_x86_64: { + srcs: ["linux_glibc/x86_64/lib/sdkmember.so"], }, }, } sdk_snapshot { name: "mysdk@current", - device_supported: false, host_supported: true, native_shared_libs: ["mysdk_sdkmember@current"], - target: { - linux_glibc: { - compile_multilib: "64", - }, - }, + compile_multilib: "64", } `), checkAllCopyRules(` -.intermediates/sdkmember/linux_glibc_x86_64_shared/sdkmember.so -> x86_64/lib/sdkmember.so +.intermediates/sdkmember/android_arm64_armv8-a_shared/sdkmember.so -> android/arm64/lib/sdkmember.so +.intermediates/sdkmember/linux_glibc_x86_64_shared/sdkmember.so -> linux_glibc/x86_64/lib/sdkmember.so `)) } @@ -1527,11 +1525,7 @@ module_exports_snapshot { device_supported: false, host_supported: true, native_static_libs: ["myexports_mynativelib@current"], - target: { - linux_glibc: { - compile_multilib: "64", - }, - }, + compile_multilib: "64", }`), checkAllCopyRules(` include/Test.h -> include/include/Test.h diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index a2198e97b..931ca3c56 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -204,8 +204,8 @@ func TestBasicSdkWithJavaLibrary(t *testing.T) { } `) - sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common_myapex").Rule("combineJar").Output - sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common_myapex2").Rule("combineJar").Output + sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common").Rule("combineJar").Output + sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common").Rule("combineJar").Output javalibForMyApex := result.ctx.ModuleForTests("myjavalib", "android_common_myapex") javalibForMyApex2 := result.ctx.ModuleForTests("myjavalib", "android_common_myapex2") diff --git a/sdk/sdk.go b/sdk/sdk.go index 3e760080e..759102028 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -406,13 +406,17 @@ func memberInterVersionMutator(mctx android.BottomUpMutatorContext) { // Step 4: transitively ripple down the SDK requirements from the root modules like APEX to its // descendants func sdkDepsMutator(mctx android.TopDownMutatorContext) { - if m, ok := mctx.Module().(android.SdkAware); ok { + if parent, ok := mctx.Module().(interface { + android.DepIsInSameApex + android.RequiredSdks + }); ok { // Module types for Mainline modules (e.g. APEX) are expected to implement RequiredSdks() // by reading its own properties like `uses_sdks`. - requiredSdks := m.RequiredSdks() + requiredSdks := parent.RequiredSdks() if len(requiredSdks) > 0 { mctx.VisitDirectDeps(func(m android.Module) { - if dep, ok := m.(android.SdkAware); ok { + // Only propagate required sdks from the apex onto its contents. + if dep, ok := m.(android.SdkAware); ok && parent.DepIsInSameApex(mctx, dep) { dep.BuildWithSdks(requiredSdks) } }) @@ -423,15 +427,28 @@ func sdkDepsMutator(mctx android.TopDownMutatorContext) { // Step 5: if libfoo.mysdk.11 is in the context where version 11 of mysdk is requested, the // versioned module is used instead of the un-versioned (in-development) module libfoo func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) { - if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() { - if sdk := m.ContainingSdk(); !sdk.Unversioned() { - if m.RequiredSdks().Contains(sdk) { - // Note that this replacement is done only for the modules that have the same - // variations as the current module. Since current module is already mutated for - // apex references in other APEXes are not affected by this replacement. - memberName := m.MemberName() - mctx.ReplaceDependencies(memberName) - } + if versionedSdkMember, ok := mctx.Module().(android.SdkAware); ok && versionedSdkMember.IsInAnySdk() { + if sdk := versionedSdkMember.ContainingSdk(); !sdk.Unversioned() { + // Only replace dependencies to <sdkmember> with <sdkmember@required-version> + // if the depending module requires it. e.g. + // foo -> sdkmember + // will be transformed to: + // foo -> sdkmember@1 + // if and only if foo is a member of an APEX that requires version 1 of the + // sdk containing sdkmember. + memberName := versionedSdkMember.MemberName() + + // Replace dependencies on sdkmember with a dependency on the current module which + // is a versioned prebuilt of the sdkmember if required. + mctx.ReplaceDependenciesIf(memberName, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool { + // from - foo + // to - sdkmember + replace := false + if parent, ok := from.(android.RequiredSdks); ok { + replace = parent.RequiredSdks().Contains(sdk) + } + return replace + }) } } } diff --git a/sdk/testing.go b/sdk/testing.go index 34ea8f0cc..b53558d9f 100644 --- a/sdk/testing.go +++ b/sdk/testing.go @@ -97,6 +97,11 @@ func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsTy ctx.PreArchMutators(android.RegisterVisibilityRuleChecker) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) ctx.PreArchMutators(android.RegisterComponentsMutator) + + android.RegisterPrebuiltMutators(ctx) + + // Register these after the prebuilt mutators have been registered to match what + // happens at runtime. ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer) ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer) diff --git a/sdk/update.go b/sdk/update.go index b8d73c63f..25d50d217 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -323,19 +323,37 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro // Add properties common to all os types. s.addMemberPropertiesToPropertySet(builder, snapshotModule, commonDynamicMemberProperties) + // Optimize other per-variant properties, besides the dynamic member lists. + type variantProperties struct { + Compile_multilib string `android:"arch_variant"` + } + var variantPropertiesContainers []propertiesContainer + variantToProperties := make(map[*sdk]*variantProperties) + for _, sdkVariant := range sdkVariants { + props := &variantProperties{ + Compile_multilib: sdkVariant.multilibUsages.String(), + } + variantPropertiesContainers = append(variantPropertiesContainers, &dynamicMemberPropertiesContainer{sdkVariant, props}) + variantToProperties[sdkVariant] = props + } + commonVariantProperties := variantProperties{} + extractor = newCommonValueExtractor(commonVariantProperties) + extractCommonProperties(ctx, extractor, &commonVariantProperties, variantPropertiesContainers) + if commonVariantProperties.Compile_multilib != "" && commonVariantProperties.Compile_multilib != "both" { + // Compile_multilib defaults to both so only needs to be set when it's + // specified and not both. + snapshotModule.AddProperty("compile_multilib", commonVariantProperties.Compile_multilib) + } + // Iterate over the os types in a fixed order. targetPropertySet := snapshotModule.AddPropertySet("target") for _, osType := range s.getPossibleOsTypes() { if sdkVariant, ok := osTypeToMemberProperties[osType]; ok { osPropertySet := targetPropertySet.AddPropertySet(sdkVariant.Target().Os.Name) - // Compile_multilib defaults to both and must always be set to both on the - // device and so only needs to be set when targeted at the host and is neither - // unspecified or both. - multilib := sdkVariant.multilibUsages - if (osType.Class == android.Host || osType.Class == android.HostCross) && - multilib != multilibNone && multilib != multilibBoth { - osPropertySet.AddProperty("compile_multilib", multilib.String()) + variantProps := variantToProperties[sdkVariant] + if variantProps.Compile_multilib != "" && variantProps.Compile_multilib != "both" { + osPropertySet.AddProperty("compile_multilib", variantProps.Compile_multilib) } s.addMemberPropertiesToPropertySet(builder, osPropertySet, sdkVariant.dynamicMemberTypeListProperties) diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go index 850338675..711129c84 100644 --- a/sysprop/sysprop_test.go +++ b/sysprop/sysprop_test.go @@ -67,6 +67,8 @@ func testContext(config android.Config) *android.TestContext { ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel() }) + android.RegisterPrebuiltMutators(ctx) + cc.RegisterRequiredBuildComponentsForTest(ctx) ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel() diff --git a/ui/build/config.go b/ui/build/config.go index ba477e61a..3fa047900 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -96,7 +96,7 @@ func NewConfig(ctx Context, args ...string) Config { environ: OsEnvironment(), } - // Sane default matching ninja + // Default matching ninja ret.parallel = runtime.NumCPU() + 2 ret.keepGoing = 1 diff --git a/ui/build/rbe_test.go b/ui/build/rbe_test.go index 2c4995b1d..23a53b449 100644 --- a/ui/build/rbe_test.go +++ b/ui/build/rbe_test.go @@ -94,12 +94,12 @@ func TestDumpRBEMetricsErrors(t *testing.T) { }, { description: "stopRBE failed", rbeOutputDirDefined: true, - bootstrapProgram: "#!/bin/bash\nexit 1", + bootstrapProgram: "#!/bin/bash\nexit 1\n", expectedErr: "shutdown failed", }, { description: "failed to copy metrics file", rbeOutputDirDefined: true, - bootstrapProgram: "#!/bin/bash", + bootstrapProgram: "#!/bin/bash\n", expectedErr: "failed to copy", }} @@ -139,4 +139,4 @@ func TestDumpRBEMetricsErrors(t *testing.T) { } } -var rbeBootstrapProgram = fmt.Sprintf("#!/bin/bash\necho 1 > $RBE_output_dir/%s", rbeMetricsPBFilename) +var rbeBootstrapProgram = fmt.Sprintf("#!/bin/bash\necho 1 > $RBE_output_dir/%s\n", rbeMetricsPBFilename) diff --git a/ui/build/upload.go b/ui/build/upload.go index 1cc2e940c..a9346e0c5 100644 --- a/ui/build/upload.go +++ b/ui/build/upload.go @@ -44,7 +44,7 @@ var ( // environment variable. The metrics files are copied to a temporary directory // and the uploader is then executed in the background to allow the user to continue // working. -func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStarted time.Time, files ...string) { +func UploadMetrics(ctx Context, config Config, simpleOutput bool, buildStarted time.Time, files ...string) { ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics") defer ctx.EndTrace() @@ -105,7 +105,7 @@ func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStarte // Start the uploader in the background as it takes several milliseconds to start the uploader // and prepare the metrics for upload. This affects small commands like "lunch". cmd := Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile) - if forceDumbOutput { + if simpleOutput { cmd.RunOrFatal() } else { cmd.RunAndStreamOrFatal() diff --git a/ui/terminal/Android.bp b/ui/terminal/Android.bp index b533b0d30..aa6e35d2b 100644 --- a/ui/terminal/Android.bp +++ b/ui/terminal/Android.bp @@ -17,7 +17,7 @@ bootstrap_go_package { pkgPath: "android/soong/ui/terminal", deps: ["soong-ui-status"], srcs: [ - "dumb_status.go", + "simple_status.go", "format.go", "smart_status.go", "status.go", diff --git a/ui/terminal/dumb_status.go b/ui/terminal/simple_status.go index 201770fac..4e8c56804 100644 --- a/ui/terminal/dumb_status.go +++ b/ui/terminal/simple_status.go @@ -21,31 +21,31 @@ import ( "android/soong/ui/status" ) -type dumbStatusOutput struct { +type simpleStatusOutput struct { writer io.Writer formatter formatter } -// NewDumbStatusOutput returns a StatusOutput that represents the +// NewSimpleStatusOutput returns a StatusOutput that represents the // current build status similarly to Ninja's built-in terminal // output. -func NewDumbStatusOutput(w io.Writer, formatter formatter) status.StatusOutput { - return &dumbStatusOutput{ +func NewSimpleStatusOutput(w io.Writer, formatter formatter) status.StatusOutput { + return &simpleStatusOutput{ writer: w, formatter: formatter, } } -func (s *dumbStatusOutput) Message(level status.MsgLevel, message string) { +func (s *simpleStatusOutput) Message(level status.MsgLevel, message string) { if level >= status.StatusLvl { fmt.Fprintln(s.writer, s.formatter.message(level, message)) } } -func (s *dumbStatusOutput) StartAction(action *status.Action, counts status.Counts) { +func (s *simpleStatusOutput) StartAction(action *status.Action, counts status.Counts) { } -func (s *dumbStatusOutput) FinishAction(result status.ActionResult, counts status.Counts) { +func (s *simpleStatusOutput) FinishAction(result status.ActionResult, counts status.Counts) { str := result.Description if str == "" { str = result.Command @@ -63,9 +63,9 @@ func (s *dumbStatusOutput) FinishAction(result status.ActionResult, counts statu } } -func (s *dumbStatusOutput) Flush() {} +func (s *simpleStatusOutput) Flush() {} -func (s *dumbStatusOutput) Write(p []byte) (int, error) { +func (s *simpleStatusOutput) Write(p []byte) (int, error) { fmt.Fprint(s.writer, string(p)) return len(p), nil } diff --git a/ui/terminal/status.go b/ui/terminal/status.go index 60dfc7025..d8e739211 100644 --- a/ui/terminal/status.go +++ b/ui/terminal/status.go @@ -26,12 +26,12 @@ import ( // // statusFormat takes nearly all the same options as NINJA_STATUS. // %c is currently unsupported. -func NewStatusOutput(w io.Writer, statusFormat string, forceDumbOutput, quietBuild bool) status.StatusOutput { +func NewStatusOutput(w io.Writer, statusFormat string, forceSimpleOutput, quietBuild bool) status.StatusOutput { formatter := newFormatter(statusFormat, quietBuild) - if !forceDumbOutput && isSmartTerminal(w) { + if !forceSimpleOutput && isSmartTerminal(w) { return NewSmartStatusOutput(w, formatter) } else { - return NewDumbStatusOutput(w, formatter) + return NewSimpleStatusOutput(w, formatter) } } diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go index 9f6082988..aa69dff53 100644 --- a/ui/terminal/status_test.go +++ b/ui/terminal/status_test.go @@ -26,64 +26,64 @@ import ( func TestStatusOutput(t *testing.T) { tests := []struct { - name string - calls func(stat status.StatusOutput) - smart string - dumb string + name string + calls func(stat status.StatusOutput) + smart string + simple string }{ { - name: "two actions", - calls: twoActions, - smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n", - dumb: "[ 50% 1/2] action1\n[100% 2/2] action2\n", + name: "two actions", + calls: twoActions, + smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n", + simple: "[ 50% 1/2] action1\n[100% 2/2] action2\n", }, { - name: "two parallel actions", - calls: twoParallelActions, - smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 0% 0/2] action2\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n", - dumb: "[ 50% 1/2] action1\n[100% 2/2] action2\n", + name: "two parallel actions", + calls: twoParallelActions, + smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 0% 0/2] action2\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n", + simple: "[ 50% 1/2] action1\n[100% 2/2] action2\n", }, { - name: "action with output", - calls: actionsWithOutput, - smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n", - dumb: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n", + name: "action with output", + calls: actionsWithOutput, + smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n", + simple: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n", }, { - name: "action with output without newline", - calls: actionsWithOutputWithoutNewline, - smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n", - dumb: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n", + name: "action with output without newline", + calls: actionsWithOutputWithoutNewline, + smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\noutput1\noutput2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n", + simple: "[ 33% 1/3] action1\n[ 66% 2/3] action2\noutput1\noutput2\n[100% 3/3] action3\n", }, { - name: "action with error", - calls: actionsWithError, - smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n", - dumb: "[ 33% 1/3] action1\n[ 66% 2/3] action2\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n[100% 3/3] action3\n", + name: "action with error", + calls: actionsWithError, + smart: "\r\x1b[1m[ 0% 0/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action1\x1b[0m\x1b[K\r\x1b[1m[ 33% 1/3] action2\x1b[0m\x1b[K\r\x1b[1m[ 66% 2/3] action2\x1b[0m\x1b[K\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n\r\x1b[1m[ 66% 2/3] action3\x1b[0m\x1b[K\r\x1b[1m[100% 3/3] action3\x1b[0m\x1b[K\n", + simple: "[ 33% 1/3] action1\n[ 66% 2/3] action2\nFAILED: f1 f2\ntouch f1 f2\nerror1\nerror2\n[100% 3/3] action3\n", }, { - name: "action with empty description", - calls: actionWithEmptyDescription, - smart: "\r\x1b[1m[ 0% 0/1] command1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] command1\x1b[0m\x1b[K\n", - dumb: "[100% 1/1] command1\n", + name: "action with empty description", + calls: actionWithEmptyDescription, + smart: "\r\x1b[1m[ 0% 0/1] command1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] command1\x1b[0m\x1b[K\n", + simple: "[100% 1/1] command1\n", }, { - name: "messages", - calls: actionsWithMessages, - smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1mstatus\x1b[0m\x1b[K\r\x1b[Kprint\nFAILED: error\n\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n", - dumb: "[ 50% 1/2] action1\nstatus\nprint\nFAILED: error\n[100% 2/2] action2\n", + name: "messages", + calls: actionsWithMessages, + smart: "\r\x1b[1m[ 0% 0/2] action1\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action1\x1b[0m\x1b[K\r\x1b[1mstatus\x1b[0m\x1b[K\r\x1b[Kprint\nFAILED: error\n\r\x1b[1m[ 50% 1/2] action2\x1b[0m\x1b[K\r\x1b[1m[100% 2/2] action2\x1b[0m\x1b[K\n", + simple: "[ 50% 1/2] action1\nstatus\nprint\nFAILED: error\n[100% 2/2] action2\n", }, { - name: "action with long description", - calls: actionWithLongDescription, - smart: "\r\x1b[1m[ 0% 0/2] action with very long descrip\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action with very long descrip\x1b[0m\x1b[K\n", - dumb: "[ 50% 1/2] action with very long description to test eliding\n", + name: "action with long description", + calls: actionWithLongDescription, + smart: "\r\x1b[1m[ 0% 0/2] action with very long descrip\x1b[0m\x1b[K\r\x1b[1m[ 50% 1/2] action with very long descrip\x1b[0m\x1b[K\n", + simple: "[ 50% 1/2] action with very long description to test eliding\n", }, { - name: "action with output with ansi codes", - calls: actionWithOuptutWithAnsiCodes, - smart: "\r\x1b[1m[ 0% 0/1] action1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] action1\x1b[0m\x1b[K\n\x1b[31mcolor\x1b[0m\n", - dumb: "[100% 1/1] action1\ncolor\n", + name: "action with output with ansi codes", + calls: actionWithOuptutWithAnsiCodes, + smart: "\r\x1b[1m[ 0% 0/1] action1\x1b[0m\x1b[K\r\x1b[1m[100% 1/1] action1\x1b[0m\x1b[K\n\x1b[31mcolor\x1b[0m\n", + simple: "[100% 1/1] action1\ncolor\n", }, } @@ -103,24 +103,24 @@ func TestStatusOutput(t *testing.T) { } }) - t.Run("dumb", func(t *testing.T) { - dumb := &bytes.Buffer{} - stat := NewStatusOutput(dumb, "", false, false) + t.Run("simple", func(t *testing.T) { + simple := &bytes.Buffer{} + stat := NewStatusOutput(simple, "", false, false) tt.calls(stat) stat.Flush() - if g, w := dumb.String(), tt.dumb; g != w { + if g, w := simple.String(), tt.simple; g != w { t.Errorf("want:\n%q\ngot:\n%q", w, g) } }) - t.Run("force dumb", func(t *testing.T) { + t.Run("force simple", func(t *testing.T) { smart := &fakeSmartTerminal{termWidth: 40} stat := NewStatusOutput(smart, "", true, false) tt.calls(stat) stat.Flush() - if g, w := smart.String(), tt.dumb; g != w { + if g, w := smart.String(), tt.simple; g != w { t.Errorf("want:\n%q\ngot:\n%q", w, g) } }) |