123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- // Copyright (C) 2018 The Android Open Source Project
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package bpf
- import (
- "fmt"
- "io"
- "path/filepath"
- "runtime"
- "strings"
- "android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
- "android/soong/cc"
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
- )
- func init() {
- registerBpfBuildComponents(android.InitRegistrationContext)
- pctx.Import("android/soong/cc/config")
- pctx.StaticVariable("relPwd", cc.PwdPrefix())
- }
- var (
- pctx = android.NewPackageContext("android/soong/bpf")
- ccRule = pctx.AndroidRemoteStaticRule("ccRule", android.RemoteRuleSupports{Goma: true},
- blueprint.RuleParams{
- Depfile: "${out}.d",
- Deps: blueprint.DepsGCC,
- Command: "$relPwd $ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
- CommandDeps: []string{"$ccCmd"},
- },
- "ccCmd", "cFlags")
- stripRule = pctx.AndroidStaticRule("stripRule",
- blueprint.RuleParams{
- Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
- `--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
- CommandDeps: []string{"$stripCmd"},
- },
- "stripCmd")
- )
- func registerBpfBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("bpf", BpfFactory)
- }
- var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents)
- // BpfModule interface is used by the apex package to gather information from a bpf module.
- type BpfModule interface {
- android.Module
- OutputFiles(tag string) (android.Paths, error)
- // Returns the sub install directory if the bpf module is included by apex.
- SubDir() string
- }
- type BpfProperties struct {
- // source paths to the files.
- Srcs []string `android:"path"`
- // additional cflags that should be used to build the bpf variant of
- // the C/C++ module.
- Cflags []string
- // directories (relative to the root of the source tree) that will
- // be added to the include paths using -I.
- Include_dirs []string
- // optional subdirectory under which this module is installed into.
- Sub_dir string
- // if set to true, generate BTF debug info for maps & programs.
- Btf *bool
- Vendor *bool
- VendorInternal bool `blueprint:"mutated"`
- }
- type bpf struct {
- android.ModuleBase
- android.BazelModuleBase
- properties BpfProperties
- objs android.Paths
- }
- var _ android.ImageInterface = (*bpf)(nil)
- func (bpf *bpf) ImageMutatorBegin(ctx android.BaseModuleContext) {}
- func (bpf *bpf) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
- return !proptools.Bool(bpf.properties.Vendor)
- }
- func (bpf *bpf) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
- return false
- }
- func (bpf *bpf) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
- return false
- }
- func (bpf *bpf) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
- return false
- }
- func (bpf *bpf) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
- return false
- }
- func (bpf *bpf) ExtraImageVariations(ctx android.BaseModuleContext) []string {
- if proptools.Bool(bpf.properties.Vendor) {
- return []string{"vendor"}
- }
- return nil
- }
- func (bpf *bpf) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
- bpf.properties.VendorInternal = variation == "vendor"
- }
- func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- cflags := []string{
- "-nostdlibinc",
- // Make paths in deps files relative
- "-no-canonical-prefixes",
- "-O2",
- "-isystem bionic/libc/include",
- "-isystem bionic/libc/kernel/uapi",
- // The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
- "-isystem bionic/libc/kernel/uapi/asm-arm64",
- "-isystem bionic/libc/kernel/android/uapi",
- "-I frameworks/libs/net/common/native/bpf_headers/include/bpf",
- // TODO(b/149785767): only give access to specific file with AID_* constants
- "-I system/core/libcutils/include",
- "-I " + ctx.ModuleDir(),
- }
- for _, dir := range android.PathsForSource(ctx, bpf.properties.Include_dirs) {
- cflags = append(cflags, "-I "+dir.String())
- }
- cflags = append(cflags, bpf.properties.Cflags...)
- if proptools.Bool(bpf.properties.Btf) {
- cflags = append(cflags, "-g")
- if runtime.GOOS != "darwin" {
- cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
- }
- }
- srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
- for _, src := range srcs {
- if strings.ContainsRune(filepath.Base(src.String()), '_') {
- ctx.ModuleErrorf("invalid character '_' in source name")
- }
- obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
- ctx.Build(pctx, android.BuildParams{
- Rule: ccRule,
- Input: src,
- Output: obj,
- Args: map[string]string{
- "cFlags": strings.Join(cflags, " "),
- "ccCmd": "${config.ClangBin}/clang",
- },
- })
- if proptools.Bool(bpf.properties.Btf) {
- objStripped := android.ObjPathWithExt(ctx, "", src, "o")
- ctx.Build(pctx, android.BuildParams{
- Rule: stripRule,
- Input: obj,
- Output: objStripped,
- Args: map[string]string{
- "stripCmd": "${config.ClangBin}/llvm-strip",
- },
- })
- bpf.objs = append(bpf.objs, objStripped.WithoutRel())
- } else {
- bpf.objs = append(bpf.objs, obj.WithoutRel())
- }
- }
- }
- func (bpf *bpf) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- var names []string
- fmt.Fprintln(w)
- fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
- fmt.Fprintln(w)
- var localModulePath string
- if bpf.properties.VendorInternal {
- localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/bpf"
- } else {
- localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
- }
- if len(bpf.properties.Sub_dir) > 0 {
- localModulePath += "/" + bpf.properties.Sub_dir
- }
- for _, obj := range bpf.objs {
- objName := name + "_" + obj.Base()
- names = append(names, objName)
- fmt.Fprintln(w, "include $(CLEAR_VARS)", " # bpf.bpf.obj")
- fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
- data.Entries.WriteLicenseVariables(w)
- fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
- fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
- fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
- fmt.Fprintln(w, localModulePath)
- fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
- fmt.Fprintln(w)
- }
- fmt.Fprintln(w, "include $(CLEAR_VARS)", " # bpf.bpf")
- fmt.Fprintln(w, "LOCAL_MODULE := ", name)
- data.Entries.WriteLicenseVariables(w)
- fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(names, " "))
- fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
- },
- }
- }
- var _ android.MixedBuildBuildable = (*bpf)(nil)
- func (bpf *bpf) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return true
- }
- func (bpf *bpf) QueueBazelCall(ctx android.BaseModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(
- bpf.GetBazelLabel(ctx, bpf),
- cquery.GetOutputFiles,
- android.GetConfigKey(ctx))
- }
- func (bpf *bpf) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- objPaths, err := bazelCtx.GetOutputFiles(bpf.GetBazelLabel(ctx, bpf), android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
- bazelOuts := android.Paths{}
- for _, p := range objPaths {
- bazelOuts = append(bazelOuts, android.PathForBazelOut(ctx, p))
- }
- bpf.objs = bazelOuts
- }
- // Implements OutputFileFileProducer interface so that the obj output can be used in the data property
- // of other modules.
- func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return bpf.objs, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
- }
- func (bpf *bpf) SubDir() string {
- return bpf.properties.Sub_dir
- }
- var _ android.OutputFileProducer = (*bpf)(nil)
- func BpfFactory() android.Module {
- module := &bpf{}
- module.AddProperties(&module.properties)
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitBazelModule(module)
- return module
- }
- type bazelBpfAttributes struct {
- Srcs bazel.LabelListAttribute
- Copts bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Btf *bool
- // TODO(b/249528391): Add support for sub_dir
- }
- // bpf bp2build converter
- func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if ctx.ModuleType() != "bpf" {
- return
- }
- srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, b.properties.Srcs))
- copts := bazel.MakeStringListAttribute(b.properties.Cflags)
- absolute_includes := bazel.MakeStringListAttribute(b.properties.Include_dirs)
- btf := b.properties.Btf
- attrs := bazelBpfAttributes{
- Srcs: srcs,
- Copts: copts,
- Absolute_includes: absolute_includes,
- Btf: btf,
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "bpf",
- Bzl_load_location: "//build/bazel/rules/bpf:bpf.bzl",
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: b.Name()}, &attrs)
- }
|