blob: dbbce505ea4caba4d98c7f76d097d4c60c759d78 [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"
Colin Cross38406592018-05-17 11:17:01 -070021 "strings"
22
23 "android/soong/android"
Zi Wangb3cb38c2022-09-23 16:36:11 -070024 "android/soong/bazel"
Colin Cross38406592018-05-17 11:17:01 -070025
26 "github.com/google/blueprint"
Connor O'Brien25739652021-12-02 20:09:45 -080027 "github.com/google/blueprint/proptools"
Colin Cross38406592018-05-17 11:17:01 -070028)
29
30func init() {
Paul Duffin12c7eb82021-02-24 18:51:54 +000031 registerBpfBuildComponents(android.InitRegistrationContext)
Colin Cross38406592018-05-17 11:17:01 -070032 pctx.Import("android/soong/cc/config")
33}
34
35var (
36 pctx = android.NewPackageContext("android/soong/bpf")
37
Ramy Medhat8ea054a2020-01-27 14:19:44 -050038 ccRule = pctx.AndroidRemoteStaticRule("ccRule", android.RemoteRuleSupports{Goma: true},
Colin Cross38406592018-05-17 11:17:01 -070039 blueprint.RuleParams{
40 Depfile: "${out}.d",
41 Deps: blueprint.DepsGCC,
42 Command: "$ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
43 CommandDeps: []string{"$ccCmd"},
44 },
45 "ccCmd", "cFlags")
Connor O'Brien25739652021-12-02 20:09:45 -080046
47 stripRule = pctx.AndroidStaticRule("stripRule",
48 blueprint.RuleParams{
49 Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
50 `--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
51 CommandDeps: []string{"$stripCmd"},
52 },
53 "stripCmd")
Colin Cross38406592018-05-17 11:17:01 -070054)
55
Paul Duffin12c7eb82021-02-24 18:51:54 +000056func registerBpfBuildComponents(ctx android.RegistrationContext) {
57 ctx.RegisterModuleType("bpf", BpfFactory)
58}
59
60var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents)
61
markchien2f59ec92020-09-02 16:23:38 +080062// BpfModule interface is used by the apex package to gather information from a bpf module.
63type BpfModule interface {
64 android.Module
65
66 OutputFiles(tag string) (android.Paths, error)
Ken Chenfad7f9d2021-11-10 22:02:57 +080067
68 // Returns the sub install directory if the bpf module is included by apex.
69 SubDir() string
markchien2f59ec92020-09-02 16:23:38 +080070}
71
Colin Cross38406592018-05-17 11:17:01 -070072type BpfProperties struct {
Zi Wang4877c722022-08-11 18:05:13 +000073 // source paths to the files.
74 Srcs []string `android:"path"`
75
76 // additional cflags that should be used to build the bpf variant of
77 // the C/C++ module.
78 Cflags []string
79
80 // directories (relative to the root of the source tree) that will
81 // be added to the include paths using -I.
Colin Cross38406592018-05-17 11:17:01 -070082 Include_dirs []string
Zi Wang4877c722022-08-11 18:05:13 +000083
84 // optional subdirectory under which this module is installed into.
85 Sub_dir string
86
87 // if set to true, generate BTF debug info for maps & programs.
88 Btf *bool
89
Steven Moreland606c5e92019-12-12 14:23:42 -080090 Vendor *bool
91
92 VendorInternal bool `blueprint:"mutated"`
Colin Cross38406592018-05-17 11:17:01 -070093}
94
95type bpf struct {
96 android.ModuleBase
Zi Wangb3cb38c2022-09-23 16:36:11 -070097 android.BazelModuleBase
Colin Cross38406592018-05-17 11:17:01 -070098
99 properties BpfProperties
100
101 objs android.Paths
102}
103
Steven Moreland606c5e92019-12-12 14:23:42 -0800104var _ android.ImageInterface = (*bpf)(nil)
105
106func (bpf *bpf) ImageMutatorBegin(ctx android.BaseModuleContext) {}
107
108func (bpf *bpf) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
109 return !proptools.Bool(bpf.properties.Vendor)
110}
111
112func (bpf *bpf) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
113 return false
114}
115
116func (bpf *bpf) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
117 return false
118}
119
120func (bpf *bpf) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
121 return false
122}
123
124func (bpf *bpf) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
125 return false
126}
127
128func (bpf *bpf) ExtraImageVariations(ctx android.BaseModuleContext) []string {
129 if proptools.Bool(bpf.properties.Vendor) {
130 return []string{"vendor"}
131 }
132 return nil
133}
134
135func (bpf *bpf) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
136 bpf.properties.VendorInternal = variation == "vendor"
137}
138
Colin Cross38406592018-05-17 11:17:01 -0700139func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
140 cflags := []string{
141 "-nostdlibinc",
Kousik Kumarfb0e2512020-03-25 15:01:27 -0700142
143 // Make paths in deps files relative
144 "-no-canonical-prefixes",
145
Colin Cross38406592018-05-17 11:17:01 -0700146 "-O2",
147 "-isystem bionic/libc/include",
148 "-isystem bionic/libc/kernel/uapi",
149 // The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
150 "-isystem bionic/libc/kernel/uapi/asm-arm64",
151 "-isystem bionic/libc/kernel/android/uapi",
Ken Chenfd264442021-12-20 18:22:55 +0800152 "-I frameworks/libs/net/common/native/bpf_headers/include/bpf",
Maciej Żenczykowski79f6f752020-02-18 15:38:36 -0800153 // TODO(b/149785767): only give access to specific file with AID_* constants
154 "-I system/core/libcutils/include",
Colin Cross38406592018-05-17 11:17:01 -0700155 "-I " + ctx.ModuleDir(),
156 }
157
158 for _, dir := range android.PathsForSource(ctx, bpf.properties.Include_dirs) {
159 cflags = append(cflags, "-I "+dir.String())
160 }
161
162 cflags = append(cflags, bpf.properties.Cflags...)
163
Connor O'Brien25739652021-12-02 20:09:45 -0800164 if proptools.Bool(bpf.properties.Btf) {
165 cflags = append(cflags, "-g")
166 }
167
Colin Cross8a497952019-03-05 22:25:09 -0800168 srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
Colin Cross38406592018-05-17 11:17:01 -0700169
170 for _, src := range srcs {
Ken Chen5372a242022-07-07 17:48:06 +0800171 if strings.ContainsRune(filepath.Base(src.String()), '_') {
172 ctx.ModuleErrorf("invalid character '_' in source name")
173 }
Connor O'Brien25739652021-12-02 20:09:45 -0800174 obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
Colin Cross38406592018-05-17 11:17:01 -0700175
176 ctx.Build(pctx, android.BuildParams{
Colin Cross815daf92019-05-14 16:05:20 -0700177 Rule: ccRule,
Colin Cross38406592018-05-17 11:17:01 -0700178 Input: src,
179 Output: obj,
180 Args: map[string]string{
181 "cFlags": strings.Join(cflags, " "),
182 "ccCmd": "${config.ClangBin}/clang",
183 },
184 })
185
Connor O'Brien25739652021-12-02 20:09:45 -0800186 if proptools.Bool(bpf.properties.Btf) {
187 objStripped := android.ObjPathWithExt(ctx, "", src, "o")
188 ctx.Build(pctx, android.BuildParams{
Steven Moreland606c5e92019-12-12 14:23:42 -0800189 Rule: stripRule,
190 Input: obj,
Connor O'Brien25739652021-12-02 20:09:45 -0800191 Output: objStripped,
192 Args: map[string]string{
193 "stripCmd": "${config.ClangBin}/llvm-strip",
194 },
195 })
196 bpf.objs = append(bpf.objs, objStripped.WithoutRel())
197 } else {
198 bpf.objs = append(bpf.objs, obj.WithoutRel())
199 }
200
Colin Cross38406592018-05-17 11:17:01 -0700201 }
202}
203
Colin Cross38406592018-05-17 11:17:01 -0700204func (bpf *bpf) AndroidMk() android.AndroidMkData {
205 return android.AndroidMkData{
206 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
207 var names []string
208 fmt.Fprintln(w)
209 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
210 fmt.Fprintln(w)
Steven Moreland606c5e92019-12-12 14:23:42 -0800211 var localModulePath string
212 if bpf.properties.VendorInternal {
213 localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/bpf"
214 } else {
215 localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
216 }
Ken Chenfad7f9d2021-11-10 22:02:57 +0800217 if len(bpf.properties.Sub_dir) > 0 {
218 localModulePath += "/" + bpf.properties.Sub_dir
219 }
Colin Cross38406592018-05-17 11:17:01 -0700220 for _, obj := range bpf.objs {
221 objName := name + "_" + obj.Base()
222 names = append(names, objName)
223 fmt.Fprintln(w, "include $(CLEAR_VARS)")
224 fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
Bob Badourb4999222021-01-07 03:34:31 +0000225 data.Entries.WriteLicenseVariables(w)
Colin Cross38406592018-05-17 11:17:01 -0700226 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
227 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
228 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
Ken Chenfad7f9d2021-11-10 22:02:57 +0800229 fmt.Fprintln(w, localModulePath)
Colin Cross38406592018-05-17 11:17:01 -0700230 fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
231 fmt.Fprintln(w)
232 }
233 fmt.Fprintln(w, "include $(CLEAR_VARS)")
234 fmt.Fprintln(w, "LOCAL_MODULE := ", name)
Bob Badourb4999222021-01-07 03:34:31 +0000235 data.Entries.WriteLicenseVariables(w)
Colin Cross38406592018-05-17 11:17:01 -0700236 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(names, " "))
237 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
238 },
239 }
240}
241
Colin Cross41955e82019-05-29 14:40:35 -0700242// Implements OutputFileFileProducer interface so that the obj output can be used in the data property
Jaewoong Jung5f3fb4b2018-12-13 15:01:46 -0800243// of other modules.
Colin Cross41955e82019-05-29 14:40:35 -0700244func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
245 switch tag {
246 case "":
247 return bpf.objs, nil
248 default:
249 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
250 }
Jaewoong Jung5f3fb4b2018-12-13 15:01:46 -0800251}
252
Ken Chenfad7f9d2021-11-10 22:02:57 +0800253func (bpf *bpf) SubDir() string {
254 return bpf.properties.Sub_dir
255}
256
Colin Cross41955e82019-05-29 14:40:35 -0700257var _ android.OutputFileProducer = (*bpf)(nil)
Jaewoong Jung5f3fb4b2018-12-13 15:01:46 -0800258
markchien2f59ec92020-09-02 16:23:38 +0800259func BpfFactory() android.Module {
Colin Cross38406592018-05-17 11:17:01 -0700260 module := &bpf{}
261
262 module.AddProperties(&module.properties)
263
264 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
Zi Wangb3cb38c2022-09-23 16:36:11 -0700265 android.InitBazelModule(module)
Colin Cross38406592018-05-17 11:17:01 -0700266 return module
267}
Zi Wangb3cb38c2022-09-23 16:36:11 -0700268
269type bazelBpfAttributes struct {
270 Srcs bazel.LabelListAttribute
271 Copts bazel.StringListAttribute
272 Absolute_includes bazel.StringListAttribute
273 Btf *bool
274 // TODO(b/249528391): Add support for sub_dir
275}
276
277// bpf bp2build converter
278func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
279 if ctx.ModuleType() != "bpf" {
280 return
281 }
282
283 srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, b.properties.Srcs))
284 copts := bazel.MakeStringListAttribute(b.properties.Cflags)
285 absolute_includes := bazel.MakeStringListAttribute(b.properties.Include_dirs)
286 btf := b.properties.Btf
287
288 attrs := bazelBpfAttributes{
289 Srcs: srcs,
290 Copts: copts,
291 Absolute_includes: absolute_includes,
292 Btf: btf,
293 }
294 props := bazel.BazelTargetModuleProperties{
295 Rule_class: "bpf",
296 Bzl_load_location: "//build/bazel/rules/bpf:bpf.bzl",
297 }
298
299 ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: b.Name()}, &attrs)
300}