blob: 710d9cd67d9b482f7611573edc60e36833aca29a [file] [log] [blame]
Colin Cross38406592018-05-17 11:17:01 -07001// Copyright (C) 2018 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 bpf
16
17import (
18 "fmt"
19 "io"
Ken Chen5372a242022-07-07 17:48:06 +080020 "path/filepath"
Connor O'Brien3e739cf2022-08-17 15:45:52 -070021 "runtime"
Colin Cross38406592018-05-17 11:17:01 -070022 "strings"
23
24 "android/soong/android"
Zi Wangb3cb38c2022-09-23 16:36:11 -070025 "android/soong/bazel"
Zi Wangaa981ed2022-10-04 16:59:31 -070026 "android/soong/bazel/cquery"
Connor O'Brien6a288bc2022-11-10 13:58:48 -080027 "android/soong/cc"
Colin Cross38406592018-05-17 11:17:01 -070028
29 "github.com/google/blueprint"
Connor O'Brien25739652021-12-02 20:09:45 -080030 "github.com/google/blueprint/proptools"
Colin Cross38406592018-05-17 11:17:01 -070031)
32
33func init() {
Paul Duffin12c7eb82021-02-24 18:51:54 +000034 registerBpfBuildComponents(android.InitRegistrationContext)
Colin Cross38406592018-05-17 11:17:01 -070035 pctx.Import("android/soong/cc/config")
Connor O'Brien6a288bc2022-11-10 13:58:48 -080036 pctx.StaticVariable("relPwd", cc.PwdPrefix())
Colin Cross38406592018-05-17 11:17:01 -070037}
38
39var (
40 pctx = android.NewPackageContext("android/soong/bpf")
41
Ramy Medhat8ea054a2020-01-27 14:19:44 -050042 ccRule = pctx.AndroidRemoteStaticRule("ccRule", android.RemoteRuleSupports{Goma: true},
Colin Cross38406592018-05-17 11:17:01 -070043 blueprint.RuleParams{
44 Depfile: "${out}.d",
45 Deps: blueprint.DepsGCC,
Connor O'Brien3e739cf2022-08-17 15:45:52 -070046 Command: "$relPwd $ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
Colin Cross38406592018-05-17 11:17:01 -070047 CommandDeps: []string{"$ccCmd"},
48 },
49 "ccCmd", "cFlags")
Connor O'Brien25739652021-12-02 20:09:45 -080050
51 stripRule = pctx.AndroidStaticRule("stripRule",
52 blueprint.RuleParams{
53 Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
54 `--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
55 CommandDeps: []string{"$stripCmd"},
56 },
57 "stripCmd")
Colin Cross38406592018-05-17 11:17:01 -070058)
59
Paul Duffin12c7eb82021-02-24 18:51:54 +000060func registerBpfBuildComponents(ctx android.RegistrationContext) {
61 ctx.RegisterModuleType("bpf", BpfFactory)
62}
63
64var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents)
65
markchien2f59ec92020-09-02 16:23:38 +080066// BpfModule interface is used by the apex package to gather information from a bpf module.
67type BpfModule interface {
68 android.Module
69
70 OutputFiles(tag string) (android.Paths, error)
Ken Chenfad7f9d2021-11-10 22:02:57 +080071
72 // Returns the sub install directory if the bpf module is included by apex.
73 SubDir() string
markchien2f59ec92020-09-02 16:23:38 +080074}
75
Colin Cross38406592018-05-17 11:17:01 -070076type BpfProperties struct {
Zi Wang4877c722022-08-11 18:05:13 +000077 // source paths to the files.
78 Srcs []string `android:"path"`
79
80 // additional cflags that should be used to build the bpf variant of
81 // the C/C++ module.
82 Cflags []string
83
84 // directories (relative to the root of the source tree) that will
85 // be added to the include paths using -I.
Colin Cross38406592018-05-17 11:17:01 -070086 Include_dirs []string
Zi Wang4877c722022-08-11 18:05:13 +000087
88 // optional subdirectory under which this module is installed into.
89 Sub_dir string
90
91 // if set to true, generate BTF debug info for maps & programs.
92 Btf *bool
93
Steven Moreland606c5e92019-12-12 14:23:42 -080094 Vendor *bool
95
96 VendorInternal bool `blueprint:"mutated"`
Colin Cross38406592018-05-17 11:17:01 -070097}
98
99type bpf struct {
100 android.ModuleBase
Zi Wangb3cb38c2022-09-23 16:36:11 -0700101 android.BazelModuleBase
Colin Cross38406592018-05-17 11:17:01 -0700102
103 properties BpfProperties
104
105 objs android.Paths
106}
107
Steven Moreland606c5e92019-12-12 14:23:42 -0800108var _ android.ImageInterface = (*bpf)(nil)
109
110func (bpf *bpf) ImageMutatorBegin(ctx android.BaseModuleContext) {}
111
112func (bpf *bpf) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
113 return !proptools.Bool(bpf.properties.Vendor)
114}
115
116func (bpf *bpf) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
117 return false
118}
119
120func (bpf *bpf) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
121 return false
122}
123
124func (bpf *bpf) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
125 return false
126}
127
128func (bpf *bpf) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
129 return false
130}
131
132func (bpf *bpf) ExtraImageVariations(ctx android.BaseModuleContext) []string {
133 if proptools.Bool(bpf.properties.Vendor) {
134 return []string{"vendor"}
135 }
136 return nil
137}
138
139func (bpf *bpf) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
140 bpf.properties.VendorInternal = variation == "vendor"
141}
142
Colin Cross38406592018-05-17 11:17:01 -0700143func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
144 cflags := []string{
145 "-nostdlibinc",
Kousik Kumarfb0e2512020-03-25 15:01:27 -0700146
147 // Make paths in deps files relative
148 "-no-canonical-prefixes",
149
Colin Cross38406592018-05-17 11:17:01 -0700150 "-O2",
151 "-isystem bionic/libc/include",
152 "-isystem bionic/libc/kernel/uapi",
153 // The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
154 "-isystem bionic/libc/kernel/uapi/asm-arm64",
155 "-isystem bionic/libc/kernel/android/uapi",
Motomu Utsumidc5b8d62023-08-22 12:03:16 +0900156 // TODO(b/296014682): Remove after the bpf_headers is moved to Connectivity
Ken Chenfd264442021-12-20 18:22:55 +0800157 "-I frameworks/libs/net/common/native/bpf_headers/include/bpf",
Motomu Utsumidc5b8d62023-08-22 12:03:16 +0900158 "-I packages/modules/Connectivity/staticlibs/native/bpf_headers/include/bpf",
Maciej Żenczykowski79f6f752020-02-18 15:38:36 -0800159 // TODO(b/149785767): only give access to specific file with AID_* constants
160 "-I system/core/libcutils/include",
Colin Cross38406592018-05-17 11:17:01 -0700161 "-I " + ctx.ModuleDir(),
162 }
163
164 for _, dir := range android.PathsForSource(ctx, bpf.properties.Include_dirs) {
165 cflags = append(cflags, "-I "+dir.String())
166 }
167
168 cflags = append(cflags, bpf.properties.Cflags...)
169
Connor O'Brien25739652021-12-02 20:09:45 -0800170 if proptools.Bool(bpf.properties.Btf) {
171 cflags = append(cflags, "-g")
Connor O'Brien3e739cf2022-08-17 15:45:52 -0700172 if runtime.GOOS != "darwin" {
173 cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
174 }
Connor O'Brien25739652021-12-02 20:09:45 -0800175 }
176
Colin Cross8a497952019-03-05 22:25:09 -0800177 srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
Colin Cross38406592018-05-17 11:17:01 -0700178
179 for _, src := range srcs {
Ken Chen5372a242022-07-07 17:48:06 +0800180 if strings.ContainsRune(filepath.Base(src.String()), '_') {
181 ctx.ModuleErrorf("invalid character '_' in source name")
182 }
Connor O'Brien25739652021-12-02 20:09:45 -0800183 obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
Colin Cross38406592018-05-17 11:17:01 -0700184
185 ctx.Build(pctx, android.BuildParams{
Colin Cross815daf92019-05-14 16:05:20 -0700186 Rule: ccRule,
Colin Cross38406592018-05-17 11:17:01 -0700187 Input: src,
188 Output: obj,
189 Args: map[string]string{
190 "cFlags": strings.Join(cflags, " "),
191 "ccCmd": "${config.ClangBin}/clang",
192 },
193 })
194
Connor O'Brien25739652021-12-02 20:09:45 -0800195 if proptools.Bool(bpf.properties.Btf) {
196 objStripped := android.ObjPathWithExt(ctx, "", src, "o")
197 ctx.Build(pctx, android.BuildParams{
Steven Moreland606c5e92019-12-12 14:23:42 -0800198 Rule: stripRule,
199 Input: obj,
Connor O'Brien25739652021-12-02 20:09:45 -0800200 Output: objStripped,
201 Args: map[string]string{
202 "stripCmd": "${config.ClangBin}/llvm-strip",
203 },
204 })
205 bpf.objs = append(bpf.objs, objStripped.WithoutRel())
206 } else {
207 bpf.objs = append(bpf.objs, obj.WithoutRel())
208 }
209
Colin Cross38406592018-05-17 11:17:01 -0700210 }
Aditya Choudhary95e2a3c2023-11-29 16:42:42 +0000211 ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
Colin Cross38406592018-05-17 11:17:01 -0700212}
213
Colin Cross38406592018-05-17 11:17:01 -0700214func (bpf *bpf) AndroidMk() android.AndroidMkData {
215 return android.AndroidMkData{
216 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
217 var names []string
218 fmt.Fprintln(w)
219 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
220 fmt.Fprintln(w)
Steven Moreland606c5e92019-12-12 14:23:42 -0800221 var localModulePath string
222 if bpf.properties.VendorInternal {
223 localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/bpf"
224 } else {
225 localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
226 }
Ken Chenfad7f9d2021-11-10 22:02:57 +0800227 if len(bpf.properties.Sub_dir) > 0 {
228 localModulePath += "/" + bpf.properties.Sub_dir
229 }
Colin Cross38406592018-05-17 11:17:01 -0700230 for _, obj := range bpf.objs {
231 objName := name + "_" + obj.Base()
232 names = append(names, objName)
Sasha Smundak5c4729d2022-12-01 10:49:23 -0800233 fmt.Fprintln(w, "include $(CLEAR_VARS)", " # bpf.bpf.obj")
Colin Cross38406592018-05-17 11:17:01 -0700234 fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
Bob Badourb4999222021-01-07 03:34:31 +0000235 data.Entries.WriteLicenseVariables(w)
Colin Cross38406592018-05-17 11:17:01 -0700236 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
237 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
238 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
Ken Chenfad7f9d2021-11-10 22:02:57 +0800239 fmt.Fprintln(w, localModulePath)
Colin Cross38406592018-05-17 11:17:01 -0700240 fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
241 fmt.Fprintln(w)
242 }
Sasha Smundak5c4729d2022-12-01 10:49:23 -0800243 fmt.Fprintln(w, "include $(CLEAR_VARS)", " # bpf.bpf")
Colin Cross38406592018-05-17 11:17:01 -0700244 fmt.Fprintln(w, "LOCAL_MODULE := ", name)
Bob Badourb4999222021-01-07 03:34:31 +0000245 data.Entries.WriteLicenseVariables(w)
Sasha Smundakdcb61292022-12-08 10:41:33 -0800246 android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", names)
Colin Cross38406592018-05-17 11:17:01 -0700247 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
248 },
249 }
250}
251
Zi Wangaa981ed2022-10-04 16:59:31 -0700252var _ android.MixedBuildBuildable = (*bpf)(nil)
253
254func (bpf *bpf) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
255 return true
256}
257
258func (bpf *bpf) QueueBazelCall(ctx android.BaseModuleContext) {
259 bazelCtx := ctx.Config().BazelContext
260 bazelCtx.QueueBazelRequest(
261 bpf.GetBazelLabel(ctx, bpf),
262 cquery.GetOutputFiles,
263 android.GetConfigKey(ctx))
264}
265
266func (bpf *bpf) ProcessBazelQueryResponse(ctx android.ModuleContext) {
267 bazelCtx := ctx.Config().BazelContext
268 objPaths, err := bazelCtx.GetOutputFiles(bpf.GetBazelLabel(ctx, bpf), android.GetConfigKey(ctx))
269 if err != nil {
270 ctx.ModuleErrorf(err.Error())
271 return
272 }
273
274 bazelOuts := android.Paths{}
275 for _, p := range objPaths {
276 bazelOuts = append(bazelOuts, android.PathForBazelOut(ctx, p))
277 }
278 bpf.objs = bazelOuts
279}
280
Colin Cross41955e82019-05-29 14:40:35 -0700281// Implements OutputFileFileProducer interface so that the obj output can be used in the data property
Jaewoong Jung5f3fb4b2018-12-13 15:01:46 -0800282// of other modules.
Colin Cross41955e82019-05-29 14:40:35 -0700283func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
284 switch tag {
285 case "":
286 return bpf.objs, nil
287 default:
288 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
289 }
Jaewoong Jung5f3fb4b2018-12-13 15:01:46 -0800290}
291
Ken Chenfad7f9d2021-11-10 22:02:57 +0800292func (bpf *bpf) SubDir() string {
293 return bpf.properties.Sub_dir
294}
295
Colin Cross41955e82019-05-29 14:40:35 -0700296var _ android.OutputFileProducer = (*bpf)(nil)
Jaewoong Jung5f3fb4b2018-12-13 15:01:46 -0800297
markchien2f59ec92020-09-02 16:23:38 +0800298func BpfFactory() android.Module {
Colin Cross38406592018-05-17 11:17:01 -0700299 module := &bpf{}
300
301 module.AddProperties(&module.properties)
302
303 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
Zi Wangb3cb38c2022-09-23 16:36:11 -0700304 android.InitBazelModule(module)
Colin Cross38406592018-05-17 11:17:01 -0700305 return module
306}
Zi Wangb3cb38c2022-09-23 16:36:11 -0700307
308type bazelBpfAttributes struct {
309 Srcs bazel.LabelListAttribute
310 Copts bazel.StringListAttribute
311 Absolute_includes bazel.StringListAttribute
312 Btf *bool
313 // TODO(b/249528391): Add support for sub_dir
314}
315
316// bpf bp2build converter
317func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
318 if ctx.ModuleType() != "bpf" {
319 return
320 }
321
322 srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, b.properties.Srcs))
323 copts := bazel.MakeStringListAttribute(b.properties.Cflags)
324 absolute_includes := bazel.MakeStringListAttribute(b.properties.Include_dirs)
325 btf := b.properties.Btf
326
327 attrs := bazelBpfAttributes{
328 Srcs: srcs,
329 Copts: copts,
330 Absolute_includes: absolute_includes,
331 Btf: btf,
332 }
333 props := bazel.BazelTargetModuleProperties{
334 Rule_class: "bpf",
335 Bzl_load_location: "//build/bazel/rules/bpf:bpf.bzl",
336 }
337
338 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: b.Name()}, &attrs)
339}