diff options
35 files changed, 913 insertions, 89 deletions
@@ -1,13 +1,33 @@ # Soong -Soong is the replacement for the old Android make-based build system. It -replaces Android.mk files with Android.bp files, which are JSON-like simple -declarative descriptions of modules to build. +Soong is one of the build systems used in Android. There are altogether three: +* The legacy Make-based build system that is controlled by files called + `Android.mk`. +* Soong, which is controlled by files called `Android.bp`. +* The upcoming Bazel-based build system that is controlled by files called + `BUILD.bazel`. + +`Android.bp` file are JSON-like declarative descriptions of "modules" to build; +a "module" is the basic unit of building that Soong understands, similarly to +how "target" is the basic unit of building for Bazel (and Make, although the +two kinds of "targets" are very different) See [Simple Build Configuration](https://source.android.com/compatibility/tests/development/blueprints) on source.android.com to read how Soong is configured for testing. +### Contributing + +Code reviews are handled through the usual code review system of Android, +available [here](https://android-review.googlesource.com/dashboard/self). + +For simple changes (fixing typos, obvious optimizations, etc.), sending a code +review request is enough. For more substantial changes, file a bug in our +[bug tracker](https://issuetracker.google.com/issues/new?component=381517) or +or write us at android-building@googlegroups.com . + +For Googlers, see our [internal documentation](http://go/soong). + ## Android.bp file format By design, Android.bp files are very simple. There are no conditionals or diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index 03ce0f16b..9b284fca5 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -284,6 +284,7 @@ var ( "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively, "system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively, "system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively, + "system/extras/toolchain-extras": Bp2BuildDefaultTrue, "system/incremental_delivery/incfs": Bp2BuildDefaultTrue, "system/libartpalette": Bp2BuildDefaultTrueRecursively, "system/libbase": Bp2BuildDefaultTrueRecursively, diff --git a/android/api_domain.go b/android/api_domain.go index 787665475..0993e3d84 100644 --- a/android/api_domain.go +++ b/android/api_domain.go @@ -73,9 +73,9 @@ func ApiDomainFactory() Module { func (a *apiDomain) DepsMutator(ctx BottomUpMutatorContext) { for _, cc := range a.properties.Cc_api_contributions { // Use FarVariationDependencies since the variants of api_domain is a subset of the variants of the dependency cc module - // Creating a dependency on the first variant is ok since this is a no-op in Soong + // Creating a dependency on the first variant that matches (os,arch) is ok since this is a no-op in Soong // The primary function of this dependency is to create a connected graph in the corresponding bp2build workspace - ctx.AddFarVariationDependencies([]blueprint.Variation{}, nil, cc) + ctx.AddFarVariationDependencies(ctx.Target().Variations(), nil, cc) } } diff --git a/android/module.go b/android/module.go index 68d9f8e75..c099e6d15 100644 --- a/android/module.go +++ b/android/module.go @@ -915,9 +915,16 @@ type commonProperties struct { type CommonAttributes struct { // Soong nameProperties -> Bazel name Name string + // Data mapped from: Required Data bazel.LabelListAttribute + // SkipData is neither a Soong nor Bazel target attribute + // If true, this will not fill the data attribute automatically + // This is useful for Soong modules that have 1:many Bazel targets + // Some of the generated Bazel targets might not have a data attribute + SkipData *bool + Tags bazel.StringListAttribute Applicable_licenses bazel.LabelListAttribute @@ -1305,7 +1312,12 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator platformEnabledAttribute.Add(&l) } - attrs.Data.Append(required) + if !proptools.Bool(attrs.SkipData) { + attrs.Data.Append(required) + } + // SkipData is not an attribute of any Bazel target + // Set this to nil so that it does not appear in the generated build file + attrs.SkipData = nil moduleEnableConstraints := bazel.LabelListAttribute{} moduleEnableConstraints.Append(platformEnabledAttribute) diff --git a/android/neverallow.go b/android/neverallow.go index 00078a025..1cdccc317 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -58,6 +58,7 @@ func init() { AddNeverAllowRules(createMakefileGoalRules()...) AddNeverAllowRules(createInitFirstStageRules()...) AddNeverAllowRules(createProhibitFrameworkAccessRules()...) + AddNeverAllowRules(createBp2BuildRule()) } // Add a NeverAllow rule to the set of rules to apply. @@ -65,6 +66,13 @@ func AddNeverAllowRules(rules ...Rule) { neverallows = append(neverallows, rules...) } +func createBp2BuildRule() Rule { + return NeverAllow(). + With("bazel_module.bp2build_available", "true"). + Because("setting bp2build_available in Android.bp is not " + + "supported for custom conversion, use allowlists.go instead.") +} + func createIncludeDirsRules() []Rule { notInIncludeDir := []string{ "art", diff --git a/apex/key.go b/apex/key.go index d44958928..2b09f1d1b 100644 --- a/apex/key.go +++ b/apex/key.go @@ -44,8 +44,6 @@ type apexKey struct { publicKeyFile android.Path privateKeyFile android.Path - - keyName string } type apexKeyProperties struct { @@ -102,7 +100,6 @@ func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) { m.publicKeyFile.String(), pubKeyName, m.privateKeyFile, privKeyName) return } - m.keyName = pubKeyName } // ////////////////////////////////////////////////////////////////////// @@ -203,8 +200,11 @@ func (s *apexKeysText) MakeVars(ctx android.MakeVarsContext) { // For Bazel / bp2build type bazelApexKeyAttributes struct { - Public_key bazel.LabelAttribute - Private_key bazel.LabelAttribute + Public_key bazel.LabelAttribute + Public_key_name bazel.LabelAttribute + + Private_key bazel.LabelAttribute + Private_key_name bazel.LabelAttribute } // ConvertWithBp2build performs conversion apexKey for bp2build @@ -214,18 +214,33 @@ func (m *apexKey) ConvertWithBp2build(ctx android.TopDownMutatorContext) { func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) { var privateKeyLabelAttribute bazel.LabelAttribute + var privateKeyNameAttribute bazel.LabelAttribute if module.properties.Private_key != nil { - privateKeyLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Private_key)) + m := String(module.properties.Private_key) + if android.SrcIsModule(m) == "" { + privateKeyNameAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Private_key)) + } else { + privateKeyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.properties.Private_key)) + } } var publicKeyLabelAttribute bazel.LabelAttribute + var publicKeyNameAttribute bazel.LabelAttribute if module.properties.Public_key != nil { - publicKeyLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Public_key)) + m := String(module.properties.Public_key) + if android.SrcIsModule(m) == "" { + publicKeyNameAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Public_key)) + } else { + publicKeyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.properties.Public_key)) + } } attrs := &bazelApexKeyAttributes{ - Private_key: privateKeyLabelAttribute, - Public_key: publicKeyLabelAttribute, + Private_key: privateKeyLabelAttribute, + Private_key_name: privateKeyNameAttribute, + + Public_key: publicKeyLabelAttribute, + Public_key_name: publicKeyNameAttribute, } props := bazel.BazelTargetModuleProperties{ diff --git a/bazel/properties.go b/bazel/properties.go index c329e4197..823cda8b2 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -73,6 +73,17 @@ func MakeLabelList(labels []Label) LabelList { } } +// MakeLabelListFromTargetNames creates a LabelList from unqualified target names +// This is a utiltity function for bp2build converters of Soong modules that have 1:many generated targets +func MakeLabelListFromTargetNames(targetNames []string) LabelList { + labels := []Label{} + for _, name := range targetNames { + label := Label{Label: ":" + name} + labels = append(labels, label) + } + return MakeLabelList(labels) +} + func (ll *LabelList) Equals(other LabelList) bool { if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) { return false @@ -1178,6 +1189,11 @@ type StringListAttribute struct { ConfigurableValues configurableStringLists } +// IsEmpty returns true if the attribute has no values under any configuration. +func (sla StringListAttribute) IsEmpty() bool { + return len(sla.Value) == 0 && !sla.HasConfigurableValues() +} + type configurableStringLists map[ConfigurationAxis]stringListSelectValues func (csl configurableStringLists) Append(other configurableStringLists) { diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go index 15bccf742..79b1d89d1 100644 --- a/bp2build/apex_key_conversion_test.go +++ b/bp2build/apex_key_conversion_test.go @@ -27,11 +27,12 @@ func runApexKeyTestCase(t *testing.T, tc Bp2buildTestCase) { } func registerApexKeyModuleTypes(ctx android.RegistrationContext) { + ctx.RegisterModuleType("filegroup", android.FileGroupFactory) } -func TestApexKeySimple(t *testing.T) { +func TestApexKeySimple_KeysAreSrcFiles(t *testing.T) { runApexKeyTestCase(t, Bp2buildTestCase{ - Description: "apex key - simple example", + Description: "apex key - keys are src files, use key_name attributes", ModuleTypeUnderTest: "apex_key", ModuleTypeUnderTestFactory: apex.ApexKeyFactory, Filesystem: map[string]string{}, @@ -43,8 +44,29 @@ apex_key { } `, ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{ - "private_key": `"com.android.apogee.pem"`, - "public_key": `"com.android.apogee.avbpubkey"`, + "private_key_name": `"com.android.apogee.pem"`, + "public_key_name": `"com.android.apogee.avbpubkey"`, + }), + }}) +} + +func TestApexKey_KeysAreModules(t *testing.T) { + runApexKeyTestCase(t, Bp2buildTestCase{ + Description: "apex key - keys are modules, use key attributes", + ModuleTypeUnderTest: "apex_key", + ModuleTypeUnderTestFactory: apex.ApexKeyFactory, + Filesystem: map[string]string{}, + Blueprint: ` +apex_key { + name: "com.android.apogee.key", + public_key: ":com.android.apogee.avbpubkey", + private_key: ":com.android.apogee.pem", +} +` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.avbpubkey") + + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.pem"), + ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{ + "private_key": `":com.android.apogee.pem"`, + "public_key": `":com.android.apogee.avbpubkey"`, }), }}) } diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go index 72d3940c4..8aa2c3ecb 100644 --- a/bp2build/cc_binary_conversion_test.go +++ b/bp2build/cc_binary_conversion_test.go @@ -228,6 +228,38 @@ func TestCcBinaryVersionScriptAndDynamicList(t *testing.T) { }) } +func TestCcBinaryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)", + blueprint: ` +{rule_name} { + name: "foo", + ldflags: [ + "--nospace_flag", + "-z spaceflag", + ], + version_script: "version_script", + dynamic_list: "dynamic.list", + include_build_directory: false, +} +`, + targets: []testBazelTarget{ + {"cc_binary", "foo", AttrNameToString{ + "additional_linker_inputs": `[ + "version_script", + "dynamic.list", + ]`, + "linkopts": `[ + "--nospace_flag", + "-z", + "spaceflag", + "-Wl,--version-script,$(location version_script)", + "-Wl,--dynamic-list,$(location dynamic.list)", + ]`, + }}}, + }) +} + func TestCcBinarySplitSrcsByLang(t *testing.T) { runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{ description: "split srcs by lang", diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 728a4dc5f..0d6d5b87e 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -961,6 +961,46 @@ cc_library { ) } +func TestCcLibraryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + Description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Filesystem: map[string]string{ + "version_script": "", + "dynamic.list": "", + }, + Blueprint: ` +cc_library { + name: "foo", + ldflags: [ + "--nospace_flag", + "-z spaceflag", + ], + version_script: "version_script", + dynamic_list: "dynamic.list", + include_build_directory: false, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}), + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "additional_linker_inputs": `[ + "version_script", + "dynamic.list", + ]`, + "linkopts": `[ + "--nospace_flag", + "-z", + "spaceflag", + "-Wl,--version-script,$(location version_script)", + "-Wl,--dynamic-list,$(location dynamic.list)", + ]`, + }), + }, + }) +} + func TestCcLibrarySharedLibs(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ Description: "cc_library shared_libs", @@ -2703,6 +2743,205 @@ cc_library { ) } +func TestCcApiContributionsWithHdrs(t *testing.T) { + bp := ` + cc_library { + name: "libfoo", + stubs: { symbol_file: "libfoo.map.txt", versions: ["28", "29", "current"] }, + llndk: { symbol_file: "libfoo.map.txt", override_export_include_dirs: ["dir2"]}, + export_include_dirs: ["dir1"], + } + ` + expectedBazelTargets := []string{ + MakeBazelTarget( + "cc_api_library_headers", + "libfoo.systemapi.headers", + AttrNameToString{ + "export_includes": `["dir1"]`, + }), + MakeBazelTarget( + "cc_api_library_headers", + "libfoo.vendorapi.headers", + AttrNameToString{ + "export_includes": `["dir2"]`, + }), + MakeBazelTarget( + "cc_api_contribution", + "libfoo.contribution", + AttrNameToString{ + "api": `"libfoo.map.txt"`, + "library_name": `"libfoo"`, + "api_surfaces": `[ + "systemapi", + "vendorapi", + ]`, + "hdrs": `[ + ":libfoo.systemapi.headers", + ":libfoo.vendorapi.headers", + ]`, + }), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{ + Blueprint: bp, + Description: "cc API contributions to systemapi and vendorapi", + ExpectedBazelTargets: expectedBazelTargets, + }) +} + +func TestCcApiSurfaceCombinations(t *testing.T) { + testCases := []struct { + bp string + expectedApi string + expectedApiSurfaces string + description string + }{ + { + bp: ` + cc_library { + name: "a", + stubs: {symbol_file: "a.map.txt"}, + }`, + expectedApi: `"a.map.txt"`, + expectedApiSurfaces: `["systemapi"]`, + description: "Library that contributes to systemapi", + }, + { + bp: ` + cc_library { + name: "a", + llndk: {symbol_file: "a.map.txt"}, + }`, + expectedApi: `"a.map.txt"`, + expectedApiSurfaces: `["vendorapi"]`, + description: "Library that contributes to vendorapi", + }, + { + bp: ` + cc_library { + name: "a", + llndk: {symbol_file: "a.map.txt"}, + stubs: {symbol_file: "a.map.txt"}, + }`, + expectedApi: `"a.map.txt"`, + expectedApiSurfaces: `[ + "systemapi", + "vendorapi", + ]`, + description: "Library that contributes to systemapi and vendorapi", + }, + } + for _, testCase := range testCases { + expectedBazelTargets := []string{ + MakeBazelTarget( + "cc_api_contribution", + "a.contribution", + AttrNameToString{ + "library_name": `"a"`, + "hdrs": `[]`, + "api": testCase.expectedApi, + "api_surfaces": testCase.expectedApiSurfaces, + }, + ), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{ + Blueprint: testCase.bp, + Description: testCase.description, + ExpectedBazelTargets: expectedBazelTargets, + }) + } +} + +// llndk struct property in Soong provides users with several options to configure the exported include dirs +// Test the generated bazel targets for the different configurations +func TestCcVendorApiHeaders(t *testing.T) { + testCases := []struct { + bp string + expectedIncludes string + expectedSystemIncludes string + description string + }{ + { + bp: ` + cc_library { + name: "a", + export_include_dirs: ["include"], + export_system_include_dirs: ["base_system_include"], + llndk: { + symbol_file: "a.map.txt", + export_headers_as_system: true, + }, + } + `, + expectedIncludes: "", + expectedSystemIncludes: `[ + "base_system_include", + "include", + ]`, + description: "Headers are exported as system to API surface", + }, + { + bp: ` + cc_library { + name: "a", + export_include_dirs: ["include"], + export_system_include_dirs: ["base_system_include"], + llndk: { + symbol_file: "a.map.txt", + override_export_include_dirs: ["llndk_include"], + }, + } + `, + expectedIncludes: `["llndk_include"]`, + expectedSystemIncludes: `["base_system_include"]`, + description: "Non-system Headers are ovverriden before export to API surface", + }, + { + bp: ` + cc_library { + name: "a", + export_include_dirs: ["include"], + export_system_include_dirs: ["base_system_include"], + llndk: { + symbol_file: "a.map.txt", + override_export_include_dirs: ["llndk_include"], + export_headers_as_system: true, + }, + } + `, + expectedIncludes: "", // includes are set to nil + expectedSystemIncludes: `[ + "base_system_include", + "llndk_include", + ]`, + description: "System Headers are extended before export to API surface", + }, + } + for _, testCase := range testCases { + attrs := AttrNameToString{} + if testCase.expectedIncludes != "" { + attrs["export_includes"] = testCase.expectedIncludes + } + if testCase.expectedSystemIncludes != "" { + attrs["export_system_includes"] = testCase.expectedSystemIncludes + } + + expectedBazelTargets := []string{ + MakeBazelTarget("cc_api_library_headers", "a.vendorapi.headers", attrs), + // Create a target for cc_api_contribution target + MakeBazelTarget("cc_api_contribution", "a.contribution", AttrNameToString{ + "api": `"a.map.txt"`, + "api_surfaces": `["vendorapi"]`, + "hdrs": `[":a.vendorapi.headers"]`, + "library_name": `"a"`, + }), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{ + Blueprint: testCase.bp, + ExpectedBazelTargets: expectedBazelTargets, + }) + } +} + func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ Description: "stub target generation of the same lib across configs should not result in duplicates", diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go index 5fa7cac5e..7d9db6fe2 100644 --- a/bp2build/cc_library_headers_conversion_test.go +++ b/bp2build/cc_library_headers_conversion_test.go @@ -123,6 +123,69 @@ cc_library_headers { }) } +func TestCcApiHeaders(t *testing.T) { + fs := map[string]string{ + "bar/Android.bp": `cc_library_headers { name: "bar_headers", }`, + } + bp := ` + cc_library_headers { + name: "foo_headers", + export_include_dirs: ["dir1", "dir2"], + export_header_lib_headers: ["bar_headers"], + + arch: { + arm: { + export_include_dirs: ["dir_arm"], + }, + x86: { + export_include_dirs: ["dir_x86"], + }, + }, + + target: { + android: { + export_include_dirs: ["dir1", "dir_android"], + }, + windows: { + export_include_dirs: ["dir_windows"], + }, + } + } + ` + expectedBazelTargets := []string{ + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.arm", AttrNameToString{ + "export_includes": `["dir_arm"]`, + "arch": `"arm"`, + }), + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.x86", AttrNameToString{ + "export_includes": `["dir_x86"]`, + "arch": `"x86"`, + }), + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.androidos", AttrNameToString{ + "export_includes": `["dir_android"]`, // common includes are deduped + }), + // Windows headers are not exported + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution", AttrNameToString{ + "export_includes": `[ + "dir1", + "dir2", + ]`, + "deps": `[ + "//bar:bar_headers.contribution", + ":foo_headers.contribution.arm", + ":foo_headers.contribution.x86", + ":foo_headers.contribution.androidos", + ]`, + }), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryHeadersBuildComponents, Bp2buildTestCase{ + Blueprint: bp, + Description: "Header library contributions to API surfaces", + ExpectedBazelTargets: expectedBazelTargets, + Filesystem: fs, + }) +} + func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ Description: "cc_library_headers test with os-specific header_libs props", diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 6253de6c7..b86f60778 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -367,6 +367,42 @@ cc_library_shared { }) } +func TestCcLibraryLdflagsSplitBySpaceSoongAdded(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)", + Filesystem: map[string]string{ + "version_script": "", + "dynamic.list": "", + }, + Blueprint: ` +cc_library_shared { + name: "foo", + ldflags: [ + "--nospace_flag", + "-z spaceflag", + ], + version_script: "version_script", + dynamic_list: "dynamic.list", + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "additional_linker_inputs": `[ + "version_script", + "dynamic.list", + ]`, + "linkopts": `[ + "--nospace_flag", + "-z", + "spaceflag", + "-Wl,--version-script,$(location version_script)", + "-Wl,--dynamic-list,$(location dynamic.list)", + ]`, + }), + }, + }) +} + func TestCcLibrarySharedNoCrtTrue(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ Description: "cc_library_shared - nocrt: true emits attribute", diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go index 023ec9687..7c39a118b 100644 --- a/bp2build/symlink_forest.go +++ b/bp2build/symlink_forest.go @@ -285,6 +285,17 @@ func plantSymlinkForestRecursive(cfg android.Config, topdir string, forestDir st // Neither is a directory. Merge them. srcBuildFile := shared.JoinPath(topdir, srcChild) generatedBuildFile := shared.JoinPath(topdir, buildFilesChild) + // Add the src and generated build files as dependencies so that bp2build + // is rerun when they change. Currently, this is only really necessary + // for srcBuildFile, because if we regenerate the generated build files + // we will always rerun the symlink forest generation as well. If that + // is later split up into separate, fully dependency-tracing steps, then + // we'll need srcBuildFile as well. Adding srcBuildFile here today + // technically makes it a dependency of bp2build_workspace_marker, which + // also implicitly outputs that file, but since bp2build_workspace_marker + // will always have a newer timestamp than the generatedBuildFile it + // shouldn't be a problem. + *acc = append(*acc, srcBuildFile, generatedBuildFile) err = mergeBuildFiles(shared.JoinPath(topdir, forestChild), srcBuildFile, generatedBuildFile, cfg.IsEnvTrue("BP2BUILD_VERBOSE")) if err != nil { fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s", diff --git a/bpf/bpf.go b/bpf/bpf.go index dbbce505e..60a410d7f 100644 --- a/bpf/bpf.go +++ b/bpf/bpf.go @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/bazel" + "android/soong/bazel/cquery" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -239,6 +240,35 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData { } } +var _ android.MixedBuildBuildable = (*bpf)(nil) + +func (bpf *bpf) IsMixedBuildSupported(ctx android.BaseModuleContext) bool { + return true +} + +func (bpf *bpf) QueueBazelCall(ctx android.BaseModuleContext) { + bazelCtx := ctx.Config().BazelContext + bazelCtx.QueueBazelRequest( + bpf.GetBazelLabel(ctx, bpf), + cquery.GetOutputFiles, + android.GetConfigKey(ctx)) +} + +func (bpf *bpf) ProcessBazelQueryResponse(ctx android.ModuleContext) { + bazelCtx := ctx.Config().BazelContext + objPaths, err := bazelCtx.GetOutputFiles(bpf.GetBazelLabel(ctx, bpf), android.GetConfigKey(ctx)) + if err != nil { + ctx.ModuleErrorf(err.Error()) + return + } + + bazelOuts := android.Paths{} + for _, p := range objPaths { + bazelOuts = append(bazelOuts, android.PathForBazelOut(ctx, p)) + } + bpf.objs = bazelOuts +} + // Implements OutputFileFileProducer interface so that the obj output can be used in the data property // of other modules. func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) { diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go index 6e3909680..a2010ff2f 100644 --- a/bpf/bpf_test.go +++ b/bpf/bpf_test.go @@ -71,3 +71,26 @@ func TestBpfSourceName(t *testing.T) { `\QAndroid.bp:2:3: module "bpf_invalid_name.o" variant "android_common": invalid character '_' in source name\E`)). RunTestWithBp(t, bp) } + +func TestBpfWithBazel(t *testing.T) { + bp := ` + bpf { + name: "bpf.o", + srcs: ["bpf.c"], + bazel_module: { label: "//bpf" }, + } + ` + + result := android.GroupFixturePreparers( + prepareForBpfTest, android.FixtureModifyConfig(func(config android.Config) { + config.BazelContext = android.MockBazelContext{ + OutputBaseDir: "outputbase", + LabelToOutputFiles: map[string][]string{ + "//bpf": []string{"bpf.o"}}} + })).RunTestWithBp(t, bp) + + output := result.Module("bpf.o", "android_common").(*bpf) + + expectedOutputFiles := []string{"outputbase/execroot/__main__/bpf.o"} + android.AssertDeepEquals(t, "output files", expectedOutputFiles, output.objs.Strings()) +} diff --git a/cc/bp2build.go b/cc/bp2build.go index 0861a51b8..d6d052faf 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -182,7 +182,7 @@ func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, mo attrs := staticOrSharedAttributes{} setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) { - attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag)) + attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag)) attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs)) attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs)) @@ -376,7 +376,7 @@ func filterOutClangUnknownCflags(flag string) bool { return false } -func parseCommandLineFlags(soongFlags []string, noCoptsTokenization bool, filterOut ...filterOutFn) []string { +func parseCommandLineFlags(soongFlags []string, filterOut ...filterOutFn) []string { var result []string for _, flag := range soongFlags { skipFlag := false @@ -391,15 +391,7 @@ func parseCommandLineFlags(soongFlags []string, noCoptsTokenization bool, filter // Soong's cflags can contain spaces, like `-include header.h`. For // Bazel's copts, split them up to be compatible with the // no_copts_tokenization feature. - if noCoptsTokenization { - result = append(result, strings.Split(flag, " ")...) - } else { - // Soong's Version Script and Dynamic List Properties are added as flags - // to Bazel's linkopts using "($location label)" syntax. - // Splitting on spaces would separate this into two different flags - // "($ location" and "label)" - result = append(result, flag) - } + result = append(result, strings.Split(flag, " ")...) } return result } @@ -433,10 +425,10 @@ func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversi // overridden. In Bazel we always allow overriding, via flags; however, this can cause // incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other // cases. - ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag, filterOutClangUnknownCflags)) - ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, true, nil)) - ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, true, filterOutClangUnknownCflags)) - ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, true, filterOutClangUnknownCflags)) + ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutClangUnknownCflags)) + ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, nil)) + ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, filterOutClangUnknownCflags)) + ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, filterOutClangUnknownCflags)) ca.rtti.SetSelectValue(axis, config, props.Rtti) } @@ -1042,6 +1034,11 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion axisFeatures = append(axisFeatures, "-static_flag") } } + + // This must happen before the addition of flags for Version Script and + // Dynamic List, as these flags must be split on spaces and those must not + linkerFlags = parseCommandLineFlags(linkerFlags, filterOutClangUnknownCflags) + additionalLinkerInputs := bazel.LabelList{} if props.Version_script != nil { label := android.BazelLabelForModuleSrcSingle(ctx, *props.Version_script) @@ -1056,7 +1053,7 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion } la.additionalLinkerInputs.SetSelectValue(axis, config, additionalLinkerInputs) - la.linkopts.SetSelectValue(axis, config, parseCommandLineFlags(linkerFlags, false, filterOutClangUnknownCflags)) + la.linkopts.SetSelectValue(axis, config, linkerFlags) la.useLibcrt.SetSelectValue(axis, config, props.libCrt()) // it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it. @@ -3753,7 +3753,18 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { var _ android.ApiProvider = (*Module)(nil) func (c *Module) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) { + if c.IsPrebuilt() { + return + } switch c.typ() { + case fullLibrary: + apiContributionBp2Build(ctx, c) + case sharedLibrary: + apiContributionBp2Build(ctx, c) + case headerLibrary: + // Aggressively generate api targets for all header modules + // This is necessary since the header module does not know if it is a dep of API surface stub library + apiLibraryHeadersBp2Build(ctx, c) case ndkLibrary: ndkLibraryBp2build(ctx, c) } diff --git a/cc/library.go b/cc/library.go index 8e262eb37..77f686e04 100644 --- a/cc/library.go +++ b/cc/library.go @@ -30,6 +30,7 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/pathtools" + "github.com/google/blueprint/proptools" ) // LibraryProperties is a collection of properties shared by cc library rules/cc. @@ -470,6 +471,147 @@ func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module } } +func apiContributionBp2Build(ctx android.TopDownMutatorContext, module *Module) { + apiSurfaces := make([]string, 0) + apiHeaders := make([]string, 0) + // systemapi (non-null `stubs` property) + if module.HasStubsVariants() { + apiSurfaces = append(apiSurfaces, android.SystemApi.String()) + apiIncludes := getSystemApiIncludes(ctx, module) + if !apiIncludes.isEmpty() { + createApiHeaderTarget(ctx, apiIncludes) + apiHeaders = append(apiHeaders, apiIncludes.name) + } + } + // vendorapi (non-null `llndk` property) + if module.HasLlndkStubs() { + apiSurfaces = append(apiSurfaces, android.VendorApi.String()) + apiIncludes := getVendorApiIncludes(ctx, module) + if !apiIncludes.isEmpty() { + createApiHeaderTarget(ctx, apiIncludes) + apiHeaders = append(apiHeaders, apiIncludes.name) + } + } + // create a target only if this module contributes to an api surface + // TODO: Currently this does not distinguish systemapi-only headers and vendrorapi-only headers + // TODO: Update so that systemapi-only headers do not get exported to vendorapi (and vice-versa) + if len(apiSurfaces) > 0 { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_api_contribution", + Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl", + } + attrs := &bazelCcApiContributionAttributes{ + Library_name: module.Name(), + Api_surfaces: bazel.MakeStringListAttribute(apiSurfaces), + Api: apiLabelAttribute(ctx, module), + Hdrs: bazel.MakeLabelListAttribute( + bazel.MakeLabelListFromTargetNames(apiHeaders), + ), + } + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{ + Name: android.ApiContributionTargetName(module.Name()), + SkipData: proptools.BoolPtr(true), + }, + attrs, + ) + } +} + +// Native apis are versioned in a single .map.txt for all api surfaces +// Pick any one of the .map.txt files +func apiLabelAttribute(ctx android.TopDownMutatorContext, module *Module) bazel.LabelAttribute { + var apiFile *string + linker := module.linker.(*libraryDecorator) + if llndkApi := linker.Properties.Llndk.Symbol_file; llndkApi != nil { + apiFile = llndkApi + } else if systemApi := linker.Properties.Stubs.Symbol_file; systemApi != nil { + apiFile = systemApi + } else { + ctx.ModuleErrorf("API surface library does not have any API file") + } + apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label + return *bazel.MakeLabelAttribute(apiLabel) +} + +// wrapper struct to flatten the arch and os specific export_include_dirs +// flattening is necessary since we want to export apis of all arches even when we build for x86 (e.g.) +type bazelCcApiLibraryHeadersAttributes struct { + bazelCcLibraryHeadersAttributes + + Arch *string +} + +func (a *bazelCcApiLibraryHeadersAttributes) isEmpty() bool { + return a.Export_includes.IsEmpty() && + a.Export_system_includes.IsEmpty() && + a.Deps.IsEmpty() +} + +type apiIncludes struct { + name string // name of the Bazel target in the generated bp2build workspace + attrs bazelCcApiLibraryHeadersAttributes +} + +func (includes *apiIncludes) isEmpty() bool { + return includes.attrs.isEmpty() +} + +func (includes *apiIncludes) addDep(name string) { + l := bazel.Label{Label: ":" + name} + ll := bazel.MakeLabelList([]bazel.Label{l}) + lla := bazel.MakeLabelListAttribute(ll) + includes.attrs.Deps.Append(lla) +} + +func getSystemApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes { + flagProps := c.library.(*libraryDecorator).flagExporter.Properties + linkProps := c.library.(*libraryDecorator).baseLinker.Properties + includes := android.FirstUniqueStrings(flagProps.Export_include_dirs) + systemIncludes := android.FirstUniqueStrings(flagProps.Export_system_include_dirs) + headerLibs := android.FirstUniqueStrings(linkProps.Export_header_lib_headers) + attrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute(includes), + Export_system_includes: bazel.MakeStringListAttribute(systemIncludes), + Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, headerLibs)), + } + + return apiIncludes{ + name: c.Name() + ".systemapi.headers", + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: attrs, + }, + } +} + +func getVendorApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes { + baseProps := c.library.(*libraryDecorator).flagExporter.Properties + llndkProps := c.library.(*libraryDecorator).Properties.Llndk + includes := baseProps.Export_include_dirs + systemIncludes := baseProps.Export_system_include_dirs + // LLNDK can override the base includes + if llndkIncludes := llndkProps.Override_export_include_dirs; llndkIncludes != nil { + includes = llndkIncludes + } + if proptools.Bool(llndkProps.Export_headers_as_system) { + systemIncludes = append(systemIncludes, includes...) + includes = nil + } + + attrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute(includes), + Export_system_includes: bazel.MakeStringListAttribute(systemIncludes), + Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, llndkProps.Export_llndk_headers)), + } + return apiIncludes{ + name: c.Name() + ".vendorapi.headers", + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: attrs, + }, + } +} + // cc_library creates both static and/or shared libraries for a device and/or // host. By default, a cc_library has a single variant that targets the device. // Specifying `host_supported: true` also creates a library that targets the diff --git a/cc/library_headers.go b/cc/library_headers.go index a683f58df..1c4f35403 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -15,6 +15,8 @@ package cc import ( + "github.com/google/blueprint/proptools" + "android/soong/android" "android/soong/bazel" "android/soong/bazel/cquery" @@ -145,3 +147,118 @@ func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs) } + +// Append .contribution suffix to input labels +func apiBazelTargets(ll bazel.LabelList) bazel.LabelList { + labels := make([]bazel.Label, 0) + for _, l := range ll.Includes { + labels = append(labels, bazel.Label{ + Label: android.ApiContributionTargetName(l.Label), + }) + } + return bazel.MakeLabelList(labels) +} + +func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { + // cc_api_library_headers have a 1:1 mapping to arch/no-arch + // For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps + + // arch-agnostic includes + apiIncludes := getSystemApiIncludes(ctx, module) + // arch and os specific includes + archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module) + for _, arch := range allArches { // sorted iteration + archApiInclude := archApiIncludes[arch] + if !archApiInclude.isEmpty() { + createApiHeaderTarget(ctx, archApiInclude) + apiIncludes.addDep(archApiInclude.name) + } + } + // os==android includes + if !androidOsIncludes.isEmpty() { + createApiHeaderTarget(ctx, androidOsIncludes) + apiIncludes.addDep(androidOsIncludes.name) + } + + if !apiIncludes.isEmpty() { + // override the name from <mod>.systemapi.headers --> <mod>.contribution + apiIncludes.name = android.ApiContributionTargetName(module.Name()) + createApiHeaderTarget(ctx, apiIncludes) + } +} + +func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_api_library_headers", + Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl", + } + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{ + Name: includes.name, + SkipData: proptools.BoolPtr(true), + }, + &includes.attrs, + ) +} + +var ( + allArches = []string{"arm", "arm64", "x86", "x86_64"} +) + +type archApiIncludes map[string]apiIncludes + +func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) { + baseProps := bp2BuildParseBaseProps(ctx, module) + i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes) + archRet := archApiIncludes{} + for _, arch := range allArches { + includes := i.Includes.SelectValue( + bazel.ArchConfigurationAxis, + arch) + systemIncludes := i.SystemIncludes.SelectValue( + bazel.ArchConfigurationAxis, + arch) + deps := baseProps.deps.SelectValue( + bazel.ArchConfigurationAxis, + arch) + attrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute(includes), + Export_system_includes: bazel.MakeStringListAttribute(systemIncludes), + } + apiDeps := apiBazelTargets(deps) + if !apiDeps.IsEmpty() { + attrs.Deps = bazel.MakeLabelListAttribute(apiDeps) + } + apiIncludes := apiIncludes{ + name: android.ApiContributionTargetName(module.Name()) + "." + arch, + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: attrs, + Arch: proptools.StringPtr(arch), + }, + } + archRet[arch] = apiIncludes + } + + // apiIncludes for os == Android + androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid) + androidOsAttrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute( + i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid), + ), + Export_system_includes: bazel.MakeStringListAttribute( + i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid), + ), + } + androidOsApiDeps := apiBazelTargets(androidOsDeps) + if !androidOsApiDeps.IsEmpty() { + androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps) + } + osRet := apiIncludes{ + name: android.ApiContributionTargetName(module.Name()) + ".androidos", + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: androidOsAttrs, + }, + } + return archRet, osRet +} diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 06ded3f8e..49a919eea 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -581,12 +581,12 @@ type bazelCcApiContributionAttributes struct { } // Names of the cc_api_header targets in the bp2build workspace -func (s *stubDecorator) apiHeaderLabels(ctx android.TopDownMutatorContext) bazel.LabelList { +func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel.LabelList { addSuffix := func(ctx android.BazelConversionPathContext, module blueprint.Module) string { label := android.BazelModuleLabel(ctx, module) return android.ApiContributionTargetName(label) } - return android.BazelLabelForModuleDepsWithFn(ctx, s.properties.Export_header_libs, addSuffix) + return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix) } func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) { @@ -604,7 +604,7 @@ func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) { apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(symbolFile)).Label attrs.Api = *bazel.MakeLabelAttribute(apiLabel) } - apiHeaders := stubLibrary.apiHeaderLabels(ctx) + apiHeaders := apiHeaderLabels(ctx, stubLibrary.properties.Export_header_libs) attrs.Hdrs = bazel.MakeLabelListAttribute(apiHeaders) apiContributionTargetName := android.ApiContributionTargetName(ctx.ModuleName()) ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: apiContributionTargetName}, attrs) diff --git a/cc/sanitize.go b/cc/sanitize.go index 0b47f0e6d..66dfef57b 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -564,6 +564,11 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Scudo = nil } + if Bool(s.Undefined) || Bool(s.All_undefined) || len(s.Misc_undefined) > 0 { + // TODO(b/251249010): re-enable Hwaddress with UBSan once fixed. + s.Hwaddress = nil + } + if Bool(s.Hwaddress) { s.Address = nil s.Thread = nil diff --git a/cc/strip.go b/cc/strip.go index c60e13530..5c32d8b04 100644 --- a/cc/strip.go +++ b/cc/strip.go @@ -56,7 +56,9 @@ func (stripper *Stripper) NeedsStrip(actx android.ModuleContext) bool { forceEnable := Bool(stripper.StripProperties.Strip.All) || Bool(stripper.StripProperties.Strip.Keep_symbols) || Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame) - return !forceDisable && (forceEnable || defaultEnable) + // create_minidebuginfo doesn't work for riscv64 yet, disable stripping for now + riscv64 := actx.Arch().ArchType == android.Riscv64 + return !forceDisable && (forceEnable || defaultEnable) && !riscv64 } // Keep this consistent with //build/bazel/rules/stripped_shared_library.bzl. diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py index 9bf07f2b2..94c856726 100644 --- a/cc/symbolfile/__init__.py +++ b/cc/symbolfile/__init__.py @@ -41,6 +41,7 @@ Tag = NewType('Tag', str) ALL_ARCHITECTURES = ( Arch('arm'), Arch('arm64'), + Arch('riscv64'), Arch('x86'), Arch('x86_64'), ) diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index eb248bb40..5e5769bf1 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -151,6 +151,8 @@ type FuzzConfig struct { // If there's a Java fuzzer with JNI, a different version of Jazzer would // need to be added to the fuzzer package than one without JNI IsJni *bool `json:"is_jni,omitempty"` + // List of modules for monitoring coverage drops in directories (e.g. "libicu") + Target_modules []string `json:"target_modules,omitempty"` } type FuzzFrameworks struct { diff --git a/java/base.go b/java/base.go index bcb722603..ab5a7d9a2 100644 --- a/java/base.go +++ b/java/base.go @@ -447,9 +447,11 @@ type Module struct { // installed file for hostdex copy hostdexInstallFile android.InstallPath - // list of .java files and srcjars that was passed to javac - compiledJavaSrcs android.Paths - compiledSrcJars android.Paths + // list of unique .java and .kt source files + uniqueSrcFiles android.Paths + + // list of srcjars that was passed to javac + compiledSrcJars android.Paths // manifest file to use instead of properties.Manifest overrideManifest android.OptionalPath @@ -1078,15 +1080,26 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { jarName := ctx.ModuleName() + ".jar" - javaSrcFiles := srcFiles.FilterByExt(".java") - var uniqueSrcFiles android.Paths + var uniqueJavaFiles android.Paths set := make(map[string]bool) - for _, v := range javaSrcFiles { + for _, v := range srcFiles.FilterByExt(".java") { if _, found := set[v.String()]; !found { set[v.String()] = true - uniqueSrcFiles = append(uniqueSrcFiles, v) + uniqueJavaFiles = append(uniqueJavaFiles, v) } } + var uniqueKtFiles android.Paths + for _, v := range srcFiles.FilterByExt(".kt") { + if _, found := set[v.String()]; !found { + set[v.String()] = true + uniqueKtFiles = append(uniqueKtFiles, v) + } + } + + var uniqueSrcFiles android.Paths + uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...) + uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...) + j.uniqueSrcFiles = uniqueSrcFiles // We don't currently run annotation processors in turbine, which means we can't use turbine // generated header jars when an annotation processor that generates API is enabled. One @@ -1094,7 +1107,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // is used to run all of the annotation processors. disableTurbine := deps.disableTurbine - // Collect .java files for AIDEGen + // Collect .java and .kt files for AIDEGen j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...) var kotlinJars android.Paths @@ -1132,12 +1145,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { flags.kotlincFlags += "$kotlincFlags" } - var kotlinSrcFiles android.Paths - kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...) - kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...) - - // Collect .kt files for AIDEGen - j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...) + // Collect common .kt files for AIDEGen j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...) flags.classpath = append(flags.classpath, deps.kotlinStdlib...) @@ -1150,7 +1158,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Use kapt for annotation processing kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar") kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar") - kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags) + kotlinKapt(ctx, kaptSrcJar, kaptResJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags) srcJars = append(srcJars, kaptSrcJar) kotlinJars = append(kotlinJars, kaptResJar) // Disable annotation processing in javac, it's already been handled by kapt @@ -1160,7 +1168,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName) kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName) - kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags) + kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags) if ctx.Failed() { return } @@ -1185,8 +1193,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { jars := append(android.Paths(nil), kotlinJars...) - // Store the list of .java files that was passed to javac - j.compiledJavaSrcs = uniqueSrcFiles j.compiledSrcJars = srcJars enableSharding := false @@ -1201,12 +1207,12 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // with sharding enabled. See: b/77284273. } headerJarFileWithoutDepsOrJarjar, j.headerJarFile = - j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinHeaderJars) + j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, kotlinHeaderJars) if ctx.Failed() { return } } - if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 { + if len(uniqueJavaFiles) > 0 || len(srcJars) > 0 { hasErrorproneableFiles := false for _, ext := range j.sourceExtensions { if ext != ".proto" && ext != ".aidl" { @@ -1231,7 +1237,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { errorproneFlags := enableErrorproneFlags(flags) errorprone := android.PathForModuleOut(ctx, "errorprone", jarName) - transformJavaToClasses(ctx, errorprone, -1, uniqueSrcFiles, srcJars, errorproneFlags, nil, + transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneFlags, nil, "errorprone", "errorprone") extraJarDeps = append(extraJarDeps, errorprone) @@ -1243,8 +1249,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } shardSize := int(*(j.properties.Javac_shard_size)) var shardSrcs []android.Paths - if len(uniqueSrcFiles) > 0 { - shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize) + if len(uniqueJavaFiles) > 0 { + shardSrcs = android.ShardPaths(uniqueJavaFiles, shardSize) for idx, shardSrc := range shardSrcs { classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc, nil, flags, extraJarDeps) @@ -1257,7 +1263,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { jars = append(jars, classes) } } else { - classes := j.compileJavaClasses(ctx, jarName, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps) + classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps) jars = append(jars, classes) } if ctx.Failed() { diff --git a/java/config/config.go b/java/config/config.go index ea44aaa08..a84c315d5 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -132,12 +132,7 @@ func init() { if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" { return override } - switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") { - case "true": - return "17" - default: - return "11" - } + return "17" }) pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin") diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go index eaa6a8c22..b704d09d2 100644 --- a/java/dexpreopt_config_test.go +++ b/java/dexpreopt_config_test.go @@ -15,12 +15,17 @@ package java import ( + "runtime" "testing" "android/soong/android" ) func TestBootImageConfig(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skipf("Skipping as boot image config test is only supported on linux not %s", runtime.GOOS) + } + result := android.GroupFixturePreparers( PrepareForBootImageConfigTest, ).RunTest(t) diff --git a/java/java_test.go b/java/java_test.go index 7f0cea718..d2373e349 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -588,8 +588,8 @@ func TestPrebuilts(t *testing.T) { sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output fooLibrary := fooModule.Module().(*Library) - assertDeepEquals(t, "foo java sources incorrect", - []string{"a.java"}, fooLibrary.compiledJavaSrcs.Strings()) + assertDeepEquals(t, "foo unique sources incorrect", + []string{"a.java"}, fooLibrary.uniqueSrcFiles.Strings()) assertDeepEquals(t, "foo java source jars incorrect", []string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"}, diff --git a/java/lint.go b/java/lint.go index 931820d74..fcd6d31ff 100644 --- a/java/lint.go +++ b/java/lint.go @@ -473,20 +473,23 @@ func (l *linter) lint(ctx android.ModuleContext) { cmd.FlagWithOutput("--write-reference-baseline ", baseline) - cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)") - - rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) - - // The HTML output contains a date, remove it to make the output deterministic. - rule.Command().Text(`sed -i.tmp -e 's|Check performed at .*\(</nav>\)|\1|'`).Output(html) + cmd.Text("; EXITCODE=$?; ") // The sources in the sandbox may have been modified by --apply-suggestions, zip them up and - // export them out of the sandbox. - rule.Command().BuiltTool("soong_zip"). + // export them out of the sandbox. Do this before exiting so that the suggestions exit even after + // a fatal error. + cmd.BuiltTool("soong_zip"). FlagWithOutput("-o ", android.PathForModuleOut(ctx, "lint", "suggested-fixes.zip")). FlagWithArg("-C ", cmd.PathForInput(android.PathForSource(ctx))). FlagWithInput("-r ", srcsList) + cmd.Text("; if [ $EXITCODE != 0 ]; then if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit $EXITCODE; fi") + + rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String()) + + // The HTML output contains a date, remove it to make the output deterministic. + rule.Command().Text(`sed -i.tmp -e 's|Check performed at .*\(</nav>\)|\1|'`).Output(html) + rule.Build("lint", "lint") l.outputs = lintOutputs{ diff --git a/java/robolectric.go b/java/robolectric.go index 7f2981fa8..b6116ec9d 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -188,9 +188,9 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) // TODO: this could all be removed if tradefed was used as the test runner, it will find everything // annotated as a test and run it. - for _, src := range r.compiledJavaSrcs { + for _, src := range r.uniqueSrcFiles { s := src.Rel() - if !strings.HasSuffix(s, "Test.java") { + if !strings.HasSuffix(s, "Test.java") && !strings.HasSuffix(s, "Test.kt") { continue } else if strings.HasSuffix(s, "/BaseRobolectricTest.java") { continue diff --git a/java/rro.go b/java/rro.go index cd8c635ff..9d0667cf0 100644 --- a/java/rro.go +++ b/java/rro.go @@ -142,6 +142,10 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC aaptLinkFlags = append(aaptLinkFlags, "--rename-overlay-target-package "+*r.overridableProperties.Target_package_name) } + if r.overridableProperties.Category != nil { + aaptLinkFlags = append(aaptLinkFlags, + "--rename-overlay-category "+*r.overridableProperties.Category) + } r.aapt.buildActions(ctx, r, nil, nil, false, aaptLinkFlags...) // Sign the built package @@ -220,6 +224,9 @@ type OverridableRuntimeResourceOverlayProperties struct { // the target package name of this overlay app. The target package name in the manifest file is used if one was not given. Target_package_name *string + + // the rro category of this overlay. The category in the manifest file is used if one was not given. + Category *string } type OverrideRuntimeResourceOverlay struct { diff --git a/java/rro_test.go b/java/rro_test.go index 00ba5ba11..8067a4703 100644 --- a/java/rro_test.go +++ b/java/rro_test.go @@ -201,6 +201,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { base: "foo_overlay", package_name: "com.android.bar.overlay", target_package_name: "com.android.bar", + category: "mycategory", } `) @@ -212,6 +213,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { targetVariant string packageFlag string targetPackageFlag string + categoryFlag string }{ { variantName: "android_common", @@ -228,6 +230,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { targetVariant: "android_common_bar", packageFlag: "com.android.bar.overlay", targetPackageFlag: "com.android.bar", + categoryFlag: "mycategory", }, } for _, expected := range expectedVariants { @@ -249,6 +252,7 @@ func TestOverrideRuntimeResourceOverlay(t *testing.T) { checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "") checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag) + checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-category", expected.categoryFlag) } } diff --git a/python/binary.go b/python/binary.go index e6324a3b5..f4ad626b8 100644 --- a/python/binary.go +++ b/python/binary.go @@ -192,8 +192,8 @@ func (binary *binaryDecorator) bootstrap(ctx android.ModuleContext, actualVersio }) } - addTopDirectoriesToPath := !proptools.BoolDefault(binary.binaryProperties.Dont_add_top_level_directories_to_path, false) - dontAddEntrypointFolderToPath := proptools.BoolDefault(binary.binaryProperties.Dont_add_entrypoint_folder_to_path, false) + addTopDirectoriesToPath := !proptools.BoolDefault(binary.binaryProperties.Dont_add_top_level_directories_to_path, true) + dontAddEntrypointFolderToPath := proptools.BoolDefault(binary.binaryProperties.Dont_add_entrypoint_folder_to_path, true) binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath, binary.getHostInterpreterName(ctx, actualVersion), diff --git a/python/python.go b/python/python.go index f6029c250..6f3a0ecf3 100644 --- a/python/python.go +++ b/python/python.go @@ -677,8 +677,7 @@ func (p *Module) createSrcsZip(ctx android.ModuleContext, pkgPath string) androi protoFlags := android.GetProtoFlags(ctx, &p.protoProperties) protoFlags.OutTypeFlag = "--python_out" - // TODO(b/247578564): Change the default to true, and then eventually remove respect_pkg_path - protosRespectPkgPath := proptools.BoolDefault(p.properties.Proto.Respect_pkg_path, false) + protosRespectPkgPath := proptools.BoolDefault(p.properties.Proto.Respect_pkg_path, true) pkgPathForProtos := pkgPath if pkgPathForProtos != "" && protosRespectPkgPath { pkgPathStagingDir := android.PathForModuleGen(ctx, "protos_staged_for_pkg_path") diff --git a/ui/build/config.go b/ui/build/config.go index 206066066..f6f5b4657 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -388,13 +388,13 @@ func NewConfig(ctx Context, args ...string) Config { if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok { return override } - if ret.environ.IsEnvTrue("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") { - return java17Home - } if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" { ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.") } - return java11Home + if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" { + ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.") + } + return java17Home }() absJavaHome := absPath(ctx, javaHome) |