From c6aef1681629bcc309a8937fed8574d9e076a488 Mon Sep 17 00:00:00 2001 From: LaMont Jones Date: Mon, 20 May 2024 10:37:25 -0700 Subject: [PATCH] Add build_flag_declarations module And generate build-flags/build_flags.{pb,textproto} files Bug: 328495189 Test: manual,TH Change-Id: I97eb864e2d84bc606fef7e9077554894338edaa0 --- aconfig/build_flags/Android.bp | 23 ++++ .../all_build_flag_declarations.go | 78 ++++++++++++ aconfig/build_flags/declarations.go | 118 ++++++++++++++++++ aconfig/build_flags/init.go | 78 ++++++++++++ 4 files changed, 297 insertions(+) create mode 100644 aconfig/build_flags/Android.bp create mode 100644 aconfig/build_flags/all_build_flag_declarations.go create mode 100644 aconfig/build_flags/declarations.go create mode 100644 aconfig/build_flags/init.go diff --git a/aconfig/build_flags/Android.bp b/aconfig/build_flags/Android.bp new file mode 100644 index 000000000..69e431606 --- /dev/null +++ b/aconfig/build_flags/Android.bp @@ -0,0 +1,23 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-aconfig-build_flags", + pkgPath: "android/soong/aconfig/build_flags", + deps: [ + "blueprint", + "blueprint-pathtools", + "sbox_proto", + "soong", + "soong-android", + ], + srcs: [ + "all_build_flag_declarations.go", + "declarations.go", + "init.go", + ], + testSrcs: [ + ], + pluginFor: ["soong_build"], +} diff --git a/aconfig/build_flags/all_build_flag_declarations.go b/aconfig/build_flags/all_build_flag_declarations.go new file mode 100644 index 000000000..282c9dcf8 --- /dev/null +++ b/aconfig/build_flags/all_build_flag_declarations.go @@ -0,0 +1,78 @@ +// 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 build_flags + +import ( + "android/soong/android" +) + +// A singleton module that collects all of the build flags declared in the +// tree into a single combined file for export to the external flag setting +// server (inside Google it's Gantry). +// +// Note that this is ALL build_declarations modules present in the tree, not just +// ones that are relevant to the product currently being built, so that that infra +// doesn't need to pull from multiple builds and merge them. +func AllBuildFlagDeclarationsFactory() android.Singleton { + return &allBuildFlagDeclarationsSingleton{} +} + +type allBuildFlagDeclarationsSingleton struct { + intermediateBinaryProtoPath android.OutputPath + intermediateTextProtoPath android.OutputPath +} + +func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) { + // Find all of the build_flag_declarations modules + var intermediateFiles android.Paths + ctx.VisitAllModules(func(module android.Module) { + decl, ok := android.SingletonModuleProvider(ctx, module, BuildFlagDeclarationsProviderKey) + if !ok { + return + } + intermediateFiles = append(intermediateFiles, decl.IntermediateCacheOutputPath) + }) + + // Generate build action for build_flag (binary proto output) + this.intermediateBinaryProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.pb") + ctx.Build(pctx, android.BuildParams{ + Rule: allDeclarationsRule, + Inputs: intermediateFiles, + Output: this.intermediateBinaryProtoPath, + Description: "all_build_flag_declarations", + Args: map[string]string{ + "intermediates": android.JoinPathsWithPrefix(intermediateFiles, "--intermediate "), + }, + }) + ctx.Phony("all_build_flag_declarations", this.intermediateBinaryProtoPath) + + // Generate build action for build_flag (text proto output) + this.intermediateTextProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.textproto") + ctx.Build(pctx, android.BuildParams{ + Rule: allDeclarationsRuleTextProto, + Input: this.intermediateBinaryProtoPath, + Output: this.intermediateTextProtoPath, + Description: "all_build_flag_declarations_textproto", + }) + ctx.Phony("all_build_flag_declarations_textproto", this.intermediateTextProtoPath) +} + +func (this *allBuildFlagDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) { + ctx.DistForGoal("droid", this.intermediateBinaryProtoPath) + for _, goal := range []string{"docs", "droid", "sdk"} { + ctx.DistForGoalWithFilename(goal, this.intermediateBinaryProtoPath, "build_flags/all_flags.pb") + ctx.DistForGoalWithFilename(goal, this.intermediateTextProtoPath, "build_flags/all_flags.textproto") + } +} diff --git a/aconfig/build_flags/declarations.go b/aconfig/build_flags/declarations.go new file mode 100644 index 000000000..f6a6ee1a8 --- /dev/null +++ b/aconfig/build_flags/declarations.go @@ -0,0 +1,118 @@ +// 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 build_flags + +import ( + "fmt" + "strings" + + "android/soong/android" + + "github.com/google/blueprint" +) + +type BuildFlagDeclarationsProviderData struct { + IntermediateCacheOutputPath android.WritablePath + IntermediateDumpOutputPath android.WritablePath +} + +var BuildFlagDeclarationsProviderKey = blueprint.NewProvider[BuildFlagDeclarationsProviderData]() + +type DeclarationsModule struct { + android.ModuleBase + android.DefaultableModuleBase + + // Properties for "aconfig_declarations" + properties struct { + // aconfig files, relative to this Android.bp file + Srcs []string `android:"path"` + } + + intermediatePath android.WritablePath +} + +func DeclarationsFactory() android.Module { + module := &DeclarationsModule{} + + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + + return module +} + +func (module *DeclarationsModule) OutputFiles(tag string) (android.Paths, error) { + switch tag { + 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 build_flags_declarations 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 optionalVariable(prefix string, value string) string { + var sb strings.Builder + if value != "" { + sb.WriteString(prefix) + sb.WriteString(value) + } + return sb.String() +} + +func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Intermediate format + declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs) + intermediateCacheFilePath := android.PathForModuleOut(ctx, "build_flag_intermediate.pb") + inputFiles := make([]android.Path, len(declarationFiles)) + copy(inputFiles, declarationFiles) + + // TODO(lamont): generate the rc_proto.FlagArtifacts message for the sources. + args := map[string]string{ + "release_version": ctx.Config().ReleaseVersion(), + "declarations": android.JoinPathsWithPrefix(declarationFiles, "--decl "), + } + ctx.Build(pctx, android.BuildParams{ + Rule: buildFlagRule, + Output: intermediateCacheFilePath, + Inputs: inputFiles, + Description: "build_flag_declarations", + Args: args, + }) + + intermediateDumpFilePath := android.PathForModuleOut(ctx, "build_flag_intermediate.textproto") + ctx.Build(pctx, android.BuildParams{ + Rule: buildFlagTextRule, + Output: intermediateDumpFilePath, + Input: intermediateCacheFilePath, + Description: "build_flag_declarations_text", + }) + + android.SetProvider(ctx, BuildFlagDeclarationsProviderKey, BuildFlagDeclarationsProviderData{ + IntermediateCacheOutputPath: intermediateCacheFilePath, + IntermediateDumpOutputPath: intermediateDumpFilePath, + }) +} diff --git a/aconfig/build_flags/init.go b/aconfig/build_flags/init.go new file mode 100644 index 000000000..5907f4eb3 --- /dev/null +++ b/aconfig/build_flags/init.go @@ -0,0 +1,78 @@ +// 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 build_flags + +import ( + "android/soong/android" + + "github.com/google/blueprint" +) + +var ( + pctx = android.NewPackageContext("android/soong/aconfig/build_flags") + + // For build_flag_declarations: Generate cache file + buildFlagRule = pctx.AndroidStaticRule("build-flag-declarations", + blueprint.RuleParams{ + Command: `${buildFlagDeclarations} ` + + ` ${declarations}` + + ` --format pb` + + ` --output ${out}.tmp` + + ` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`, + CommandDeps: []string{ + "${buildFlagDeclarations}", + }, + Restat: true, + }, "release_version", "declarations") + + buildFlagTextRule = pctx.AndroidStaticRule("build-flag-declarations-text", + blueprint.RuleParams{ + Command: `${buildFlagDeclarations} --format=textproto` + + ` --intermediate ${in}` + + ` --format textproto` + + ` --output ${out}.tmp` + + ` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`, + CommandDeps: []string{ + "${buildFlagDeclarations}", + }, + Restat: true, + }) + + allDeclarationsRule = pctx.AndroidStaticRule("all-build-flag-declarations-dump", + blueprint.RuleParams{ + Command: `${buildFlagDeclarations} ${intermediates} --format pb --output ${out}`, + CommandDeps: []string{ + "${buildFlagDeclarations}", + }, + }, "intermediates") + + allDeclarationsRuleTextProto = pctx.AndroidStaticRule("All_build_flag_declarations_dump_textproto", + blueprint.RuleParams{ + Command: `${buildFlagDeclarations} --intermediate ${in} --format textproto --output ${out}`, + CommandDeps: []string{ + "${buildFlagDeclarations}", + }, + }) +) + +func init() { + RegisterBuildComponents(android.InitRegistrationContext) + pctx.HostBinToolVariable("buildFlagDeclarations", "build-flag-declarations") +} + +func RegisterBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("build_flag_declarations", DeclarationsFactory) + ctx.RegisterParallelSingletonType("all_build_flag_declarations", AllBuildFlagDeclarationsFactory) +}