blob: 1fdb3d63646b209ce32da183161db4b8313cf258 [file] [log] [blame]
Neill Kapron41efab72024-07-31 22:17:36 +00001// Copyright (C) 2024 The Android Open Source Project
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
15package libbpf_prog
16
17import (
18 "fmt"
19 "io"
20 "runtime"
21 "strings"
22
23 "android/soong/android"
24 "android/soong/cc"
25 "android/soong/genrule"
26
27 "github.com/google/blueprint"
28)
29
30type libbpfProgDepType struct {
31 blueprint.BaseDependencyTag
32}
33
34func init() {
35 registerLibbpfProgBuildComponents(android.InitRegistrationContext)
36 pctx.Import("android/soong/cc/config")
37 pctx.StaticVariable("relPwd", cc.PwdPrefix())
38}
39
40var (
41 pctx = android.NewPackageContext("android/soong/bpf/libbpf_prog")
42
43 libbpfProgCcRule = pctx.AndroidStaticRule("libbpfProgCcRule",
44 blueprint.RuleParams{
45 Depfile: "${out}.d",
46 Deps: blueprint.DepsGCC,
47 Command: "$relPwd $ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
48 CommandDeps: []string{"$ccCmd"},
49 },
50 "ccCmd", "cFlags")
51
52 libbpfProgStripRule = pctx.AndroidStaticRule("libbpfProgStripRule",
53 blueprint.RuleParams{
54 Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
55 `--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
56 CommandDeps: []string{"$stripCmd"},
57 },
58 "stripCmd")
59
60 libbpfProgDepTag = libbpfProgDepType{}
61)
62
63func registerLibbpfProgBuildComponents(ctx android.RegistrationContext) {
64 ctx.RegisterModuleType("libbpf_prog", LibbpfProgFactory)
65}
66
67var PrepareForTestWithLibbpfProg = android.GroupFixturePreparers(
68 android.FixtureRegisterWithContext(registerLibbpfProgBuildComponents),
69 android.FixtureAddFile("libbpf_headers/Foo.h", nil),
70 android.FixtureAddFile("libbpf_headers/Android.bp", []byte(`
71 genrule {
72 name: "libbpf_headers",
73 out: ["foo.h",],
74 }
75 `)),
76 genrule.PrepareForTestWithGenRuleBuildComponents,
77)
78
79type LibbpfProgProperties struct {
80 // source paths to the files.
81 Srcs []string `android:"path"`
82
83 // additional cflags that should be used to build the libbpf variant of
84 // the C/C++ module.
85 Cflags []string `android:"arch_variant"`
86
87 // list of directories relative to the Blueprint file that will
88 // be added to the include path using -I
89 Local_include_dirs []string `android:"arch_variant"`
90
91 // optional subdirectory under which this module is installed into.
92 Relative_install_path string
93}
94
95type libbpfProg struct {
96 android.ModuleBase
97 properties LibbpfProgProperties
98 objs android.Paths
99}
100
101var _ android.ImageInterface = (*libbpfProg)(nil)
102
103func (libbpf *libbpfProg) ImageMutatorBegin(ctx android.BaseModuleContext) {}
104
105func (libbpf *libbpfProg) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
106 return false
107}
108
109func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
110 return false
111}
112
113func (libbpf *libbpfProg) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
114 return true
115}
116
117func (libbpf *libbpfProg) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
118 return false
119}
120
121func (libbpf *libbpfProg) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
122 return false
123}
124
125func (libbpf *libbpfProg) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
126 return false
127}
128
129func (libbpf *libbpfProg) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
130 return false
131}
132
133func (libbpf *libbpfProg) ExtraImageVariations(ctx android.BaseModuleContext) []string {
134 return nil
135}
136
137func (libbpf *libbpfProg) SetImageVariation(ctx android.BaseModuleContext, variation string) {
138}
139
140func (libbpf *libbpfProg) DepsMutator(ctx android.BottomUpMutatorContext) {
141 ctx.AddDependency(ctx.Module(), libbpfProgDepTag, "libbpf_headers")
142}
143
144func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
145 var cFlagsDeps android.Paths
146 cflags := []string{
147 "-nostdlibinc",
148
149 // Make paths in deps files relative
150 "-no-canonical-prefixes",
151
152 "-O2",
153 "-Wall",
154 "-Werror",
155 "-Wextra",
156
157 "-isystem bionic/libc/include",
158 "-isystem bionic/libc/kernel/uapi",
159 // The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
160 "-isystem bionic/libc/kernel/uapi/asm-arm64",
161 "-isystem bionic/libc/kernel/android/uapi",
162 "-I " + ctx.ModuleDir(),
163 "-g", //Libbpf builds require BTF data
164 }
165
166 if runtime.GOOS != "darwin" {
167 cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
168 }
169
170 ctx.VisitDirectDeps(func(dep android.Module) {
171 depTag := ctx.OtherModuleDependencyTag(dep)
172 if depTag == libbpfProgDepTag {
173 if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
174 cFlagsDeps = append(cFlagsDeps, genRule.GeneratedDeps()...)
175 dirs := genRule.GeneratedHeaderDirs()
176 for _, dir := range dirs {
177 cflags = append(cflags, "-I "+dir.String())
178 }
179 } else {
180 depName := ctx.OtherModuleName(dep)
181 ctx.ModuleErrorf("module %q is not a genrule", depName)
182 }
183 }
184 })
185
186 for _, dir := range android.PathsForModuleSrc(ctx, libbpf.properties.Local_include_dirs) {
187 cflags = append(cflags, "-I "+dir.String())
188 }
189
190 cflags = append(cflags, libbpf.properties.Cflags...)
191
192 srcs := android.PathsForModuleSrc(ctx, libbpf.properties.Srcs)
193
194 for _, src := range srcs {
195 if strings.ContainsRune(src.Base(), '_') {
196 ctx.ModuleErrorf("invalid character '_' in source name")
197 }
198 obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
199
200 ctx.Build(pctx, android.BuildParams{
201 Rule: libbpfProgCcRule,
202 Input: src,
203 Implicits: cFlagsDeps,
204 Output: obj,
205 Args: map[string]string{
206 "cFlags": strings.Join(cflags, " "),
207 "ccCmd": "${config.ClangBin}/clang",
208 },
209 })
210
211 objStripped := android.ObjPathWithExt(ctx, "", src, "o")
212 ctx.Build(pctx, android.BuildParams{
213 Rule: libbpfProgStripRule,
214 Input: obj,
215 Output: objStripped,
216 Args: map[string]string{
217 "stripCmd": "${config.ClangBin}/llvm-strip",
218 },
219 })
220 libbpf.objs = append(libbpf.objs, objStripped.WithoutRel())
221 }
222
223 installDir := android.PathForModuleInstall(ctx, "etc", "bpf/libbpf")
224 if len(libbpf.properties.Relative_install_path) > 0 {
225 installDir = installDir.Join(ctx, libbpf.properties.Relative_install_path)
226 }
227 for _, obj := range libbpf.objs {
228 ctx.PackageFile(installDir, obj.Base(), obj)
229 }
230
231 android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
232
233 ctx.SetOutputFiles(libbpf.objs, "")
234}
235
236func (libbpf *libbpfProg) AndroidMk() android.AndroidMkData {
237 return android.AndroidMkData{
238 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
239 var names []string
240 fmt.Fprintln(w)
241 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
242 fmt.Fprintln(w)
243 var localModulePath string
244 localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf/libbpf"
245 if len(libbpf.properties.Relative_install_path) > 0 {
246 localModulePath += "/" + libbpf.properties.Relative_install_path
247 }
248 for _, obj := range libbpf.objs {
249 objName := name + "_" + obj.Base()
250 names = append(names, objName)
251 fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf.obj")
252 fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
253 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
254 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
255 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
256 fmt.Fprintln(w, localModulePath)
257 // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
258 for _, extra := range data.Extra {
259 extra(w, nil)
260 }
261 fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
262 fmt.Fprintln(w)
263 }
264 fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf")
265 fmt.Fprintln(w, "LOCAL_MODULE := ", name)
266 android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", names)
267 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
268 },
269 }
270}
271
272func LibbpfProgFactory() android.Module {
273 module := &libbpfProg{}
274
275 module.AddProperties(&module.properties)
276 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
277 return module
278}