diff options
| -rw-r--r-- | android/arch.go | 1 | ||||
| -rw-r--r-- | android/arch_module_context.go | 8 | ||||
| -rw-r--r-- | android/base_module_context.go | 31 | ||||
| -rw-r--r-- | android/buildinfo_prop.go | 152 | ||||
| -rw-r--r-- | android/config.go | 63 | ||||
| -rw-r--r-- | android/early_module_context.go | 10 | ||||
| -rw-r--r-- | android/module.go | 71 | ||||
| -rw-r--r-- | android/module_context.go | 2 | ||||
| -rw-r--r-- | android/sdk.go | 8 | ||||
| -rw-r--r-- | android/selects_test.go | 25 | ||||
| -rw-r--r-- | android/singleton.go | 7 | ||||
| -rw-r--r-- | android/variable.go | 23 | ||||
| -rw-r--r-- | androidmk/androidmk/androidmk_test.go | 16 | ||||
| -rw-r--r-- | androidmk/parser/scope.go | 6 | ||||
| -rw-r--r-- | cc/ndk_library.go | 7 | ||||
| -rw-r--r-- | filesystem/system_image.go | 27 | ||||
| -rw-r--r-- | java/aar.go | 100 | ||||
| -rw-r--r-- | java/android_manifest_test.go | 5 | ||||
| -rw-r--r-- | java/androidmk.go | 12 | ||||
| -rw-r--r-- | java/app_test.go | 90 | ||||
| -rw-r--r-- | java/base.go | 11 | ||||
| -rw-r--r-- | java/java.go | 86 | ||||
| -rw-r--r-- | java/java_test.go | 88 | ||||
| -rw-r--r-- | java/sdk.go | 15 | ||||
| -rw-r--r-- | linkerconfig/linkerconfig.go | 45 | ||||
| -rw-r--r-- | phony/phony.go | 10 | ||||
| -rw-r--r-- | python/python.go | 1 | ||||
| -rw-r--r-- | scripts/Android.bp | 11 | ||||
| -rwxr-xr-x | scripts/buildinfo.py | 156 |
29 files changed, 838 insertions, 249 deletions
diff --git a/android/arch.go b/android/arch.go index 4fe434502..9e79e3175 100644 --- a/android/arch.go +++ b/android/arch.go @@ -693,6 +693,7 @@ func addTargetProperties(m Module, target Target, multiTargets []Target, primary m.base().commonProperties.CompileTarget = target m.base().commonProperties.CompileMultiTargets = multiTargets m.base().commonProperties.CompilePrimary = primaryTarget + m.base().commonProperties.ArchReady = true } // decodeMultilib returns the appropriate compile_multilib property for the module, or the default diff --git a/android/arch_module_context.go b/android/arch_module_context.go index 3cf4b4115..a3a03af02 100644 --- a/android/arch_module_context.go +++ b/android/arch_module_context.go @@ -35,6 +35,7 @@ type ArchModuleContext interface { type archModuleContext struct { // TODO: these should eventually go through a (possibly cached) provider like any other configuration instead // of being special cased. + ready bool os OsType target Target targetPrimary bool @@ -42,6 +43,13 @@ type archModuleContext struct { primaryArch bool } +// ArchReady returns true if the arch mutator has run on the module. Before this returns +// true, the module essentially doesn't have an arch and cannot make decisions based on +// architecture. +func (a *archModuleContext) ArchReady() bool { + return a.ready +} + func (a *archModuleContext) Target() Target { return a.target } diff --git a/android/base_module_context.go b/android/base_module_context.go index 9be3fad9a..c4922f4bc 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -219,7 +219,7 @@ type BaseModuleContext interface { // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context // can be used to evaluate the final value of Configurable properties. - EvaluateConfiguration(parser.SelectType, string) (string, bool) + EvaluateConfiguration(parser.SelectType, string, string) (string, bool) } type baseModuleContext struct { @@ -577,31 +577,6 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) string { return sb.String() } -func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, condition string) (string, bool) { - switch ty { - case parser.SelectTypeReleaseVariable: - if v, ok := m.Config().productVariables.BuildFlags[condition]; ok { - return v, true - } - return "", false - case parser.SelectTypeProductVariable: - // TODO(b/323382414): Might add these on a case-by-case basis - m.ModuleErrorf("TODO(b/323382414): Product variables are not yet supported in selects") - return "", false - case parser.SelectTypeSoongConfigVariable: - parts := strings.Split(condition, ":") - namespace := parts[0] - variable := parts[1] - if n, ok := m.Config().productVariables.VendorVars[namespace]; ok { - if v, ok := n[variable]; ok { - return v, true - } - } - return "", false - case parser.SelectTypeVariant: - m.ModuleErrorf("TODO(b/323382414): Variants are not yet supported in selects") - return "", false - default: - panic("Should be unreachable") - } +func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) { + return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(ty, property, condition) } diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go index 8e19ad5f4..8288fc555 100644 --- a/android/buildinfo_prop.go +++ b/android/buildinfo_prop.go @@ -54,6 +54,39 @@ func (p *buildinfoPropModule) OutputFiles(tag string) (Paths, error) { return Paths{p.outputFilePath}, nil } +func getBuildVariant(config Config) string { + if config.Eng() { + return "eng" + } else if config.Debuggable() { + return "userdebug" + } else { + return "user" + } +} + +func getBuildFlavor(config Config) string { + buildFlavor := config.DeviceProduct() + "-" + getBuildVariant(config) + if InList("address", config.SanitizeDevice()) && !strings.Contains(buildFlavor, "_asan") { + buildFlavor += "_asan" + } + return buildFlavor +} + +func shouldAddBuildThumbprint(config Config) bool { + knownOemProperties := []string{ + "ro.product.brand", + "ro.product.name", + "ro.product.device", + } + + for _, knownProp := range knownOemProperties { + if InList(knownProp, config.OemProperties()) { + return true + } + } + return false +} + func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath if !ctx.Config().KatiEnabled() { @@ -61,87 +94,66 @@ func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { return } - lines := make([]string, 0) + rule := NewRuleBuilder(pctx, ctx) - writeString := func(str string) { - lines = append(lines, str) - } + config := ctx.Config() + buildVariant := getBuildVariant(config) + buildFlavor := getBuildFlavor(config) - writeString("# begin build properties") - writeString("# autogenerated by build/soong/android/buildinfo_prop.go") + cmd := rule.Command().BuiltTool("buildinfo") - writeProp := func(key, value string) { - if strings.Contains(key, "=") { - panic(fmt.Errorf("wrong property key %q: key must not contain '='", key)) - } - writeString(key + "=" + value) + if config.BoardUseVbmetaDigestInFingerprint() { + cmd.Flag("--use-vbmeta-digest-in-fingerprint") } - config := ctx.Config() - - writeProp("ro.build.version.sdk", config.PlatformSdkVersion().String()) - writeProp("ro.build.version.preview_sdk", config.PlatformPreviewSdkVersion()) - writeProp("ro.build.version.codename", config.PlatformSdkCodename()) - writeProp("ro.build.version.all_codenames", strings.Join(config.PlatformVersionActiveCodenames(), ",")) - writeProp("ro.build.version.release", config.PlatformVersionLastStable()) - writeProp("ro.build.version.release_or_codename", config.PlatformVersionName()) - writeProp("ro.build.version.security_patch", config.PlatformSecurityPatch()) - writeProp("ro.build.version.base_os", config.PlatformBaseOS()) - writeProp("ro.build.version.min_supported_target_sdk", config.PlatformMinSupportedTargetSdkVersion()) - writeProp("ro.build.version.known_codenames", config.PlatformVersionKnownCodenames()) + cmd.FlagWithArg("--build-flavor=", buildFlavor) + cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx)) + cmd.FlagWithArg("--build-id=", config.BuildId()) + cmd.FlagWithArg("--build-keys=", config.BuildKeys()) - if config.Eng() { - writeProp("ro.build.type", "eng") - } else if config.Debuggable() { - writeProp("ro.build.type", "userdebug") - } else { - writeProp("ro.build.type", "user") + // shouldn't depend on BuildNumberFile and BuildThumbprintFile to prevent from rebuilding + // on every incremental build. + cmd.FlagWithArg("--build-number-file=", config.BuildNumberFile(ctx).String()) + if shouldAddBuildThumbprint(config) { + cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String()) } - // Currently, only a few properties are implemented to unblock microdroid use case. - // TODO(b/189164487): support below properties as well and replace build/make/tools/buildinfo.sh - /* - if $BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT { - writeProp("ro.build.legacy.id", config.BuildID()) - } else { - writeProp("ro.build.id", config.BuildId()) - } - writeProp("ro.build.display.id", $BUILD_DISPLAY_ID) - writeProp("ro.build.version.incremental", $BUILD_NUMBER) - writeProp("ro.build.version.preview_sdk_fingerprint", $PLATFORM_PREVIEW_SDK_FINGERPRINT) - writeProp("ro.build.version.release_or_preview_display", $PLATFORM_DISPLAY_VERSION) - writeProp("ro.build.date", `$DATE`) - writeProp("ro.build.date.utc", `$DATE +%s`) - writeProp("ro.build.user", $BUILD_USERNAME) - writeProp("ro.build.host", $BUILD_HOSTNAME) - writeProp("ro.build.tags", $BUILD_VERSION_TAGS) - writeProp("ro.build.flavor", $TARGET_BUILD_FLAVOR) - // These values are deprecated, use "ro.product.cpu.abilist" - // instead (see below). - writeString("# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,") - writeString("# use ro.product.cpu.abilist instead.") - writeProp("ro.product.cpu.abi", $TARGET_CPU_ABI) - if [ -n "$TARGET_CPU_ABI2" ] { - writeProp("ro.product.cpu.abi2", $TARGET_CPU_ABI2) - } + cmd.FlagWithArg("--build-type=", config.BuildType()) + cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME")) + cmd.FlagWithArg("--build-variant=", buildVariant) + cmd.FlagForEachArg("--cpu-abis=", config.DeviceAbi()) - if [ -n "$PRODUCT_DEFAULT_LOCALE" ] { - writeProp("ro.product.locale", $PRODUCT_DEFAULT_LOCALE) - } - writeProp("ro.wifi.channels", $PRODUCT_DEFAULT_WIFI_CHANNELS) - writeString("# ro.build.product is obsolete; use ro.product.device") - writeProp("ro.build.product", $TARGET_DEVICE) - - writeString("# Do not try to parse description or thumbprint") - writeProp("ro.build.description", $PRIVATE_BUILD_DESC) - if [ -n "$BUILD_THUMBPRINT" ] { - writeProp("ro.build.thumbprint", $BUILD_THUMBPRINT) - } - */ + // shouldn't depend on BUILD_DATETIME_FILE to prevent from rebuilding on every incremental + // build. + cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE")) - writeString("# end build properties") + if len(config.ProductLocales()) > 0 { + cmd.FlagWithArg("--default-locale=", config.ProductLocales()[0]) + } + + cmd.FlagForEachArg("--default-wifi-channels=", config.ProductDefaultWifiChannels()) + cmd.FlagWithArg("--device=", config.DeviceName()) + if config.DisplayBuildNumber() { + cmd.Flag("--display-build-number") + } - WriteFileRule(ctx, p.outputFilePath, strings.Join(lines, "\n")) + cmd.FlagWithArg("--platform-base-os=", config.PlatformBaseOS()) + cmd.FlagWithArg("--platform-display-version=", config.PlatformDisplayVersionName()) + cmd.FlagWithArg("--platform-min-supported-target-sdk-version=", config.PlatformMinSupportedTargetSdkVersion()) + cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx)) + cmd.FlagWithArg("--platform-preview-sdk-version=", config.PlatformPreviewSdkVersion()) + cmd.FlagWithArg("--platform-sdk-version=", config.PlatformSdkVersion().String()) + cmd.FlagWithArg("--platform-security-patch=", config.PlatformSecurityPatch()) + cmd.FlagWithArg("--platform-version=", config.PlatformVersionName()) + cmd.FlagWithArg("--platform-version-codename=", config.PlatformSdkCodename()) + cmd.FlagForEachArg("--platform-version-all-codenames=", config.PlatformVersionActiveCodenames()) + cmd.FlagWithArg("--platform-version-known-codenames=", config.PlatformVersionKnownCodenames()) + cmd.FlagWithArg("--platform-version-last-stable=", config.PlatformVersionLastStable()) + cmd.FlagWithArg("--product=", config.DeviceProduct()) + + cmd.FlagWithOutput("--out=", p.outputFilePath) + + rule.Build(ctx.ModuleName(), "generating buildinfo props") if !p.installable() { p.SkipInstall() diff --git a/android/config.go b/android/config.go index 10c30d4df..2ee3b9355 100644 --- a/android/config.go +++ b/android/config.go @@ -114,6 +114,8 @@ const ( GenerateDocFile ) +const testKeyDir = "build/make/target/product/security" + // SoongOutDir returns the build output directory for the configuration. func (c Config) SoongOutDir() string { return c.soongOutDir @@ -841,6 +843,10 @@ func (c *config) BuildId() string { return String(c.productVariables.BuildId) } +func (c *config) DisplayBuildNumber() bool { + return Bool(c.productVariables.DisplayBuildNumber) +} + // BuildNumberFile returns the path to a text file containing metadata // representing the current build's number. // @@ -852,6 +858,23 @@ func (c *config) BuildNumberFile(ctx PathContext) Path { return PathForOutput(ctx, String(c.productVariables.BuildNumberFile)) } +// BuildHostnameFile returns the path to a text file containing metadata +// representing the current build's host name. +func (c *config) BuildHostnameFile(ctx PathContext) Path { + return PathForOutput(ctx, String(c.productVariables.BuildHostnameFile)) +} + +// BuildThumbprintFile returns the path to a text file containing metadata +// representing the current build's thumbprint. +// +// Rules that want to reference the build thumbprint should read from this file +// without depending on it. They will run whenever their other dependencies +// require them to run and get the current build thumbprint. This ensures they +// don't rebuild on every incremental build when the build thumbprint changes. +func (c *config) BuildThumbprintFile(ctx PathContext) Path { + return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildThumbprintFile)) +} + // DeviceName returns the name of the current device target. // TODO: take an AndroidModuleContext to select the device name for multi-device builds func (c *config) DeviceName() string { @@ -873,6 +896,10 @@ func (c *config) HasDeviceProduct() bool { return c.productVariables.DeviceProduct != nil } +func (c *config) DeviceAbi() []string { + return c.productVariables.DeviceAbi +} + func (c *config) DeviceResourceOverlays() []string { return c.productVariables.DeviceResourceOverlays } @@ -881,6 +908,10 @@ func (c *config) ProductResourceOverlays() []string { return c.productVariables.ProductResourceOverlays } +func (c *config) PlatformDisplayVersionName() string { + return String(c.productVariables.Platform_display_version_name) +} + func (c *config) PlatformVersionName() string { return String(c.productVariables.Platform_version_name) } @@ -1038,7 +1069,7 @@ func (c *config) DefaultAppCertificateDir(ctx PathContext) SourcePath { if defaultCert != "" { return PathForSource(ctx, filepath.Dir(defaultCert)) } - return PathForSource(ctx, "build/make/target/product/security") + return PathForSource(ctx, testKeyDir) } func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) { @@ -1050,10 +1081,18 @@ func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) { return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8") } +func (c *config) BuildKeys() string { + defaultCert := String(c.productVariables.DefaultAppCertificate) + if defaultCert == "" || defaultCert == filepath.Join(testKeyDir, "testkey") { + return "test-keys" + } + return "dev-keys" +} + func (c *config) ApexKeyDir(ctx ModuleContext) SourcePath { // TODO(b/121224311): define another variable such as TARGET_APEX_KEY_OVERRIDE defaultCert := String(c.productVariables.DefaultAppCertificate) - if defaultCert == "" || filepath.Dir(defaultCert) == "build/make/target/product/security" { + if defaultCert == "" || filepath.Dir(defaultCert) == testKeyDir { // When defaultCert is unset or is set to the testkeys path, use the APEX keys // that is under the module dir return pathForModuleSrc(ctx) @@ -1112,6 +1151,10 @@ func (c *config) Eng() bool { return Bool(c.productVariables.Eng) } +func (c *config) BuildType() string { + return String(c.productVariables.BuildType) +} + // DevicePrimaryArchType returns the ArchType for the first configured device architecture, or // Common if there are no device architectures. func (c *config) DevicePrimaryArchType() ArchType { @@ -2086,3 +2129,19 @@ func (c *config) AllApexContributions() []string { func (c *config) BuildIgnoreApexContributionContents() []string { return c.productVariables.BuildIgnoreApexContributionContents } + +func (c *config) ProductLocales() []string { + return c.productVariables.ProductLocales +} + +func (c *config) ProductDefaultWifiChannels() []string { + return c.productVariables.ProductDefaultWifiChannels +} + +func (c *config) BoardUseVbmetaDigestInFingerprint() bool { + return Bool(c.productVariables.BoardUseVbmetaDigestInFingerprint) +} + +func (c *config) OemProperties() []string { + return c.productVariables.OemProperties +} diff --git a/android/early_module_context.go b/android/early_module_context.go index 8f7577358..cf1b5fcab 100644 --- a/android/early_module_context.go +++ b/android/early_module_context.go @@ -15,9 +15,10 @@ package android import ( - "github.com/google/blueprint" "os" "text/scanner" + + "github.com/google/blueprint" ) // EarlyModuleContext provides methods that can be called early, as soon as the properties have @@ -54,6 +55,9 @@ type EarlyModuleContext interface { // PropertyErrorf reports an error at the line number of a property in the module definition. PropertyErrorf(property, fmt string, args ...interface{}) + // OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition. + OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{}) + // Failed returns true if any errors have been reported. In most cases the module can continue with generating // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error // has prevented the module from creating necessary data it can return early when Failed returns true. @@ -167,3 +171,7 @@ func (e *earlyModuleContext) SystemExtSpecific() bool { func (e *earlyModuleContext) Namespace() *Namespace { return e.EarlyModuleContext.Namespace().(*Namespace) } + +func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) { + e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args) +} diff --git a/android/module.go b/android/module.go index cce4fa6cb..9f1d5eff0 100644 --- a/android/module.go +++ b/android/module.go @@ -29,6 +29,7 @@ import ( "android/soong/bazel" "github.com/google/blueprint" + "github.com/google/blueprint/parser" "github.com/google/blueprint/proptools" ) @@ -123,6 +124,8 @@ type Module interface { // TransitivePackagingSpecs returns the PackagingSpecs for this module and any transitive // dependencies with dependency tags for which IsInstallDepNeeded() returns true. TransitivePackagingSpecs() []PackagingSpec + + ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator } // Qualified id for a module @@ -433,6 +436,10 @@ type commonProperties struct { // Set by osMutator CompileOS OsType `blueprint:"mutated"` + // Set to true after the arch mutator has run on this module and set CompileTarget, + // CompileMultiTargets, and CompilePrimary + ArchReady bool `blueprint:"mutated"` + // The Target of artifacts that this module variant is responsible for creating. // // Set by archMutator @@ -1226,6 +1233,10 @@ func (m *ModuleBase) GenerateTaggedDistFiles(ctx BaseModuleContext) TaggedDistFi return distFiles } +func (m *ModuleBase) ArchReady() bool { + return m.commonProperties.ArchReady +} + func (m *ModuleBase) Target() Target { return m.commonProperties.CompileTarget } @@ -1749,6 +1760,7 @@ func (m *ModuleBase) archModuleContextFactory(ctx blueprint.IncomingTransitionCo } return archModuleContext{ + ready: m.commonProperties.ArchReady, os: m.commonProperties.CompileOS, target: m.commonProperties.CompileTarget, targetPrimary: m.commonProperties.CompilePrimary, @@ -2099,6 +2111,65 @@ func (m *ModuleBase) IsNativeBridgeSupported() bool { return proptools.Bool(m.commonProperties.Native_bridge_supported) } +type ConfigAndErrorContext interface { + Config() Config + OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) +} + +type configurationEvalutor struct { + ctx ConfigAndErrorContext + m Module +} + +func (m *ModuleBase) ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator { + return configurationEvalutor{ + ctx: ctx, + m: m.module, + } +} + +func (e configurationEvalutor) PropertyErrorf(property string, fmt string, args ...interface{}) { + e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args) +} + +func (e configurationEvalutor) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) { + ctx := e.ctx + m := e.m + switch ty { + case parser.SelectTypeReleaseVariable: + if v, ok := ctx.Config().productVariables.BuildFlags[condition]; ok { + return v, true + } + return "", false + case parser.SelectTypeProductVariable: + // TODO(b/323382414): Might add these on a case-by-case basis + ctx.OtherModulePropertyErrorf(m, property, "TODO(b/323382414): Product variables are not yet supported in selects") + return "", false + case parser.SelectTypeSoongConfigVariable: + parts := strings.Split(condition, ":") + namespace := parts[0] + variable := parts[1] + if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok { + if v, ok := n[variable]; ok { + return v, true + } + } + return "", false + case parser.SelectTypeVariant: + if condition == "arch" { + if !m.base().ArchReady() { + ctx.OtherModulePropertyErrorf(m, property, "A select on arch was attempted before the arch mutator ran") + return "", false + } + return m.base().Arch().ArchType.Name, true + } + ctx.OtherModulePropertyErrorf(m, property, "Unknown variant %s", condition) + return "", false + default: + panic("Should be unreachable") + } +} + // ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current // variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule // or if this variant is not overridden. diff --git a/android/module_context.go b/android/module_context.go index 1cab63022..d3e2770cb 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -234,6 +234,8 @@ type moduleContext struct { variables map[string]string } +var _ ModuleContext = &moduleContext{} + func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) { return pctx, BuildParams{ Rule: ErrorRule, diff --git a/android/sdk.go b/android/sdk.go index 6d5293e65..121470d6e 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -868,3 +868,11 @@ type AdditionalSdkInfo struct { } var AdditionalSdkInfoProvider = blueprint.NewProvider[AdditionalSdkInfo]() + +var apiFingerprintPathKey = NewOnceKey("apiFingerprintPathKey") + +func ApiFingerprintPath(ctx PathContext) OutputPath { + return ctx.Config().Once(apiFingerprintPathKey, func() interface{} { + return PathForOutput(ctx, "api_fingerprint.txt") + }).(OutputPath) +} diff --git a/android/selects_test.go b/android/selects_test.go index aa9c521a2..b4e226f4b 100644 --- a/android/selects_test.go +++ b/android/selects_test.go @@ -231,11 +231,30 @@ func TestSelects(t *testing.T) { my_string: proptools.StringPtr("c.cpp"), }, }, + { + name: "Select on variant", + bp: ` + my_module_type { + name: "foo", + my_string: select(variant("arch"), { + "x86": "my_x86", + "x86_64": "my_x86_64", + "arm": "my_arm", + "arm64": "my_arm64", + _: "my_default", + }), + } + `, + provider: selectsTestProvider{ + my_string: proptools.StringPtr("my_arm64"), + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { fixtures := GroupFixturePreparers( + PrepareForTestWithArchMutator, FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("my_module_type", newSelectsMockModule) }), @@ -249,8 +268,8 @@ func TestSelects(t *testing.T) { result := fixtures.RunTestWithBp(t, tc.bp) if tc.expectedError == "" { - m := result.ModuleForTests("foo", "") - p, _ := OtherModuleProvider[selectsTestProvider](result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey) + m := result.ModuleForTests("foo", "android_arm64_armv8-a") + p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey) if !reflect.DeepEqual(p, tc.provider) { t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String()) } @@ -310,7 +329,7 @@ func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { func newSelectsMockModule() Module { m := &selectsMockModule{} m.AddProperties(&m.properties) - InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon) + InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst) InitDefaultableModule(m) return m } diff --git a/android/singleton.go b/android/singleton.go index 5f939967c..76df1ebba 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -87,6 +87,9 @@ type SingletonContext interface { // builder whenever a file matching the pattern as added or removed, without rerunning if a // file that does not match the pattern is added to a searched directory. GlobWithDeps(pattern string, excludes []string) ([]string, error) + + // OtherModulePropertyErrorf reports an error on the line number of the given property of the given module + OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) } type singletonAdaptor struct { @@ -279,3 +282,7 @@ func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name st func (s *singletonContextAdaptor) moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { return s.SingletonContext.ModuleProvider(module, provider) } + +func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) { + s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args) +} diff --git a/android/variable.go b/android/variable.go index 73f5bfd1f..9b630c01f 100644 --- a/android/variable.go +++ b/android/variable.go @@ -193,9 +193,13 @@ type ProductVariables struct { // Suffix to add to generated Makefiles Make_suffix *string `json:",omitempty"` - BuildId *string `json:",omitempty"` - BuildNumberFile *string `json:",omitempty"` + BuildId *string `json:",omitempty"` + BuildNumberFile *string `json:",omitempty"` + BuildHostnameFile *string `json:",omitempty"` + BuildThumbprintFile *string `json:",omitempty"` + DisplayBuildNumber *bool `json:",omitempty"` + Platform_display_version_name *string `json:",omitempty"` Platform_version_name *string `json:",omitempty"` Platform_sdk_version *int `json:",omitempty"` Platform_sdk_codename *string `json:",omitempty"` @@ -296,6 +300,8 @@ type ProductVariables struct { MinimizeJavaDebugInfo *bool `json:",omitempty"` Build_from_text_stub *bool `json:",omitempty"` + BuildType *string `json:",omitempty"` + Check_elf_files *bool `json:",omitempty"` UncompressPrivAppDex *bool `json:",omitempty"` @@ -472,9 +478,8 @@ type ProductVariables struct { AfdoProfiles []string `json:",omitempty"` - ProductManufacturer string `json:",omitempty"` - ProductBrand string `json:",omitempty"` - BuildVersionTags []string `json:",omitempty"` + ProductManufacturer string `json:",omitempty"` + ProductBrand string `json:",omitempty"` ReleaseVersion string `json:",omitempty"` ReleaseAconfigValueSets []string `json:",omitempty"` @@ -502,6 +507,14 @@ type ProductVariables struct { ExportRuntimeApis *bool `json:",omitempty"` AconfigContainerValidation string `json:",omitempty"` + + ProductLocales []string `json:",omitempty"` + + ProductDefaultWifiChannels []string `json:",omitempty"` + + BoardUseVbmetaDigestInFingerprint *bool `json:",omitempty"` + + OemProperties []string `json:",omitempty"` } type PartitionQualifiedVariablesType struct { diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go index 460f1ffac..1dd479ca5 100644 --- a/androidmk/androidmk/androidmk_test.go +++ b/androidmk/androidmk/androidmk_test.go @@ -511,6 +511,22 @@ endif # b==false `, }, { + // Unsupported function case because that doesn't work in bp + desc: "error for unsupported functions", + in: ` +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(filter-out filter-out-file.java ,$(call all-java-files-under, src)) +LOCAL_PACKAGE_NAME := foo +include $(BUILD_PACKAGE) +`, + expected: ` +android_app { + name: "foo", + srcs: ["UNSUPPORTED FUNCTION:filter-out filter-out-file.java src/**/*.java"], +} + `, + }, + { desc: "ignore all-makefiles-under", in: ` include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/androidmk/parser/scope.go b/androidmk/parser/scope.go index 8111c89e1..e1a523a6b 100644 --- a/androidmk/parser/scope.go +++ b/androidmk/parser/scope.go @@ -14,9 +14,7 @@ package parser -import ( - "strings" -) +import "strings" type Scope interface { Get(name string) string @@ -88,7 +86,7 @@ func (v Variable) EvalFunction(scope Scope) ([]string, bool) { if fname == "call" { return scope.Call(argVals[0], argVals[1:]), true } else { - return []string{"__builtin_func:" + fname + " " + strings.Join(argVals, " ")}, true + return []string{"UNSUPPORTED FUNCTION:" + fname + " " + strings.Join(argVals, " ")}, true } } } diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 183e81805..64193b166 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -325,13 +325,6 @@ func canDumpAbi(config android.Config) bool { if runtime.GOOS == "darwin" { return false } - // abidw doesn't currently handle top-byte-ignore correctly. Disable ABI - // dumping for those configs while we wait for a fix. We'll still have ABI - // checking coverage from non-hwasan builds. - // http://b/190554910 - if android.InList("hwaddress", config.SanitizeDevice()) { - return false - } // http://b/156513478 return config.ReleaseNdkAbiMonitored() } diff --git a/filesystem/system_image.go b/filesystem/system_image.go index 78ce3770c..5028a493e 100644 --- a/filesystem/system_image.go +++ b/filesystem/system_image.go @@ -56,19 +56,40 @@ func (s *systemImage) buildLinkerConfigFile(ctx android.ModuleContext, root andr output := root.Join(ctx, "system", "etc", "linker.config.pb") // we need "Module"s for packaging items - var otherModules []android.Module + modulesInPackageByModule := make(map[android.Module]bool) + modulesInPackageByName := make(map[string]bool) + deps := s.gatherFilteredPackagingSpecs(ctx) ctx.WalkDeps(func(child, parent android.Module) bool { for _, ps := range child.PackagingSpecs() { if _, ok := deps[ps.RelPathInPackage()]; ok { - otherModules = append(otherModules, child) + modulesInPackageByModule[child] = true + modulesInPackageByName[child.Name()] = true + return true } } return true }) + provideModules := make([]android.Module, 0, len(modulesInPackageByModule)) + for mod := range modulesInPackageByModule { + provideModules = append(provideModules, mod) + } + + var requireModules []android.Module + ctx.WalkDeps(func(child, parent android.Module) bool { + _, parentInPackage := modulesInPackageByModule[parent] + _, childInPackageName := modulesInPackageByName[child.Name()] + + // When parent is in the package, and child (or its variant) is not, this can be from an interface. + if parentInPackage && !childInPackageName { + requireModules = append(requireModules, child) + } + return true + }) + builder := android.NewRuleBuilder(pctx, ctx) - linkerconfig.BuildLinkerConfig(ctx, builder, input, otherModules, output) + linkerconfig.BuildLinkerConfig(ctx, builder, input, provideModules, requireModules, output) builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String()) return output } diff --git a/java/aar.go b/java/aar.go index 506187959..3ac77fa44 100644 --- a/java/aar.go +++ b/java/aar.go @@ -164,7 +164,9 @@ func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) { } func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool { - return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault()) + return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault()) && + // TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries. + !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib") } func (a *aapt) filterProduct() string { @@ -387,11 +389,6 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio // Add additional manifest files to transitive manifests. additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests) transitiveManifestPaths := append(android.Paths{manifestPath}, additionalManifests...) - // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import - // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies - // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of - // android_library_import modules. If this is fixed, staticManifestsDepSet can be dropped completely in favor of - // staticResourcesNodesDepSet.manifests() transitiveManifestPaths = append(transitiveManifestPaths, staticManifestsDepSet.ToList()...) if len(transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) { @@ -763,7 +760,8 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa // reverse later. // NOTE: this is legacy and probably incorrect behavior, for most other cases (e.g. conflicting classes in // dependencies) the highest priority dependency is listed first, but for resources the highest priority - // dependency has to be listed last. + // dependency has to be listed last. This is also inconsistent with the way manifests from the same + // transitive dependencies are merged. staticResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil, android.ReverseSliceInPlace(staticResourcesNodeDepSets)) sharedResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil, @@ -978,7 +976,8 @@ type AARImport struct { properties AARImportProperties - classpathFile android.WritablePath + headerJarFile android.WritablePath + implementationJarFile android.WritablePath proguardFlags android.WritablePath exportPackage android.WritablePath transitiveAaptResourcePackagesFile android.Path @@ -999,6 +998,9 @@ type AARImport struct { sdkVersion android.SdkSpec minSdkVersion android.ApiLevel + usesLibrary + classLoaderContexts dexpreopt.ClassLoaderContextMap + // Single aconfig "cache file" merged from this module and all dependencies. mergedAconfigFiles map[string]android.Paths } @@ -1011,7 +1013,7 @@ func (a *AARImport) OutputFiles(tag string) (android.Paths, error) { case ".aar": return []android.Path{a.aarPath}, nil case "": - return []android.Path{a.classpathFile}, nil + return []android.Path{a.implementationJarFile}, nil default: return nil, fmt.Errorf("unsupported module reference tag %q", tag) } @@ -1094,6 +1096,8 @@ func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...) ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...) + + a.usesLibrary.deps(ctx, false) } type JniPackageInfo struct { @@ -1152,27 +1156,33 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { } extractedAARDir := android.PathForModuleOut(ctx, "aar") - a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar") + classpathFile := extractedAARDir.Join(ctx, "classes-combined.jar") a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml") a.rTxt = extractedAARDir.Join(ctx, "R.txt") a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip") a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt") + transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx) android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{ ProguardFlagsFiles: android.NewDepSet[android.Path]( android.POSTORDER, android.Paths{a.proguardFlags}, + transitiveProguardFlags, + ), + UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path]( + android.POSTORDER, nil, + transitiveUnconditionalExportedFlags, ), }) ctx.Build(pctx, android.BuildParams{ Rule: unzipAAR, Input: a.aarPath, - Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, a.rTxt}, + Outputs: android.WritablePaths{classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, a.rTxt}, Description: "unzip AAR", Args: map[string]string{ "outDir": extractedAARDir.String(), - "combinedClassesJar": a.classpathFile.String(), + "combinedClassesJar": classpathFile.String(), "assetsPackage": a.assetsPackage.String(), }, }) @@ -1245,13 +1255,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.resourcesNodesDepSet = resourcesNodesDepSetBuilder.Build() manifestDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(a.manifest) - // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import - // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies - // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of - // android_library_import modules. If this is fixed, AndroidLibraryDependency.ManifestsDepSet can be dropped - // completely in favor of AndroidLibraryDependency.ResourceNodesDepSet.manifest - //manifestDepSetBuilder.Transitive(transitiveStaticDeps.manifests) - _ = staticManifestsDepSet + manifestDepSetBuilder.Transitive(staticManifestsDepSet) a.manifestsDepSet = manifestDepSetBuilder.Build() transitiveAaptResourcePackages := staticDeps.resPackages().Strings() @@ -1263,12 +1267,45 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile a.collectTransitiveHeaderJars(ctx) + + a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx) + + var staticJars android.Paths + var staticHeaderJars android.Paths + ctx.VisitDirectDeps(func(module android.Module) { + if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { + tag := ctx.OtherModuleDependencyTag(module) + switch tag { + case staticLibTag: + staticJars = append(staticJars, dep.ImplementationJars...) + staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...) + } + } + addCLCFromDep(ctx, module, a.classLoaderContexts) + }) + + if len(staticJars) > 0 { + combineJars := append(android.Paths{classpathFile}, staticJars...) + a.implementationJarFile = android.PathForModuleOut(ctx, "combined", ctx.ModuleName()+".jar") + TransformJarsToJar(ctx, a.implementationJarFile, "combine", combineJars, android.OptionalPath{}, false, nil, nil) + } else { + a.implementationJarFile = classpathFile + } + + if len(staticHeaderJars) > 0 { + combineJars := append(android.Paths{classpathFile}, staticHeaderJars...) + a.headerJarFile = android.PathForModuleOut(ctx, "turbine-combined", ctx.ModuleName()+".jar") + TransformJarsToJar(ctx, a.headerJarFile, "combine header jars", combineJars, android.OptionalPath{}, false, nil, nil) + } else { + a.headerJarFile = classpathFile + } + android.SetProvider(ctx, JavaInfoProvider, JavaInfo{ - HeaderJars: android.PathsIfNonNil(a.classpathFile), + HeaderJars: android.PathsIfNonNil(a.headerJarFile), TransitiveLibsHeaderJars: a.transitiveLibsHeaderJars, TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars, - ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile), - ImplementationJars: android.PathsIfNonNil(a.classpathFile), + ImplementationAndResourcesJars: android.PathsIfNonNil(a.implementationJarFile), + ImplementationJars: android.PathsIfNonNil(a.implementationJarFile), StubsLinkType: Implementation, // TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts }) @@ -1301,15 +1338,15 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { } func (a *AARImport) HeaderJars() android.Paths { - return android.Paths{a.classpathFile} + return android.Paths{a.headerJarFile} } func (a *AARImport) ImplementationAndResourcesJars() android.Paths { - return android.Paths{a.classpathFile} + return android.Paths{a.implementationJarFile} } -func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path { - return nil +func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { + return OptionalDexJarPath{} } func (a *AARImport) DexJarInstallPath() android.Path { @@ -1317,9 +1354,11 @@ func (a *AARImport) DexJarInstallPath() android.Path { } func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { - return nil + return a.classLoaderContexts } +var _ UsesLibraryDependency = (*AARImport)(nil) + var _ android.ApexModule = (*AARImport)(nil) // Implements android.ApexModule @@ -1328,7 +1367,7 @@ func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.M } // Implements android.ApexModule -func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, +func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { return nil } @@ -1342,7 +1381,10 @@ var _ android.PrebuiltInterface = (*AARImport)(nil) func AARImportFactory() android.Module { module := &AARImport{} - module.AddProperties(&module.properties) + module.AddProperties( + &module.properties, + &module.usesLibrary.usesLibraryProperties, + ) android.InitPrebuiltModule(module, &module.properties.Aars) android.InitApexModule(module) diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go index 5909b1e6a..7c9188462 100644 --- a/java/android_manifest_test.go +++ b/java/android_manifest_test.go @@ -92,10 +92,9 @@ func TestManifestMerger(t *testing.T) { "out/soong/.intermediates/transitive/android_common/manifest_fixer/AndroidManifest.xml", "transitive/AndroidManifest2.xml", "out/soong/.intermediates/transitive_import/android_common/aar/AndroidManifest.xml", + "out/soong/.intermediates/transitive_import_dep/android_common/aar/AndroidManifest.xml", "out/soong/.intermediates/direct_import/android_common/aar/AndroidManifest.xml", - // TODO(b/288358614): Soong has historically not merged manifests from dependencies of - // android_library_import modules. - + "out/soong/.intermediates/direct_import_dep/android_common/aar/AndroidManifest.xml", }, manifestMergerRule.Implicits) } diff --git a/java/androidmk.go b/java/androidmk.go index 498962f88..a52d43965 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -211,7 +211,7 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", OverrideName: prebuilt.BaseModuleName(), - OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile), + OutputFile: android.OptionalPathForPath(prebuilt.combinedImplementationFile), Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { @@ -219,8 +219,8 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries { if prebuilt.dexJarFile.IsSet() { entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile.Path()) } - entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile) - entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile) + entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedHeaderFile) + entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedImplementationFile) entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String()) entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem()) // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts @@ -262,13 +262,13 @@ func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries { } return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", - OutputFile: android.OptionalPathForPath(prebuilt.classpathFile), + OutputFile: android.OptionalPathForPath(prebuilt.implementationJarFile), Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) - entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile) - entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile) + entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.headerJarFile) + entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.implementationJarFile) entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage) entries.SetPath("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackagesFile) entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags) diff --git a/java/app_test.go b/java/app_test.go index b75cb1678..8262777b2 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -829,12 +829,12 @@ func TestAndroidResourceProcessor(t *testing.T) { "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar", "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar", "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar", }, appCombined: []string{ "out/soong/.intermediates/app/android_common/javac/app.jar", "out/soong/.intermediates/direct/android_common/combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar", }, directResources: nil, @@ -849,12 +849,12 @@ func TestAndroidResourceProcessor(t *testing.T) { directClasspath: []string{ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar", "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar", }, directCombined: []string{ "out/soong/.intermediates/direct/android_common/javac/direct.jar", "out/soong/.intermediates/transitive/android_common/javac/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar", }, transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"}, @@ -928,13 +928,13 @@ func TestAndroidResourceProcessor(t *testing.T) { "out/soong/.intermediates/app/android_common/busybox/R.jar", "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar", "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar", }, appCombined: []string{ "out/soong/.intermediates/app/android_common/javac/app.jar", "out/soong/.intermediates/app/android_common/busybox/R.jar", "out/soong/.intermediates/direct/android_common/combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar", }, directResources: nil, @@ -953,12 +953,12 @@ func TestAndroidResourceProcessor(t *testing.T) { "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar", "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar", "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar", }, directCombined: []string{ "out/soong/.intermediates/direct/android_common/javac/direct.jar", "out/soong/.intermediates/transitive/android_common/javac/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar", }, transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"}, @@ -1034,13 +1034,13 @@ func TestAndroidResourceProcessor(t *testing.T) { "out/soong/.intermediates/app/android_common/busybox/R.jar", "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar", "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar", }, appCombined: []string{ "out/soong/.intermediates/app/android_common/javac/app.jar", "out/soong/.intermediates/app/android_common/busybox/R.jar", "out/soong/.intermediates/direct/android_common/combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar", }, dontVerifyDirect: true, @@ -1075,12 +1075,12 @@ func TestAndroidResourceProcessor(t *testing.T) { "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar", "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar", "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar", }, appCombined: []string{ "out/soong/.intermediates/app/android_common/javac/app.jar", "out/soong/.intermediates/direct/android_common/combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar", }, directResources: nil, @@ -1098,12 +1098,12 @@ func TestAndroidResourceProcessor(t *testing.T) { "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar", "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar", "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar", }, directCombined: []string{ "out/soong/.intermediates/direct/android_common/javac/direct.jar", "out/soong/.intermediates/transitive/android_common/javac/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar", }, dontVerifyTransitive: true, @@ -1137,12 +1137,12 @@ func TestAndroidResourceProcessor(t *testing.T) { "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar", "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar", "out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar", }, appCombined: []string{ "out/soong/.intermediates/app/android_common/javac/app.jar", "out/soong/.intermediates/direct/android_common/combined/direct.jar", - "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar", }, directResources: nil, @@ -1157,12 +1157,12 @@ func TestAndroidResourceProcessor(t *testing.T) { directClasspath: []string{ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar", "out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar", }, directCombined: []string{ "out/soong/.intermediates/direct/android_common/javac/direct.jar", "out/soong/.intermediates/transitive/android_common/javac/transitive.jar", - "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar", + "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar", }, transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"}, @@ -3625,7 +3625,10 @@ func TestExportedProguardFlagFiles(t *testing.T) { android_app { name: "foo", sdk_version: "current", - static_libs: ["lib1"], + static_libs: [ + "lib1", + "lib3", + ], } android_library { @@ -3633,22 +3636,49 @@ func TestExportedProguardFlagFiles(t *testing.T) { sdk_version: "current", optimize: { proguard_flags_files: ["lib1proguard.cfg"], + }, + static_libs: ["lib2"], + } + + android_library { + name: "lib2", + sdk_version: "current", + optimize: { + proguard_flags_files: ["lib2proguard.cfg"], } } - `) - m := ctx.ModuleForTests("foo", "android_common") - hasLib1Proguard := false - for _, s := range m.Rule("java.r8").Implicits.Strings() { - if s == "lib1proguard.cfg" { - hasLib1Proguard = true - break + android_library_import { + name: "lib3", + sdk_version: "current", + aars: ["lib3.aar"], + static_libs: ["lib4"], } - } - if !hasLib1Proguard { - t.Errorf("App does not use library proguard config") - } + android_library { + name: "lib4", + sdk_version: "current", + optimize: { + proguard_flags_files: ["lib4proguard.cfg"], + } + } + + + `) + + m := ctx.ModuleForTests("foo", "android_common") + r8 := m.Rule("java.r8") + implicits := r8.Implicits.RelativeToTop().Strings() + android.AssertStringListContains(t, "r8 implicits", implicits, "lib1proguard.cfg") + android.AssertStringListContains(t, "r8 implicits", implicits, "lib2proguard.cfg") + android.AssertStringListContains(t, "r8 implicits", implicits, "lib4proguard.cfg") + android.AssertStringListContains(t, "r8 implicits", implicits, "out/soong/.intermediates/lib3/android_common/aar/proguard.txt") + + flags := r8.Args["r8Flags"] + android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib1proguard.cfg") + android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib2proguard.cfg") + android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib4proguard.cfg") + android.AssertStringDoesContain(t, "r8 flags", flags, "-include out/soong/.intermediates/lib3/android_common/aar/proguard.txt") } func TestTargetSdkVersionManifestFixer(t *testing.T) { diff --git a/java/base.go b/java/base.go index be286fe33..838574df5 100644 --- a/java/base.go +++ b/java/base.go @@ -1757,10 +1757,7 @@ func (j *Module) useCompose() bool { return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs) } -func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo { - transitiveUnconditionalExportedFlags := []*android.DepSet[android.Path]{} - transitiveProguardFlags := []*android.DepSet[android.Path]{} - +func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []*android.DepSet[android.Path]) { ctx.VisitDirectDeps(func(m android.Module) { depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider) depTag := ctx.OtherModuleDependencyTag(m) @@ -1775,6 +1772,12 @@ func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpec } }) + return transitiveProguardFlags, transitiveUnconditionalExportedFlags +} + +func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo { + transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx) + directUnconditionalExportedFlags := android.Paths{} proguardFlagsForThisModule := android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files) exportUnconditionally := proptools.Bool(j.dexProperties.Optimize.Export_proguard_flags_files) diff --git a/java/java.go b/java/java.go index 97feb9bb2..72536cd6d 100644 --- a/java/java.go +++ b/java/java.go @@ -21,6 +21,7 @@ package java import ( "fmt" "path/filepath" + "slices" "sort" "strings" @@ -2337,6 +2338,9 @@ type ImportProperties struct { // List of shared java libs that this module has dependencies to Libs []string + // List of static java libs that this module has dependencies to + Static_libs []string + // List of files to remove from the jar file(s) Exclude_files []string @@ -2389,9 +2393,10 @@ type Import struct { dexJarFileErr error dexJarInstallFile android.Path - combinedClasspathFile android.Path - classLoaderContexts dexpreopt.ClassLoaderContextMap - exportAidlIncludeDirs android.Paths + combinedImplementationFile android.Path + combinedHeaderFile android.Path + classLoaderContexts dexpreopt.ClassLoaderContextMap + exportAidlIncludeDirs android.Paths hideApexVariantFromMake bool @@ -2475,6 +2480,7 @@ func (j *Import) setStrictUpdatabilityLinting(bool) { func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...) + ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...) if ctx.Device() && Bool(j.dexProperties.Compile_dex) { sdkDeps(ctx, android.SdkContext(j), j.dexer) @@ -2504,23 +2510,13 @@ func (j *Import) commonBuildActions(ctx android.ModuleContext) { func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.commonBuildActions(ctx) - jars := android.PathsForModuleSrc(ctx, j.properties.Jars) - - jarName := j.Stem() + ".jar" - outputFile := android.PathForModuleOut(ctx, "combined", jarName) - TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{}, - false, j.properties.Exclude_files, j.properties.Exclude_dirs) - if Bool(j.properties.Jetifier) { - inputFile := outputFile - outputFile = android.PathForModuleOut(ctx, "jetifier", jarName) - TransformJetifier(ctx, outputFile, inputFile) - } - j.combinedClasspathFile = outputFile j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap) var flags javaBuilderFlags j.collectTransitiveHeaderJars(ctx) + var staticJars android.Paths + var staticHeaderJars android.Paths ctx.VisitDirectDeps(func(module android.Module) { tag := ctx.OtherModuleDependencyTag(module) if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { @@ -2530,6 +2526,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...) case staticLibTag: flags.classpath = append(flags.classpath, dep.HeaderJars...) + staticJars = append(staticJars, dep.ImplementationAndResourcesJars...) + staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...) case bootClasspathTag: flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...) } @@ -2543,6 +2541,46 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { addCLCFromDep(ctx, module, j.classLoaderContexts) }) + jars := android.PathsForModuleSrc(ctx, j.properties.Jars) + jarName := j.Stem() + ".jar" + + // Always pass the input jars to TransformJarsToJar, even if there is only a single jar, we need the output + // file of the module to be named jarName. + outputFile := android.PathForModuleOut(ctx, "combined", jarName) + implementationJars := append(slices.Clone(jars), staticJars...) + TransformJarsToJar(ctx, outputFile, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{}, + false, j.properties.Exclude_files, j.properties.Exclude_dirs) + + // If no dependencies have separate header jars then there is no need to create a separate + // header jar for this module. + reuseImplementationJarAsHeaderJar := slices.Equal(staticJars, staticHeaderJars) + + var headerOutputFile android.WritablePath + if reuseImplementationJarAsHeaderJar { + headerOutputFile = outputFile + } else { + headerJars := append(slices.Clone(jars), staticHeaderJars...) + headerOutputFile = android.PathForModuleOut(ctx, "turbine-combined", jarName) + TransformJarsToJar(ctx, headerOutputFile, "combine prebuilt header jars", headerJars, android.OptionalPath{}, + false, j.properties.Exclude_files, j.properties.Exclude_dirs) + } + + if Bool(j.properties.Jetifier) { + inputFile := outputFile + outputFile = android.PathForModuleOut(ctx, "jetifier", jarName) + TransformJetifier(ctx, outputFile, inputFile) + + if !reuseImplementationJarAsHeaderJar { + headerInputFile := headerOutputFile + headerOutputFile = android.PathForModuleOut(ctx, "jetifier-headers", jarName) + TransformJetifier(ctx, headerOutputFile, headerInputFile) + } else { + headerOutputFile = outputFile + } + } + j.combinedHeaderFile = headerOutputFile + j.combinedImplementationFile = outputFile + j.maybeInstall(ctx, jarName, outputFile) j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs) @@ -2626,11 +2664,11 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } android.SetProvider(ctx, JavaInfoProvider, JavaInfo{ - HeaderJars: android.PathsIfNonNil(j.combinedClasspathFile), + HeaderJars: android.PathsIfNonNil(j.combinedHeaderFile), TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars, TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars, - ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile), - ImplementationJars: android.PathsIfNonNil(j.combinedClasspathFile), + ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile), + ImplementationJars: android.PathsIfNonNil(j.combinedImplementationFile), AidlIncludeDirs: j.exportAidlIncludeDirs, StubsLinkType: j.stubsLinkType, // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts @@ -2658,7 +2696,7 @@ func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputF func (j *Import) OutputFiles(tag string) (android.Paths, error) { switch tag { case "", ".jar": - return android.Paths{j.combinedClasspathFile}, nil + return android.Paths{j.combinedImplementationFile}, nil default: return nil, fmt.Errorf("unsupported module reference tag %q", tag) } @@ -2667,17 +2705,11 @@ func (j *Import) OutputFiles(tag string) (android.Paths, error) { var _ android.OutputFileProducer = (*Import)(nil) func (j *Import) HeaderJars() android.Paths { - if j.combinedClasspathFile == nil { - return nil - } - return android.Paths{j.combinedClasspathFile} + return android.PathsIfNonNil(j.combinedHeaderFile) } func (j *Import) ImplementationAndResourcesJars() android.Paths { - if j.combinedClasspathFile == nil { - return nil - } - return android.Paths{j.combinedClasspathFile} + return android.PathsIfNonNil(j.combinedImplementationFile) } func (j *Import) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { diff --git a/java/java_test.go b/java/java_test.go index 194f9d974..2676aa558 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -588,10 +588,11 @@ func TestPrebuilts(t *testing.T) { javac := fooModule.Rule("javac") combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac") barModule := ctx.ModuleForTests("bar", "android_common") - barJar := barModule.Rule("combineJar").Output + barJar := barModule.Output("combined/bar.jar").Output bazModule := ctx.ModuleForTests("baz", "android_common") bazJar := bazModule.Rule("combineJar").Output - sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output + sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common"). + Output("combined/sdklib.stubs.jar").Output fooLibrary := fooModule.Module().(*Library) assertDeepEquals(t, "foo unique sources incorrect", @@ -1035,7 +1036,7 @@ func TestExcludeFileGroupInSrcs(t *testing.T) { } } -func TestJavaLibrary(t *testing.T) { +func TestJavaLibraryOutputFiles(t *testing.T) { testJavaWithFS(t, "", map[string][]byte{ "libcore/Android.bp": []byte(` java_library { @@ -1052,7 +1053,7 @@ func TestJavaLibrary(t *testing.T) { }) } -func TestJavaImport(t *testing.T) { +func TestJavaImportOutputFiles(t *testing.T) { testJavaWithFS(t, "", map[string][]byte{ "libcore/Android.bp": []byte(` java_import { @@ -1068,6 +1069,85 @@ func TestJavaImport(t *testing.T) { }) } +func TestJavaImport(t *testing.T) { + bp := ` + java_library { + name: "source_library", + srcs: ["source.java"], + } + + java_import { + name: "import_with_no_deps", + jars: ["no_deps.jar"], + } + + java_import { + name: "import_with_source_deps", + jars: ["source_deps.jar"], + static_libs: ["source_library"], + } + + java_import { + name: "import_with_import_deps", + jars: ["import_deps.jar"], + static_libs: ["import_with_no_deps"], + } + ` + ctx := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + ).RunTestWithBp(t, bp) + + source := ctx.ModuleForTests("source_library", "android_common") + sourceJar := source.Output("javac/source_library.jar") + sourceHeaderJar := source.Output("turbine-combined/source_library.jar") + sourceJavaInfo, _ := android.SingletonModuleProvider(ctx, source.Module(), JavaInfoProvider) + + // The source library produces separate implementation and header jars + android.AssertPathsRelativeToTopEquals(t, "source library implementation jar", + []string{sourceJar.Output.String()}, sourceJavaInfo.ImplementationAndResourcesJars) + android.AssertPathsRelativeToTopEquals(t, "source library header jar", + []string{sourceHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars) + + importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common") + importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar") + importWithNoDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider) + + // An import with no deps produces a single jar used as both the header and implementation jar. + android.AssertPathsRelativeToTopEquals(t, "import with no deps implementation jar", + []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.ImplementationAndResourcesJars) + android.AssertPathsRelativeToTopEquals(t, "import with no deps header jar", + []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.HeaderJars) + android.AssertPathsRelativeToTopEquals(t, "import with no deps combined inputs", + []string{"no_deps.jar"}, importWithNoDepsJar.Inputs) + + importWithSourceDeps := ctx.ModuleForTests("import_with_source_deps", "android_common") + importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar") + importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar") + importWithSourceDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider) + + // An import with source deps produces separate header and implementation jars. + android.AssertPathsRelativeToTopEquals(t, "import with source deps implementation jar", + []string{importWithSourceDepsJar.Output.String()}, importWithSourceDepsJavaInfo.ImplementationAndResourcesJars) + android.AssertPathsRelativeToTopEquals(t, "import with source deps header jar", + []string{importWithSourceDepsHeaderJar.Output.String()}, importWithSourceDepsJavaInfo.HeaderJars) + android.AssertPathsRelativeToTopEquals(t, "import with source deps combined implementation jar inputs", + []string{"source_deps.jar", sourceJar.Output.String()}, importWithSourceDepsJar.Inputs) + android.AssertPathsRelativeToTopEquals(t, "import with source deps combined header jar inputs", + []string{"source_deps.jar", sourceHeaderJar.Output.String()}, importWithSourceDepsHeaderJar.Inputs) + + importWithImportDeps := ctx.ModuleForTests("import_with_import_deps", "android_common") + importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar") + importWithImportDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider) + + // An import with only import deps produces a single jar used as both the header and implementation jar. + android.AssertPathsRelativeToTopEquals(t, "import with import deps implementation jar", + []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.ImplementationAndResourcesJars) + android.AssertPathsRelativeToTopEquals(t, "import with import deps header jar", + []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.HeaderJars) + android.AssertPathsRelativeToTopEquals(t, "import with import deps combined implementation jar inputs", + []string{"import_deps.jar", importWithNoDepsJar.Output.String()}, importWithImportDepsJar.Inputs) +} + var compilerFlagsTestCases = []struct { in string out bool diff --git a/java/sdk.go b/java/sdk.go index 3591ccdb6..d972c19bd 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -31,7 +31,6 @@ func init() { var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey") var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey") -var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey") func UseApiFingerprint(ctx android.BaseModuleContext) (useApiFingerprint bool, fingerprintSdkVersion string, fingerprintDeps android.OutputPath) { if ctx.Config().UnbundledBuild() && !ctx.Config().AlwaysUsePrebuiltSdks() { @@ -45,8 +44,8 @@ func UseApiFingerprint(ctx android.BaseModuleContext) (useApiFingerprint bool, f useApiFingerprint = apiFingerprintTrue || dessertShaIsSet if apiFingerprintTrue { - fingerprintSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) - fingerprintDeps = ApiFingerprintPath(ctx) + fingerprintSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", android.ApiFingerprintPath(ctx).String()) + fingerprintDeps = android.ApiFingerprintPath(ctx) } if dessertShaIsSet { fingerprintSdkVersion = ctx.Config().Getenv("UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA") @@ -337,7 +336,7 @@ func nonUpdatableFrameworkAidlPath(ctx android.PathContext) android.OutputPath { // Create api_fingerprint.txt func createAPIFingerprint(ctx android.SingletonContext) { - out := ApiFingerprintPath(ctx) + out := android.ApiFingerprintPath(ctx) rule := android.NewRuleBuilder(pctx, ctx) @@ -378,17 +377,11 @@ func createAPIFingerprint(ctx android.SingletonContext) { rule.Build("api_fingerprint", "generate api_fingerprint.txt") } -func ApiFingerprintPath(ctx android.PathContext) android.OutputPath { - return ctx.Config().Once(apiFingerprintPathKey, func() interface{} { - return android.PathForOutput(ctx, "api_fingerprint.txt") - }).(android.OutputPath) -} - func sdkMakeVars(ctx android.MakeVarsContext) { if ctx.Config().AlwaysUsePrebuiltSdks() { return } ctx.Strict("FRAMEWORK_AIDL", sdkFrameworkAidlPath(ctx).String()) - ctx.Strict("API_FINGERPRINT", ApiFingerprintPath(ctx).String()) + ctx.Strict("API_FINGERPRINT", android.ApiFingerprintPath(ctx).String()) } diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go index 78b62d9b8..98aa40805 100644 --- a/linkerconfig/linkerconfig.go +++ b/linkerconfig/linkerconfig.go @@ -89,7 +89,7 @@ func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { output := android.PathForModuleOut(ctx, "linker.config.pb").OutputPath builder := android.NewRuleBuilder(pctx, ctx) - BuildLinkerConfig(ctx, builder, input, nil, output) + BuildLinkerConfig(ctx, builder, input, nil, nil, output) builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String()) l.outputFilePath = output @@ -101,7 +101,7 @@ func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { } func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder, - input android.Path, otherModules []android.Module, output android.OutputPath) { + input android.Path, provideModules []android.Module, requireModules []android.Module, output android.OutputPath) { // First, convert the input json to protobuf format interimOutput := android.PathForModuleOut(ctx, "temp.pb") @@ -111,9 +111,9 @@ func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder, FlagWithInput("-s ", input). FlagWithOutput("-o ", interimOutput) - // Secondly, if there's provideLibs gathered from otherModules, append them + // Secondly, if there's provideLibs gathered from provideModules, append them var provideLibs []string - for _, m := range otherModules { + for _, m := range provideModules { if c, ok := m.(*cc.Module); ok && cc.IsStubTarget(c) { for _, ps := range c.PackagingSpecs() { provideLibs = append(provideLibs, ps.FileName()) @@ -122,18 +122,45 @@ func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder, } provideLibs = android.FirstUniqueStrings(provideLibs) sort.Strings(provideLibs) + + var requireLibs []string + for _, m := range requireModules { + if c, ok := m.(*cc.Module); ok && c.HasStubsVariants() && !c.Host() { + requireLibs = append(requireLibs, c.ImplementationModuleName(ctx)+".so") + } + } + + requireLibs = android.FirstUniqueStrings(requireLibs) + sort.Strings(requireLibs) + if len(provideLibs) > 0 { + prevOutput := interimOutput + interimOutput = android.PathForModuleOut(ctx, "temp_provideLibs.pb") builder.Command(). BuiltTool("conv_linker_config"). Flag("append"). - FlagWithInput("-s ", interimOutput). - FlagWithOutput("-o ", output). + FlagWithInput("-s ", prevOutput). + FlagWithOutput("-o ", interimOutput). FlagWithArg("--key ", "provideLibs"). FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(provideLibs, " "))) - } else { - // If nothing to add, just cp to the final output - builder.Command().Text("cp").Input(interimOutput).Output(output) + builder.Temporary(prevOutput) } + if len(requireLibs) > 0 { + prevOutput := interimOutput + interimOutput = android.PathForModuleOut(ctx, "temp_requireLibs.pb") + builder.Command(). + BuiltTool("conv_linker_config"). + Flag("append"). + FlagWithInput("-s ", prevOutput). + FlagWithOutput("-o ", interimOutput). + FlagWithArg("--key ", "requireLibs"). + FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(requireLibs, " "))) + builder.Temporary(prevOutput) + } + + // cp to the final output + builder.Command().Text("cp").Input(interimOutput).Output(output) + builder.Temporary(interimOutput) builder.DeleteTemporaryFiles() } diff --git a/phony/phony.go b/phony/phony.go index b8dbd00d0..68fbf48d0 100644 --- a/phony/phony.go +++ b/phony/phony.go @@ -23,10 +23,16 @@ import ( ) func init() { - android.RegisterModuleType("phony", PhonyFactory) - android.RegisterModuleType("phony_rule", PhonyRuleFactory) + registerPhonyModuleTypes(android.InitRegistrationContext) } +func registerPhonyModuleTypes(ctx android.RegistrationContext) { + ctx.RegisterModuleType("phony", PhonyFactory) + ctx.RegisterModuleType("phony_rule", PhonyRuleFactory) +} + +var PrepareForTestWithPhony = android.FixtureRegisterWithContext(registerPhonyModuleTypes) + type phony struct { android.ModuleBase requiredModuleNames []string diff --git a/python/python.go b/python/python.go index d3cbd7695..2b1974eb8 100644 --- a/python/python.go +++ b/python/python.go @@ -545,7 +545,6 @@ func (p *PythonLibraryModule) createSrcsZip(ctx android.ModuleContext, pkgPath s var stagedProtoSrcs android.Paths for _, srcFile := range protoSrcs { stagedProtoSrc := pkgPathStagingDir.Join(ctx, pkgPath, srcFile.Rel()) - rule.Command().Text("mkdir -p").Flag(filepath.Base(stagedProtoSrc.String())) rule.Command().Text("cp -f").Input(srcFile).Output(stagedProtoSrc) stagedProtoSrcs = append(stagedProtoSrcs, stagedProtoSrc) } diff --git a/scripts/Android.bp b/scripts/Android.bp index f36329b1d..d039a8171 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -305,3 +305,14 @@ python_binary_host { }, }, } + +python_binary_host { + name: "buildinfo", + main: "buildinfo.py", + srcs: ["buildinfo.py"], + version: { + py3: { + embedded_launcher: true, + }, + }, +} diff --git a/scripts/buildinfo.py b/scripts/buildinfo.py new file mode 100755 index 000000000..e4fb0da09 --- /dev/null +++ b/scripts/buildinfo.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""A tool for generating buildinfo.prop""" + +import argparse +import contextlib +import subprocess + +def parse_args(): + """Parse commandline arguments.""" + parser = argparse.ArgumentParser() + parser.add_argument('--use-vbmeta-digest-in-fingerprint', action='store_true') + parser.add_argument('--build-flavor', required=True) + parser.add_argument('--build-hostname-file', required=True, type=argparse.FileType('r')), + parser.add_argument('--build-id', required=True) + parser.add_argument('--build-keys', required=True) + parser.add_argument('--build-number-file', required=True, type=argparse.FileType('r')) + parser.add_argument('--build-thumbprint-file', type=argparse.FileType('r')) + parser.add_argument('--build-type', required=True) + parser.add_argument('--build-username', required=True) + parser.add_argument('--build-variant', required=True) + parser.add_argument('--cpu-abis', action='append', required=True) + parser.add_argument('--date-file', required=True, type=argparse.FileType('r')) + parser.add_argument('--default-locale') + parser.add_argument('--default-wifi-channels', action='append', default=[]) + parser.add_argument('--device', required=True) + parser.add_argument("--display-build-number", action='store_true') + parser.add_argument('--platform-base-os', required=True) + parser.add_argument('--platform-display-version', required=True) + parser.add_argument('--platform-min-supported-target-sdk-version', required=True) + parser.add_argument('--platform-preview-sdk-fingerprint-file', + required=True, + type=argparse.FileType('r')) + parser.add_argument('--platform-preview-sdk-version', required=True) + parser.add_argument('--platform-sdk-version', required=True) + parser.add_argument('--platform-security-patch', required=True) + parser.add_argument('--platform-version', required=True) + parser.add_argument('--platform-version-codename',required=True) + parser.add_argument('--platform-version-all-codenames', action='append', required=True) + parser.add_argument('--platform-version-known-codenames', required=True) + parser.add_argument('--platform-version-last-stable', required=True) + parser.add_argument('--product', required=True) + + parser.add_argument('--out', required=True, type=argparse.FileType('w')) + + return parser.parse_args() + +def main(): + option = parse_args() + + build_hostname = option.build_hostname_file.read().strip() + build_number = option.build_number_file.read().strip() + build_version_tags = option.build_keys + if option.build_type == "debug": + build_version_tags = "debug," + build_version_tags + + raw_date = option.date_file.read().strip() + date = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip() + date_utc = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip() + + # build_desc is human readable strings that describe this build. This has the same info as the + # build fingerprint. + # e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys" + build_desc = f"{option.product}-{option.build_variant} {option.platform_version} " \ + f"{option.build_id} {build_number} {build_version_tags}" + + platform_preview_sdk_fingerprint = option.platform_preview_sdk_fingerprint_file.read().strip() + + with contextlib.redirect_stdout(option.out): + print("# begin build properties") + print("# autogenerated by buildinfo.py") + + # The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest. + if option.use_vbmeta_digest_in_fingerprint: + print(f"ro.build.legacy.id={option.build_id}") + else: + print(f"ro.build.id?={option.build_id}") + + # ro.build.display.id is shown under Settings -> About Phone + if option.build_variant == "user": + # User builds should show: + # release build number or branch.buld_number non-release builds + + # Dev. branches should have DISPLAY_BUILD_NUMBER set + if option.display_build_number: + print(f"ro.build.display.id?={option.build_id} {build_number} {option.build_keys}") + else: + print(f"ro.build.display.id?={option.build_id} {option.build_keys}") + else: + # Non-user builds should show detailed build information (See build desc above) + print(f"ro.build.display.id?={build_desc}") + print(f"ro.build.version.incremental={build_number}") + print(f"ro.build.version.sdk={option.platform_sdk_version}") + print(f"ro.build.version.preview_sdk={option.platform_preview_sdk_version}") + print(f"ro.build.version.preview_sdk_fingerprint={platform_preview_sdk_fingerprint}") + print(f"ro.build.version.codename={option.platform_version_codename}") + print(f"ro.build.version.all_codenames={','.join(option.platform_version_all_codenames)}") + print(f"ro.build.version.known_codenames={option.platform_version_known_codenames}") + print(f"ro.build.version.release={option.platform_version_last_stable}") + print(f"ro.build.version.release_or_codename={option.platform_version}") + print(f"ro.build.version.release_or_preview_display={option.platform_display_version}") + print(f"ro.build.version.security_patch={option.platform_security_patch}") + print(f"ro.build.version.base_os={option.platform_base_os}") + print(f"ro.build.version.min_supported_target_sdk={option.platform_min_supported_target_sdk_version}") + print(f"ro.build.date={date}") + print(f"ro.build.date.utc={date_utc}") + print(f"ro.build.type={option.build_variant}") + print(f"ro.build.user={option.build_username}") + print(f"ro.build.host={build_hostname}") + # TODO: Remove any tag-related optional property declarations once the goals + # from go/arc-android-sigprop-changes have been achieved. + print(f"ro.build.tags?={build_version_tags}") + # ro.build.flavor are used only by the test harness to distinguish builds. + # Only add _asan for a sanitized build if it isn't already a part of the + # flavor (via a dedicated lunch config for example). + print(f"ro.build.flavor={option.build_flavor}") + + # These values are deprecated, use "ro.product.cpu.abilist" + # instead (see below). + print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,") + print(f"# use ro.product.cpu.abilist instead.") + print(f"ro.product.cpu.abi={option.cpu_abis[0]}") + if len(option.cpu_abis) > 1: + print(f"ro.product.cpu.abi2={option.cpu_abis[1]}") + + if option.default_locale: + print(f"ro.product.locale={option.default_locale}") + print(f"ro.wifi.channels={' '.join(option.default_wifi_channels)}") + + print(f"# ro.build.product is obsolete; use ro.product.device") + print(f"ro.build.product={option.device}") + + print(f"# Do not try to parse description or thumbprint") + print(f"ro.build.description?={build_desc}") + if option.build_thumbprint_file: + build_thumbprint = option.build_thumbprint_file.read().strip() + print(f"ro.build.thumbprint={build_thumbprint}") + + print(f"# end build properties") + +if __name__ == "__main__": + main() |