diff options
| -rw-r--r-- | android/bazel_handler.go | 4 | ||||
| -rw-r--r-- | android/config.go | 10 | ||||
| -rw-r--r-- | android/variable.go | 3 | ||||
| -rw-r--r-- | apex/apex.go | 43 | ||||
| -rw-r--r-- | bp2build/cc_library_conversion_test.go | 56 | ||||
| -rw-r--r-- | cc/bp2build.go | 67 | ||||
| -rw-r--r-- | cc/builder.go | 23 | ||||
| -rw-r--r-- | cc/object.go | 9 | ||||
| -rw-r--r-- | cmd/soong_build/main.go | 10 | ||||
| -rw-r--r-- | device_config/Android.bp | 30 | ||||
| -rw-r--r-- | device_config/device_config_definitions.go | 150 | ||||
| -rw-r--r-- | device_config/device_config_test.go | 61 | ||||
| -rw-r--r-- | device_config/device_config_value_set.go | 92 | ||||
| -rw-r--r-- | device_config/device_config_values.go | 70 | ||||
| -rw-r--r-- | device_config/init.go | 70 | ||||
| -rw-r--r-- | device_config/testing.go | 19 | ||||
| -rw-r--r-- | etc/prebuilt_etc.go | 4 | ||||
| -rw-r--r-- | java/app_test.go | 4 | ||||
| -rw-r--r-- | java/dex.go | 19 | ||||
| -rw-r--r-- | ui/build/config.go | 5 |
20 files changed, 724 insertions, 25 deletions
diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 5291ecae9..10cf60a0a 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -29,6 +29,7 @@ import ( "android/soong/bazel/cquery" "android/soong/shared" "android/soong/starlark_fmt" + "github.com/google/blueprint" "github.com/google/blueprint/metrics" @@ -700,9 +701,6 @@ func (context *mixedBuildBazelContext) createBazelCommand(config Config, runName // We don't need to set --host_platforms because it's set in bazelrc files // that the bazel shell script wrapper passes - // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network. - "--experimental_repository_disable_download", - // Suppress noise "--ui_event_filters=-INFO", "--noshow_progress", diff --git a/android/config.go b/android/config.go index 9e94e0517..acadb3ff3 100644 --- a/android/config.go +++ b/android/config.go @@ -183,6 +183,16 @@ func (c Config) MaxPageSizeSupported() string { return String(c.config.productVariables.DeviceMaxPageSizeSupported) } +// The release version passed to aconfig, derived from RELEASE_VERSION +func (c Config) ReleaseVersion() string { + return c.config.productVariables.ReleaseVersion +} + +// The flag values files passed to aconfig, derived from RELEASE_VERSION +func (c Config) ReleaseDeviceConfigValueSets() []string { + return c.config.productVariables.ReleaseDeviceConfigValueSets +} + // A DeviceConfig object represents the configuration for a particular device // being built. For now there will only be one of these, but in the future there // may be multiple devices being built. diff --git a/android/variable.go b/android/variable.go index bf66135b5..97171e7b9 100644 --- a/android/variable.go +++ b/android/variable.go @@ -473,6 +473,9 @@ type productVariables struct { ProductManufacturer string `json:",omitempty"` ProductBrand string `json:",omitempty"` BuildVersionTags []string `json:",omitempty"` + + ReleaseVersion string `json:",omitempty"` + ReleaseDeviceConfigValueSets []string `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/apex/apex.go b/apex/apex.go index 026734eee..ff7ee35c0 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -404,7 +404,7 @@ type apexBundle struct { /////////////////////////////////////////////////////////////////////////////////////////// // Inputs - // Keys for apex_paylaod.img + // Keys for apex_payload.img publicKeyFile android.Path privateKeyFile android.Path @@ -2606,8 +2606,45 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) }) vctx.normalizeFileInfo(ctx) if a.privateKeyFile == nil { - ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key)) - return + if ctx.Config().AllowMissingDependencies() { + // TODO(b/266099037): a better approach for slim manifests. + ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)}) + // Create placeholder paths for later stages that expect to see those paths, + // though they won't be used. + var unusedPath = android.PathForModuleOut(ctx, "nonexistentprivatekey") + ctx.Build(pctx, android.BuildParams{ + Rule: android.ErrorRule, + Output: unusedPath, + Args: map[string]string{ + "error": "Private key not available", + }, + }) + a.privateKeyFile = unusedPath + } else { + ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key)) + return + } + } + + if a.publicKeyFile == nil { + if ctx.Config().AllowMissingDependencies() { + // TODO(b/266099037): a better approach for slim manifests. + ctx.AddMissingDependencies([]string{String(a.overridableProperties.Key)}) + // Create placeholder paths for later stages that expect to see those paths, + // though they won't be used. + var unusedPath = android.PathForModuleOut(ctx, "nonexistentpublickey") + ctx.Build(pctx, android.BuildParams{ + Rule: android.ErrorRule, + Output: unusedPath, + Args: map[string]string{ + "error": "Public key not available", + }, + }) + a.publicKeyFile = unusedPath + } else { + ctx.PropertyErrorf("key", "public_key for %q could not be found", String(a.overridableProperties.Key)) + return + } } //////////////////////////////////////////////////////////////////////////////////////////// diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index e998ac8f4..17b160861 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -4601,3 +4601,59 @@ func TestCcLibraryCppFlagsInProductVariables(t *testing.T) { }, ) } + +func TestCcLibraryYaccConversion(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + Description: "cc_library is built from .y/.yy files", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Blueprint: soongCcLibraryPreamble + `cc_library { + name: "a", + srcs: [ + "a.cpp", + "a.yy", + ], + shared_libs: ["sharedlib"], + static_libs: ["staticlib"], + yacc: { + flags: ["someYaccFlag"], + gen_location_hh: true, + gen_position_hh: true, + }, +} +cc_library_static { + name: "staticlib", + bazel_module: { bp2build_available: false }, +} +cc_library { + name: "sharedlib", + bazel_module: { bp2build_available: false }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_yacc_static_library", "a_yacc", AttrNameToString{ + "src": `"a.yy"`, + "implementation_deps": `[":staticlib"]`, + "implementation_dynamic_deps": `[":sharedlib"]`, + "flags": `["someYaccFlag"]`, + "gen_location_hh": "True", + "gen_position_hh": "True", + "local_includes": `["."]`, + }), + MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ + "srcs": `["a.cpp"]`, + "implementation_deps": `[":staticlib"]`, + "implementation_dynamic_deps": `[":sharedlib"]`, + "implementation_whole_archive_deps": `[":a_yacc"]`, + "local_includes": `["."]`, + }), + MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + "srcs": `["a.cpp"]`, + "implementation_deps": `[":staticlib"]`, + "implementation_dynamic_deps": `[":sharedlib"]`, + "implementation_whole_archive_deps": `[":a_yacc"]`, + "local_includes": `["."]`, + }), + }, + }) +} diff --git a/cc/bp2build.go b/cc/bp2build.go index 0f978a5ca..29e849477 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -38,6 +38,7 @@ const ( protoSrcPartition = "proto" aidlSrcPartition = "aidl" syspropSrcPartition = "sysprop" + yaccSrcPartition = "yacc" stubsSuffix = "_stub_libs_current" ) @@ -154,6 +155,7 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab // know the language of these sources until the genrule is executed. cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true}, syspropSrcPartition: bazel.LabelPartition{Extensions: []string{".sysprop"}}, + yaccSrcPartition: bazel.LabelPartition{Extensions: []string{".y", "yy"}}, } return bazel.PartitionLabelListAttribute(ctx, &srcs, labels) @@ -404,6 +406,12 @@ type compilerAttributes struct { // Sysprop sources syspropSrcs bazel.LabelListAttribute + // Yacc sources + yaccSrc *bazel.LabelAttribute + yaccFlags bazel.StringListAttribute + yaccGenLocationHeader bazel.BoolAttribute + yaccGenPositionHeader bazel.BoolAttribute + hdrs bazel.LabelListAttribute rtti bazel.BoolAttribute @@ -566,6 +574,12 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i ca.asmSrcs = partitionedSrcs[asmSrcPartition] ca.lSrcs = partitionedSrcs[lSrcPartition] ca.llSrcs = partitionedSrcs[llSrcPartition] + if yacc := partitionedSrcs[yaccSrcPartition]; !yacc.IsEmpty() { + if len(yacc.Value.Includes) > 1 { + ctx.PropertyErrorf("srcs", "Found multiple yacc (.y/.yy) files in library") + } + ca.yaccSrc = bazel.MakeLabelAttribute(yacc.Value.Includes[0].Label) + } ca.syspropSrcs = partitionedSrcs[syspropSrcPartition] ca.absoluteIncludes.DeduplicateAxesFromBase() @@ -744,6 +758,11 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) if baseCompilerProps.Lex != nil { compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags) } + if baseCompilerProps.Yacc != nil { + compilerAttrs.yaccFlags.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Flags) + compilerAttrs.yaccGenLocationHeader.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Gen_location_hh) + compilerAttrs.yaccGenPositionHeader.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Gen_position_hh) + } (&compilerAttrs).bp2buildForAxisAndConfig(ctx, axis, cfg, baseCompilerProps) aidlLibs.Append(android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Aidl.Libs)) } @@ -836,6 +855,12 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) } } + // Create a cc_yacc_static_library if srcs contains .y/.yy files + // This internal target will produce an .a file that will be statically linked to the parent library + if yaccDep := bp2buildCcYaccLibrary(ctx, compilerAttrs, linkerAttrs); yaccDep != nil { + (&linkerAttrs).implementationWholeArchiveDeps.Add(yaccDep) + } + convertedLSrcs := bp2BuildLex(ctx, module.Name(), compilerAttrs) (&compilerAttrs).srcs.Add(&convertedLSrcs.srcName) (&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName) @@ -874,6 +899,48 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) } } +type ccYaccLibraryAttributes struct { + Src bazel.LabelAttribute + Flags bazel.StringListAttribute + Gen_location_hh bazel.BoolAttribute + Gen_position_hh bazel.BoolAttribute + Local_includes bazel.StringListAttribute + Implementation_deps bazel.LabelListAttribute + Implementation_dynamic_deps bazel.LabelListAttribute +} + +func bp2buildCcYaccLibrary(ctx android.Bp2buildMutatorContext, ca compilerAttributes, la linkerAttributes) *bazel.LabelAttribute { + if ca.yaccSrc == nil { + return nil + } + yaccLibraryLabel := ctx.Module().Name() + "_yacc" + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: "cc_yacc_static_library", + Bzl_load_location: "//build/bazel/rules/cc:cc_yacc_library.bzl", + }, + android.CommonAttributes{ + Name: yaccLibraryLabel, + }, + &ccYaccLibraryAttributes{ + Src: *ca.yaccSrc, + Flags: ca.yaccFlags, + Gen_location_hh: ca.yaccGenLocationHeader, + Gen_position_hh: ca.yaccGenPositionHeader, + Local_includes: ca.localIncludes, + Implementation_deps: la.implementationDeps, + Implementation_dynamic_deps: la.implementationDynamicDeps, + }, + ) + + yaccLibrary := &bazel.LabelAttribute{ + Value: &bazel.Label{ + Label: ":" + yaccLibraryLabel, + }, + } + return yaccLibrary +} + // As a workaround for b/261657184, we are manually adding the default value // of system_dynamic_deps for the linux_musl os. // TODO: Solve this properly diff --git a/cc/builder.go b/cc/builder.go index fef00d4d5..f5e0dcca5 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -125,6 +125,14 @@ var ( }, "objcopyCmd", "prefix") + // Rule to run objcopy --remove-section=.llvm_addrsig on a partially linked object + noAddrSig = pctx.AndroidStaticRule("noAddrSig", + blueprint.RuleParams{ + Command: "rm -f ${out} && $objcopyCmd --remove-section=.llvm_addrsig ${in} ${out}", + CommandDeps: []string{"$objcopyCmd"}, + }, + "objcopyCmd") + _ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh") _ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz") _ = pctx.SourcePathVariable("createMiniDebugInfo", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/create_minidebuginfo") @@ -1008,6 +1016,21 @@ func transformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inpu }) } +// Generate a rule for running objcopy --remove-section=.llvm_addrsig on a partially linked object +func transformObjectNoAddrSig(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) { + objcopyCmd := "${config.ClangBin}/llvm-objcopy" + + ctx.Build(pctx, android.BuildParams{ + Rule: noAddrSig, + Description: "remove addrsig " + outputFile.Base(), + Output: outputFile, + Input: inputFile, + Args: map[string]string{ + "objcopyCmd": objcopyCmd, + }, + }) +} + // Registers a build statement to invoke `strip` (to discard symbols and data from object files). func transformStrip(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath, flags StripFlags) { diff --git a/cc/object.go b/cc/object.go index 5d6187233..ca1484538 100644 --- a/cc/object.go +++ b/cc/object.go @@ -309,6 +309,8 @@ func (object *objectLinker) link(ctx ModuleContext, }) } } else { + outputAddrSig := android.PathForModuleOut(ctx, "addrsig", outputName) + if String(object.Properties.Prefix_symbols) != "" { input := android.PathForModuleOut(ctx, "unprefixed", outputName) transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input, @@ -316,7 +318,12 @@ func (object *objectLinker) link(ctx ModuleContext, output = input } - transformObjsToObj(ctx, objs.objFiles, builderFlags, output, flags.LdFlagsDeps) + transformObjsToObj(ctx, objs.objFiles, builderFlags, outputAddrSig, flags.LdFlagsDeps) + + // ld -r reorders symbols and invalidates the .llvm_addrsig section, which then causes warnings + // if the resulting object is used with ld --icf=safe. Strip the .llvm_addrsig section to + // prevent the warnings. + transformObjectNoAddrSig(ctx, outputAddrSig, output) } ctx.CheckbuildFile(outputFile) diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 10b09d3eb..cf6c1c7b8 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -133,6 +133,10 @@ func runMixedModeBuild(ctx *android.Context, extraNinjaDeps []string) string { ninjaDeps = append(ninjaDeps, writeBuildGlobsNinjaFile(ctx)...) writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps) + + if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") { + writeNinjaHint(ctx) + } return cmdlineArgs.OutFile } @@ -455,6 +459,9 @@ func runSoongOnlyBuild(ctx *android.Context, extraNinjaDeps []string) string { // The actual output (build.ninja) was written in the RunBlueprint() call // above writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps) + if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") { + writeNinjaHint(ctx) + } return cmdlineArgs.OutFile } } @@ -535,9 +542,6 @@ func main() { } else { finalOutputFile = runSoongOnlyBuild(ctx, extraNinjaDeps) } - if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") { - writeNinjaHint(ctx) - } writeMetrics(configuration, ctx.EventHandler, metricsDir) } writeUsedEnvironmentFile(configuration) diff --git a/device_config/Android.bp b/device_config/Android.bp new file mode 100644 index 000000000..360b3898a --- /dev/null +++ b/device_config/Android.bp @@ -0,0 +1,30 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-device_config", + pkgPath: "android/soong/device_config", + deps: [ + "blueprint", + "blueprint-pathtools", + "sbox_proto", + "soong", + "soong-android", + "soong-bazel", + "soong-shared", + ], + srcs: [ + "device_config_definitions.go", + "device_config_values.go", + "device_config_value_set.go", + "init.go", + //"testing.go" + ], + /* + testSrcs: [ + "device_config_test.go", + ], + */ + pluginFor: ["soong_build"], +} diff --git a/device_config/device_config_definitions.go b/device_config/device_config_definitions.go new file mode 100644 index 000000000..c5657666c --- /dev/null +++ b/device_config/device_config_definitions.go @@ -0,0 +1,150 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package device_config + +import ( + "android/soong/android" + "fmt" + "github.com/google/blueprint" + "strings" +) + +type DefinitionsModule struct { + android.ModuleBase + android.DefaultableModuleBase + + // Properties for "device_config_definitions" + properties struct { + // aconfig files, relative to this Android.bp file + Srcs []string `android:"path"` + + // Release config flag namespace + Namespace string + + // Values from TARGET_RELEASE / RELEASE_DEVICE_CONFIG_VALUE_SETS + Values []string `blueprint:"mutated"` + } + + intermediatePath android.WritablePath + srcJarPath android.WritablePath +} + +func DefinitionsFactory() android.Module { + module := &DefinitionsModule{} + + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + // TODO: bp2build + //android.InitBazelModule(module) + + return module +} + +type implicitValuesTagType struct { + blueprint.BaseDependencyTag +} + +var implicitValuesTag = implicitValuesTagType{} + +func (module *DefinitionsModule) DepsMutator(ctx android.BottomUpMutatorContext) { + // Validate Properties + if len(module.properties.Srcs) == 0 { + ctx.PropertyErrorf("srcs", "missing source files") + return + } + if len(module.properties.Namespace) == 0 { + ctx.PropertyErrorf("namespace", "missing namespace property") + } + + // Add a dependency on the device_config_value_sets defined in + // RELEASE_DEVICE_CONFIG_VALUE_SETS, and add any device_config_values that + // match our namespace. + valuesFromConfig := ctx.Config().ReleaseDeviceConfigValueSets() + ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...) +} + +func (module *DefinitionsModule) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case ".srcjar": + return []android.Path{module.srcJarPath}, nil + case "": + // The default output of this module is the intermediates format, which is + // not installable and in a private format that no other rules can handle + // correctly. + return []android.Path{module.intermediatePath}, nil + default: + return nil, fmt.Errorf("unsupported device_config_definitions module reference tag %q", tag) + } +} + +func joinAndPrefix(prefix string, values []string) string { + var sb strings.Builder + for _, v := range values { + sb.WriteString(prefix) + sb.WriteString(v) + } + return sb.String() +} + +func (module *DefinitionsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Get the values that came from the global RELEASE_DEVICE_CONFIG_VALUE_SETS flag + ctx.VisitDirectDeps(func(dep android.Module) { + if !ctx.OtherModuleHasProvider(dep, valueSetProviderKey) { + // Other modules get injected as dependencies too, for example the license modules + return + } + depData := ctx.OtherModuleProvider(dep, valueSetProviderKey).(valueSetProviderData) + valuesFiles, ok := depData.AvailableNamespaces[module.properties.Namespace] + if ok { + for _, path := range valuesFiles { + module.properties.Values = append(module.properties.Values, path.String()) + } + } + }) + + // Intermediate format + inputFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs) + module.intermediatePath = android.PathForModuleOut(ctx, "intermediate.json") + ctx.Build(pctx, android.BuildParams{ + Rule: aconfigRule, + Inputs: inputFiles, + Output: module.intermediatePath, + Description: "device_config_definitions", + Args: map[string]string{ + "release_version": ctx.Config().ReleaseVersion(), + "namespace": module.properties.Namespace, + "values": joinAndPrefix(" --values ", module.properties.Values), + }, + }) + + // Generated java inside a srcjar + module.srcJarPath = android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar") + ctx.Build(pctx, android.BuildParams{ + Rule: srcJarRule, + Input: module.intermediatePath, + Output: module.srcJarPath, + Description: "device_config.srcjar", + }) + + // TODO: C++ + + // Phony target for debugging convenience + ctx.Build(pctx, android.BuildParams{ + Rule: blueprint.Phony, + Output: android.PathForPhony(ctx, ctx.ModuleName()), + Inputs: []android.Path{module.srcJarPath}, // TODO: C++ + }) +} diff --git a/device_config/device_config_test.go b/device_config/device_config_test.go new file mode 100644 index 000000000..91a06a781 --- /dev/null +++ b/device_config/device_config_test.go @@ -0,0 +1,61 @@ +// Copyright (C) 2019 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package device_config + +import ( + "os" + "testing" + + "android/soong/android" + "android/soong/java" +) + +func TestMain(m *testing.M) { + os.Exit(m.Run()) +} + +func test(t *testing.T, bp string) *android.TestResult { + t.Helper() + + mockFS := android.MockFS{ + "config.aconfig": nil, + } + + result := android.GroupFixturePreparers( + java.PrepareForTestWithJavaDefaultModules, + PrepareForTestWithSyspropBuildComponents, + // TODO: Consider values files, although maybe in its own test + // android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + // variables.ReleaseConfigValuesBasePaths = ... + //}) + mockFS.AddToFixture(), + android.FixtureWithRootAndroidBp(bp), + ).RunTest(t) + + return result +} + +func TestOutputs(t *testing.T) { + /*result := */ test(t, ` + device_config { + name: "my_device_config", + srcs: ["config.aconfig"], + } + `) + + // TODO: Make sure it exports a .srcjar, which is used by java libraries + // TODO: Make sure it exports an intermediates file + // TODO: Make sure the intermediates file is propagated to the Android.mk file +} diff --git a/device_config/device_config_value_set.go b/device_config/device_config_value_set.go new file mode 100644 index 000000000..e406d20e0 --- /dev/null +++ b/device_config/device_config_value_set.go @@ -0,0 +1,92 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package device_config + +import ( + "android/soong/android" + "github.com/google/blueprint" +) + +// Properties for "device_config_value_set" +type ValueSetModule struct { + android.ModuleBase + android.DefaultableModuleBase + + properties struct { + // device_config_values modules + Values []string + } +} + +func ValueSetFactory() android.Module { + module := &ValueSetModule{} + + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + // TODO: bp2build + //android.InitBazelModule(module) + + return module +} + +// Dependency tag for values property +type valueSetType struct { + blueprint.BaseDependencyTag +} + +var valueSetTag = valueSetType{} + +// Provider published by device_config_value_set +type valueSetProviderData struct { + // The namespace of each of the + // (map of namespace --> device_config_module) + AvailableNamespaces map[string]android.Paths +} + +var valueSetProviderKey = blueprint.NewProvider(valueSetProviderData{}) + +func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) { + deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...) + for _, dep := range deps { + _, ok := dep.(*ValuesModule) + if !ok { + ctx.PropertyErrorf("values", "values must be a device_config_values module") + return + } + } +} + +func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Accumulate the namespaces of the values modules listed, and set that as an + // valueSetProviderKey provider that device_config modules can read and use + // to append values to their aconfig actions. + namespaces := make(map[string]android.Paths) + ctx.VisitDirectDeps(func(dep android.Module) { + if !ctx.OtherModuleHasProvider(dep, valuesProviderKey) { + // Other modules get injected as dependencies too, for example the license modules + return + } + depData := ctx.OtherModuleProvider(dep, valuesProviderKey).(valuesProviderData) + + srcs := make([]android.Path, len(depData.Values)) + copy(srcs, depData.Values) + namespaces[depData.Namespace] = srcs + + }) + ctx.SetProvider(valueSetProviderKey, valueSetProviderData{ + AvailableNamespaces: namespaces, + }) +} diff --git a/device_config/device_config_values.go b/device_config/device_config_values.go new file mode 100644 index 000000000..110f12a1c --- /dev/null +++ b/device_config/device_config_values.go @@ -0,0 +1,70 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package device_config + +import ( + "android/soong/android" + "github.com/google/blueprint" +) + +// Properties for "device_config_value" +type ValuesModule struct { + android.ModuleBase + android.DefaultableModuleBase + + properties struct { + // aconfig files, relative to this Android.bp file + Srcs []string `android:"path"` + + // Release config flag namespace + Namespace string + } +} + +func ValuesFactory() android.Module { + module := &ValuesModule{} + + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + // TODO: bp2build + //android.InitBazelModule(module) + + return module +} + +// Provider published by device_config_value_set +type valuesProviderData struct { + // The namespace that this values module values + Namespace string + + // The values aconfig files, relative to the root of the tree + Values android.Paths +} + +var valuesProviderKey = blueprint.NewProvider(valuesProviderData{}) + +func (module *ValuesModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if len(module.properties.Namespace) == 0 { + ctx.PropertyErrorf("namespace", "missing namespace property") + } + + // Provide the our source files list to the device_config_value_set as a list of files + providerData := valuesProviderData{ + Namespace: module.properties.Namespace, + Values: android.PathsForModuleSrc(ctx, module.properties.Srcs), + } + ctx.SetProvider(valuesProviderKey, providerData) +} diff --git a/device_config/init.go b/device_config/init.go new file mode 100644 index 000000000..0a4645b2b --- /dev/null +++ b/device_config/init.go @@ -0,0 +1,70 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package device_config + +import ( + "android/soong/android" + "github.com/google/blueprint" +) + +var ( + pctx = android.NewPackageContext("android/soong/device_config") + + // For device_config_definitions: Generate cache file + // TODO: Restat + aconfigRule = pctx.AndroidStaticRule("aconfig", + blueprint.RuleParams{ + Command: `${aconfig} create-cache` + + ` --namespace ${namespace}` + + ` --declarations ${in}` + + ` ${values}` + + ` --cache ${out}.tmp` + + ` && ( if cmp -s ${out}.tmp ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`, + // ` --build-id ${release_version}` + + CommandDeps: []string{ + "${aconfig}", + }, + Restat: true, + }, "release_version", "namespace", "values") + + // For device_config_definitions: Generate java file + srcJarRule = pctx.AndroidStaticRule("aconfig_srcjar", + blueprint.RuleParams{ + Command: `rm -rf ${out}.tmp` + + ` && mkdir -p ${out}.tmp` + + ` && ${aconfig} create-java-lib` + + ` --cache ${in}` + + ` --out ${out}.tmp` + + ` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` + + ` && rm -rf ${out}.tmp`, + CommandDeps: []string{ + "$aconfig", + "$soong_zip", + }, + Restat: true, + }) +) + +func init() { + registerBuildComponents(android.InitRegistrationContext) +} + +func registerBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("device_config_definitions", DefinitionsFactory) + ctx.RegisterModuleType("device_config_values", ValuesFactory) + ctx.RegisterModuleType("device_config_value_set", ValueSetFactory) + pctx.HostBinToolVariable("aconfig", "aconfig") + pctx.HostBinToolVariable("soong_zip", "soong_zip") +} diff --git a/device_config/testing.go b/device_config/testing.go new file mode 100644 index 000000000..f0544766b --- /dev/null +++ b/device_config/testing.go @@ -0,0 +1,19 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package device_config + +import "android/soong/android" + +var PrepareForTestWithSyspropBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents) diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index 6817dcef0..3e1bbded6 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -652,9 +652,7 @@ func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.Singleto prop := snapshot.SnapshotJsonFlags{} propOut := snapshotLibOut + ".json" prop.InitBaseSnapshotProps(m) - if m.subdirProperties.Relative_install_path != nil { - prop.RelativeInstallPath = *m.subdirProperties.Relative_install_path - } + prop.RelativeInstallPath = m.SubDir() if m.properties.Filename != nil { prop.Filename = *m.properties.Filename diff --git a/java/app_test.go b/java/app_test.go index daff94ca9..8a69a03e7 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -443,9 +443,9 @@ func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits var crtbeginFound, crtendFound bool expectedCrtBegin := ctx.ModuleForTests("crtbegin_so", - "android_arm64_armv8-a_sdk_29").Rule("partialLd").Output + "android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output expectedCrtEnd := ctx.ModuleForTests("crtend_so", - "android_arm64_armv8-a_sdk_29").Rule("partialLd").Output + "android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output implicits := []string{} for _, input := range inputs { implicits = append(implicits, input.String()) diff --git a/java/dex.go b/java/dex.go index f7c1361e2..7e7da00fd 100644 --- a/java/dex.go +++ b/java/dex.go @@ -161,7 +161,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", "$r8Template": &remoteexec.REParams{ Labels: map[string]string{"type": "compile", "compiler": "r8"}, Inputs: []string{"$implicits", "${config.R8Jar}"}, - OutputFiles: []string{"${outUsage}"}, + OutputFiles: []string{"${outUsage}", "${outConfig}", "${outDict}"}, ExecStrategy: "${config.RER8ExecStrategy}", ToolchainInputs: []string{"${config.JavaCmd}"}, Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, @@ -399,13 +399,16 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam args["implicits"] = strings.Join(r8Deps.Strings(), ",") } ctx.Build(pctx, android.BuildParams{ - Rule: rule, - Description: "r8", - Output: javalibJar, - ImplicitOutputs: android.WritablePaths{proguardDictionary, proguardUsageZip}, - Input: dexParams.classesJar, - Implicits: r8Deps, - Args: args, + Rule: rule, + Description: "r8", + Output: javalibJar, + ImplicitOutputs: android.WritablePaths{ + proguardDictionary, + proguardUsageZip, + proguardConfiguration}, + Input: dexParams.classesJar, + Implicits: r8Deps, + Args: args, }) } else { d8Flags, d8Deps := d8Flags(dexParams.flags) diff --git a/ui/build/config.go b/ui/build/config.go index 8ec96800f..6b6ce7154 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -316,8 +316,9 @@ func UploadOnlyConfig(ctx Context, args ...string) Config { func NewConfig(ctx Context, args ...string) Config { ret := &configImpl{ - environ: OsEnvironment(), - sandboxConfig: &SandboxConfig{}, + environ: OsEnvironment(), + sandboxConfig: &SandboxConfig{}, + ninjaWeightListSource: HINT_FROM_SOONG, } // Default matching ninja |