blob: 618a0852b7b28b30d649cf0d3eb7a9ba84c0656c [file] [log] [blame]
Colin Cross1496fb12024-09-09 16:44:10 -07001// 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 "github.com/google/blueprint"
26 "github.com/google/blueprint/bootstrap"
27)
28
29func init() {
30 // Wrap the blueprint Go module types with Soong ones that interoperate with the rest of the Soong modules.
31 bootstrap.GoModuleTypesAreWrapped()
32 RegisterGoModuleTypes(android.InitRegistrationContext)
33}
34
35func RegisterGoModuleTypes(ctx android.RegistrationContext) {
36 ctx.RegisterModuleType("bootstrap_go_package", goPackageModuleFactory)
37 ctx.RegisterModuleType("blueprint_go_binary", goBinaryModuleFactory)
38}
39
40// A GoPackage is a module for building Go packages.
41type GoPackage struct {
42 android.ModuleBase
43 bootstrap.GoPackage
44}
45
46func goPackageModuleFactory() android.Module {
47 module := &GoPackage{}
48 module.AddProperties(module.Properties()...)
49 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
50 return module
51}
52
53func (g *GoPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
54 // The embedded ModuleBase and bootstrap.GoPackage each implement GenerateBuildActions,
55 // the delegation has to be implemented manually to disambiguate. Call ModuleBase's
56 // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call
57 // bootstrap.GoPackage.GenerateBuildActions.
58 g.ModuleBase.GenerateBuildActions(ctx)
59}
60
61func (g *GoPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
62 g.GoPackage.GenerateBuildActions(ctx.BlueprintModuleContext())
63}
64
65// A GoBinary is a module for building executable binaries from Go sources.
66type GoBinary struct {
67 android.ModuleBase
68 bootstrap.GoBinary
69
70 outputFile android.Path
71}
72
73func goBinaryModuleFactory() android.Module {
74 module := &GoBinary{}
75 module.AddProperties(module.Properties()...)
76 android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst)
77 return module
78}
79
80func (g *GoBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
81 // The embedded ModuleBase and bootstrap.GoBinary each implement GenerateBuildActions,
82 // the delegation has to be implemented manually to disambiguate. Call ModuleBase's
83 // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call
84 // bootstrap.GoBinary.GenerateBuildActions.
85 g.ModuleBase.GenerateBuildActions(ctx)
86}
87
88func (g *GoBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
89 // Install the file in Soong instead of blueprint so that Soong knows about the install rules.
90 g.GoBinary.SetSkipInstall()
91
92 // Run the build actions from the wrapped blueprint bootstrap module.
93 g.GoBinary.GenerateBuildActions(ctx.BlueprintModuleContext())
94
95 // Translate the bootstrap module's string path into a Path
96 outputFile := android.PathForArbitraryOutput(ctx, android.Rel(ctx, ctx.Config().OutDir(), g.IntermediateFile())).WithoutRel()
97 g.outputFile = outputFile
98
Colin Cross893528a2024-09-12 23:04:43 -070099 // Don't create install rules for modules used by bootstrap, the install command line will differ from
100 // what was used during bootstrap, which will cause ninja to rebuild the module on the next run,
101 // triggering reanalysis.
102 if !usedByBootstrap(ctx.ModuleName()) {
103 installPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), outputFile)
Colin Cross1496fb12024-09-09 16:44:10 -0700104
Colin Cross1496fb12024-09-09 16:44:10 -0700105 // Modules in an unexported namespace have no install rule, only add modules in the exported namespaces
106 // to the blueprint_tools phony rules.
Colin Cross893528a2024-09-12 23:04:43 -0700107 if !ctx.Config().KatiEnabled() || g.ExportedToMake() {
108 ctx.Phony("blueprint_tools", installPath)
109 }
Colin Cross1496fb12024-09-09 16:44:10 -0700110 }
111
112 ctx.SetOutputFiles(android.Paths{outputFile}, "")
113}
114
Colin Cross893528a2024-09-12 23:04:43 -0700115func usedByBootstrap(name string) bool {
116 switch name {
117 case "loadplugins", "soong_build":
118 return true
119 default:
120 return false
121 }
122}
123
Colin Cross1496fb12024-09-09 16:44:10 -0700124func (g *GoBinary) HostToolPath() android.OptionalPath {
125 return android.OptionalPathForPath(g.outputFile)
126}
127
128func (g *GoBinary) AndroidMkEntries() []android.AndroidMkEntries {
129 return []android.AndroidMkEntries{
130 {
131 Class: "EXECUTABLES",
132 OutputFile: android.OptionalPathForPath(g.outputFile),
133 Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
134 },
135 }
136}