blob: f9f64f57ce173238b624eb662fd388829a80e4ae [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) {
Neill Kapron4f1f0492024-09-16 19:33:46 +000064 ctx.RegisterModuleType("libbpf_defaults", defaultsFactory)
Neill Kapron41efab72024-07-31 22:17:36 +000065 ctx.RegisterModuleType("libbpf_prog", LibbpfProgFactory)
66}
67
68var PrepareForTestWithLibbpfProg = android.GroupFixturePreparers(
69 android.FixtureRegisterWithContext(registerLibbpfProgBuildComponents),
70 android.FixtureAddFile("libbpf_headers/Foo.h", nil),
71 android.FixtureAddFile("libbpf_headers/Android.bp", []byte(`
72 genrule {
73 name: "libbpf_headers",
74 out: ["foo.h",],
75 }
76 `)),
77 genrule.PrepareForTestWithGenRuleBuildComponents,
78)
79
80type LibbpfProgProperties struct {
81 // source paths to the files.
82 Srcs []string `android:"path"`
83
84 // additional cflags that should be used to build the libbpf variant of
85 // the C/C++ module.
86 Cflags []string `android:"arch_variant"`
87
88 // list of directories relative to the Blueprint file that will
89 // be added to the include path using -I
90 Local_include_dirs []string `android:"arch_variant"`
91
92 // optional subdirectory under which this module is installed into.
93 Relative_install_path string
94}
95
96type libbpfProg struct {
97 android.ModuleBase
Neill Kapron4f1f0492024-09-16 19:33:46 +000098 android.DefaultableModuleBase
Neill Kapron41efab72024-07-31 22:17:36 +000099 properties LibbpfProgProperties
Neill Kapron4f1f0492024-09-16 19:33:46 +0000100 objs android.Paths
Neill Kapron41efab72024-07-31 22:17:36 +0000101}
102
103var _ android.ImageInterface = (*libbpfProg)(nil)
104
105func (libbpf *libbpfProg) ImageMutatorBegin(ctx android.BaseModuleContext) {}
106
107func (libbpf *libbpfProg) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
108 return false
109}
110
111func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
112 return false
113}
114
115func (libbpf *libbpfProg) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
116 return true
117}
118
119func (libbpf *libbpfProg) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
120 return false
121}
122
123func (libbpf *libbpfProg) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
124 return false
125}
126
127func (libbpf *libbpfProg) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
128 return false
129}
130
131func (libbpf *libbpfProg) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
132 return false
133}
134
135func (libbpf *libbpfProg) ExtraImageVariations(ctx android.BaseModuleContext) []string {
136 return nil
137}
138
139func (libbpf *libbpfProg) SetImageVariation(ctx android.BaseModuleContext, variation string) {
140}
141
142func (libbpf *libbpfProg) DepsMutator(ctx android.BottomUpMutatorContext) {
143 ctx.AddDependency(ctx.Module(), libbpfProgDepTag, "libbpf_headers")
144}
145
146func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
147 var cFlagsDeps android.Paths
148 cflags := []string{
149 "-nostdlibinc",
150
151 // Make paths in deps files relative
152 "-no-canonical-prefixes",
153
154 "-O2",
155 "-Wall",
156 "-Werror",
157 "-Wextra",
158
159 "-isystem bionic/libc/include",
160 "-isystem bionic/libc/kernel/uapi",
161 // The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
162 "-isystem bionic/libc/kernel/uapi/asm-arm64",
163 "-isystem bionic/libc/kernel/android/uapi",
164 "-I " + ctx.ModuleDir(),
165 "-g", //Libbpf builds require BTF data
166 }
167
168 if runtime.GOOS != "darwin" {
169 cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
170 }
171
172 ctx.VisitDirectDeps(func(dep android.Module) {
173 depTag := ctx.OtherModuleDependencyTag(dep)
174 if depTag == libbpfProgDepTag {
175 if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
176 cFlagsDeps = append(cFlagsDeps, genRule.GeneratedDeps()...)
177 dirs := genRule.GeneratedHeaderDirs()
178 for _, dir := range dirs {
179 cflags = append(cflags, "-I "+dir.String())
180 }
181 } else {
182 depName := ctx.OtherModuleName(dep)
183 ctx.ModuleErrorf("module %q is not a genrule", depName)
184 }
185 }
186 })
187
188 for _, dir := range android.PathsForModuleSrc(ctx, libbpf.properties.Local_include_dirs) {
189 cflags = append(cflags, "-I "+dir.String())
190 }
191
192 cflags = append(cflags, libbpf.properties.Cflags...)
193
194 srcs := android.PathsForModuleSrc(ctx, libbpf.properties.Srcs)
195
196 for _, src := range srcs {
197 if strings.ContainsRune(src.Base(), '_') {
198 ctx.ModuleErrorf("invalid character '_' in source name")
199 }
200 obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
201
202 ctx.Build(pctx, android.BuildParams{
203 Rule: libbpfProgCcRule,
204 Input: src,
205 Implicits: cFlagsDeps,
206 Output: obj,
207 Args: map[string]string{
208 "cFlags": strings.Join(cflags, " "),
209 "ccCmd": "${config.ClangBin}/clang",
210 },
211 })
212
213 objStripped := android.ObjPathWithExt(ctx, "", src, "o")
214 ctx.Build(pctx, android.BuildParams{
215 Rule: libbpfProgStripRule,
216 Input: obj,
217 Output: objStripped,
218 Args: map[string]string{
219 "stripCmd": "${config.ClangBin}/llvm-strip",
220 },
221 })
222 libbpf.objs = append(libbpf.objs, objStripped.WithoutRel())
223 }
224
225 installDir := android.PathForModuleInstall(ctx, "etc", "bpf/libbpf")
226 if len(libbpf.properties.Relative_install_path) > 0 {
227 installDir = installDir.Join(ctx, libbpf.properties.Relative_install_path)
228 }
229 for _, obj := range libbpf.objs {
230 ctx.PackageFile(installDir, obj.Base(), obj)
231 }
232
233 android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
234
235 ctx.SetOutputFiles(libbpf.objs, "")
236}
237
238func (libbpf *libbpfProg) AndroidMk() android.AndroidMkData {
239 return android.AndroidMkData{
240 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
241 var names []string
242 fmt.Fprintln(w)
243 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
244 fmt.Fprintln(w)
245 var localModulePath string
246 localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf/libbpf"
247 if len(libbpf.properties.Relative_install_path) > 0 {
248 localModulePath += "/" + libbpf.properties.Relative_install_path
249 }
250 for _, obj := range libbpf.objs {
251 objName := name + "_" + obj.Base()
252 names = append(names, objName)
253 fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf.obj")
254 fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
255 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
256 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
257 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
258 fmt.Fprintln(w, localModulePath)
259 // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
260 for _, extra := range data.Extra {
261 extra(w, nil)
262 }
263 fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
264 fmt.Fprintln(w)
265 }
266 fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf")
267 fmt.Fprintln(w, "LOCAL_MODULE := ", name)
268 android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", names)
269 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
270 },
271 }
272}
273
Neill Kapron4f1f0492024-09-16 19:33:46 +0000274type Defaults struct {
275 android.ModuleBase
276 android.DefaultsModuleBase
277}
278
279func defaultsFactory() android.Module {
280 return DefaultsFactory()
281}
282
283func DefaultsFactory(props ...interface{}) android.Module {
284 module := &Defaults{}
285
286 module.AddProperties(props...)
287 module.AddProperties(&LibbpfProgProperties{})
288
289 android.InitDefaultsModule(module)
290
291 return module
292}
293
Neill Kapron41efab72024-07-31 22:17:36 +0000294func LibbpfProgFactory() android.Module {
295 module := &libbpfProg{}
296
297 module.AddProperties(&module.properties)
298 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
Neill Kapron4f1f0492024-09-16 19:33:46 +0000299 android.InitDefaultableModule(module)
300
Neill Kapron41efab72024-07-31 22:17:36 +0000301 return module
302}