| // 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", |
| }, |
| } |
| } |