// Copyright 2024 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 golang wraps the blueprint blueprint_go_binary and bootstrap_go_binary module types in versions // that implement android.Module that are used when building in Soong. This simplifies the code in Soong // so it can always assume modules are an android.Module. // The original blueprint blueprint_go_binary and bootstrap_go_binary module types are still used during // bootstrapping, so the Android.bp entries for these module types must be compatible with both the // original blueprint module types and these wrapped module types. package golang import ( "android/soong/android" "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" ) func init() { // Wrap the blueprint Go module types with Soong ones that interoperate with the rest of the Soong modules. bootstrap.GoModuleTypesAreWrapped() RegisterGoModuleTypes(android.InitRegistrationContext) } func RegisterGoModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("bootstrap_go_package", goPackageModuleFactory) ctx.RegisterModuleType("blueprint_go_binary", goBinaryModuleFactory) } // A GoPackage is a module for building Go packages. type GoPackage struct { android.ModuleBase bootstrap.GoPackage } func goPackageModuleFactory() android.Module { module := &GoPackage{} module.AddProperties(module.Properties()...) android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst) return module } func (g *GoPackage) GenerateBuildActions(ctx blueprint.ModuleContext) { // The embedded ModuleBase and bootstrap.GoPackage each implement GenerateBuildActions, // the delegation has to be implemented manually to disambiguate. Call ModuleBase's // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call // bootstrap.GoPackage.GenerateBuildActions. g.ModuleBase.GenerateBuildActions(ctx) } func (g *GoPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) { g.GoPackage.GenerateBuildActions(ctx.BlueprintModuleContext()) } // A GoBinary is a module for building executable binaries from Go sources. type GoBinary struct { android.ModuleBase bootstrap.GoBinary outputFile android.Path } func goBinaryModuleFactory() android.Module { module := &GoBinary{} module.AddProperties(module.Properties()...) android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst) return module } func (g *GoBinary) GenerateBuildActions(ctx blueprint.ModuleContext) { // The embedded ModuleBase and bootstrap.GoBinary each implement GenerateBuildActions, // the delegation has to be implemented manually to disambiguate. Call ModuleBase's // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call // bootstrap.GoBinary.GenerateBuildActions. g.ModuleBase.GenerateBuildActions(ctx) } func (g *GoBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Install the file in Soong instead of blueprint so that Soong knows about the install rules. g.GoBinary.SetSkipInstall() // Run the build actions from the wrapped blueprint bootstrap module. g.GoBinary.GenerateBuildActions(ctx.BlueprintModuleContext()) // Translate the bootstrap module's string path into a Path outputFile := android.PathForArbitraryOutput(ctx, android.Rel(ctx, ctx.Config().OutDir(), g.IntermediateFile())).WithoutRel() g.outputFile = outputFile // Don't create install rules for modules used by bootstrap, the install command line will differ from // what was used during bootstrap, which will cause ninja to rebuild the module on the next run, // triggering reanalysis. if !usedByBootstrap(ctx.ModuleName()) { installPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), outputFile) // Modules in an unexported namespace have no install rule, only add modules in the exported namespaces // to the blueprint_tools phony rules. if !ctx.Config().KatiEnabled() || g.ExportedToMake() { ctx.Phony("blueprint_tools", installPath) } } ctx.SetOutputFiles(android.Paths{outputFile}, "") } func usedByBootstrap(name string) bool { switch name { case "loadplugins", "soong_build": return true default: return false } } func (g *GoBinary) HostToolPath() android.OptionalPath { return android.OptionalPathForPath(g.outputFile) } func (g *GoBinary) AndroidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{ { Class: "EXECUTABLES", OutputFile: android.OptionalPathForPath(g.outputFile), Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk", }, } }