1// Copyright 2024 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// Package golang wraps the blueprint blueprint_go_binary and bootstrap_go_binary module types in versions 16// that implement android.Module that are used when building in Soong. This simplifies the code in Soong 17// so it can always assume modules are an android.Module. 18// The original blueprint blueprint_go_binary and bootstrap_go_binary module types are still used during 19// bootstrapping, so the Android.bp entries for these module types must be compatible with both the 20// original blueprint module types and these wrapped module types. 21package golang 22 23import ( 24 "android/soong/android" 25 26 "github.com/google/blueprint" 27 "github.com/google/blueprint/bootstrap" 28) 29 30func init() { 31 // Wrap the blueprint Go module types with Soong ones that interoperate with the rest of the Soong modules. 32 bootstrap.GoModuleTypesAreWrapped() 33 RegisterGoModuleTypes(android.InitRegistrationContext) 34} 35 36func RegisterGoModuleTypes(ctx android.RegistrationContext) { 37 ctx.RegisterModuleType("bootstrap_go_package", goPackageModuleFactory) 38 ctx.RegisterModuleType("blueprint_go_binary", goBinaryModuleFactory) 39} 40 41// A GoPackage is a module for building Go packages. 42type GoPackage struct { 43 android.ModuleBase 44 bootstrap.GoPackage 45} 46 47func goPackageModuleFactory() android.Module { 48 module := &GoPackage{} 49 module.AddProperties(module.Properties()...) 50 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst) 51 return module 52} 53 54func (g *GoPackage) GenerateBuildActions(ctx blueprint.ModuleContext) { 55 // The embedded ModuleBase and bootstrap.GoPackage each implement GenerateBuildActions, 56 // the delegation has to be implemented manually to disambiguate. Call ModuleBase's 57 // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call 58 // bootstrap.GoPackage.GenerateBuildActions. 59 g.ModuleBase.GenerateBuildActions(ctx) 60} 61 62func (g *GoPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) { 63 g.GoPackage.GenerateBuildActions(ctx.BlueprintModuleContext()) 64} 65 66// A GoBinary is a module for building executable binaries from Go sources. 67type GoBinary struct { 68 android.ModuleBase 69 bootstrap.GoBinary 70 71 outputFile android.Path 72} 73 74func goBinaryModuleFactory() android.Module { 75 module := &GoBinary{} 76 module.AddProperties(module.Properties()...) 77 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst) 78 return module 79} 80 81func (g *GoBinary) GenerateBuildActions(ctx blueprint.ModuleContext) { 82 // The embedded ModuleBase and bootstrap.GoBinary each implement GenerateBuildActions, 83 // the delegation has to be implemented manually to disambiguate. Call ModuleBase's 84 // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call 85 // bootstrap.GoBinary.GenerateBuildActions. 86 g.ModuleBase.GenerateBuildActions(ctx) 87} 88 89func (g *GoBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 90 // Install the file in Soong instead of blueprint so that Soong knows about the install rules. 91 g.GoBinary.SetSkipInstall() 92 93 // Run the build actions from the wrapped blueprint bootstrap module. 94 g.GoBinary.GenerateBuildActions(ctx.BlueprintModuleContext()) 95 96 // Translate the bootstrap module's string path into a Path 97 outputFile := android.PathForArbitraryOutput(ctx, android.Rel(ctx, ctx.Config().OutDir(), g.IntermediateFile())).WithoutRel() 98 g.outputFile = outputFile 99 100 // Don't create install rules for modules used by bootstrap, the install command line will differ from 101 // what was used during bootstrap, which will cause ninja to rebuild the module on the next run, 102 // triggering reanalysis. 103 if !usedByBootstrap(ctx.ModuleName()) { 104 installPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), outputFile) 105 106 // Modules in an unexported namespace have no install rule, only add modules in the exported namespaces 107 // to the blueprint_tools phony rules. 108 if !ctx.Config().KatiEnabled() || g.ExportedToMake() { 109 ctx.Phony("blueprint_tools", installPath) 110 } 111 } 112 113 ctx.SetOutputFiles(android.Paths{outputFile}, "") 114} 115 116func usedByBootstrap(name string) bool { 117 switch name { 118 case "loadplugins", "soong_build": 119 return true 120 default: 121 return false 122 } 123} 124 125func (g *GoBinary) HostToolPath() android.OptionalPath { 126 return android.OptionalPathForPath(g.outputFile) 127} 128 129func (g *GoBinary) AndroidMkEntries() []android.AndroidMkEntries { 130 return []android.AndroidMkEntries{ 131 { 132 Class: "EXECUTABLES", 133 OutputFile: android.OptionalPathForPath(g.outputFile), 134 Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk", 135 }, 136 } 137} 138