Merge "SOONG: BPF: add libbpf_prog soong module" into main am: f1d63b8b6d
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/3202693 Change-Id: I6007e73b5dea1d1766f4ddebeee26c63a3e6c398 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -913,6 +913,7 @@ func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *
|
|||||||
case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
|
case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
|
||||||
case "*apex.apexBundle": // license properties written
|
case "*apex.apexBundle": // license properties written
|
||||||
case "*bpf.bpf": // license properties written (both for module and objs)
|
case "*bpf.bpf": // license properties written (both for module and objs)
|
||||||
|
case "*libbpf_prog.libbpfProg": // license properties written (both for module and objs)
|
||||||
case "*genrule.Module": // writes non-custom before adding .phony
|
case "*genrule.Module": // writes non-custom before adding .phony
|
||||||
case "*java.SystemModules": // doesn't go through base_rules
|
case "*java.SystemModules": // doesn't go through base_rules
|
||||||
case "*java.systemModulesImport": // doesn't go through base_rules
|
case "*java.systemModulesImport": // doesn't go through base_rules
|
||||||
|
38
bpf/libbpf/Android.bp
Normal file
38
bpf/libbpf/Android.bp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2024 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 {
|
||||||
|
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrap_go_package {
|
||||||
|
name: "soong-libbpf",
|
||||||
|
pkgPath: "android/soong/bpf/libbpf",
|
||||||
|
deps: [
|
||||||
|
"blueprint",
|
||||||
|
"blueprint-proptools",
|
||||||
|
"soong-android",
|
||||||
|
"soong-cc",
|
||||||
|
"soong-cc-config",
|
||||||
|
],
|
||||||
|
srcs: [
|
||||||
|
"libbpf_prog.go",
|
||||||
|
],
|
||||||
|
testSrcs: [
|
||||||
|
"libbpf_prog_test.go",
|
||||||
|
],
|
||||||
|
pluginFor: ["soong_build"],
|
||||||
|
}
|
278
bpf/libbpf/libbpf_prog.go
Normal file
278
bpf/libbpf/libbpf_prog.go
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
// Copyright (C) 2024 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 libbpf_prog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"android/soong/android"
|
||||||
|
"android/soong/cc"
|
||||||
|
"android/soong/genrule"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
)
|
||||||
|
|
||||||
|
type libbpfProgDepType struct {
|
||||||
|
blueprint.BaseDependencyTag
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registerLibbpfProgBuildComponents(android.InitRegistrationContext)
|
||||||
|
pctx.Import("android/soong/cc/config")
|
||||||
|
pctx.StaticVariable("relPwd", cc.PwdPrefix())
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
pctx = android.NewPackageContext("android/soong/bpf/libbpf_prog")
|
||||||
|
|
||||||
|
libbpfProgCcRule = pctx.AndroidStaticRule("libbpfProgCcRule",
|
||||||
|
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")
|
||||||
|
|
||||||
|
libbpfProgStripRule = pctx.AndroidStaticRule("libbpfProgStripRule",
|
||||||
|
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")
|
||||||
|
|
||||||
|
libbpfProgDepTag = libbpfProgDepType{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func registerLibbpfProgBuildComponents(ctx android.RegistrationContext) {
|
||||||
|
ctx.RegisterModuleType("libbpf_prog", LibbpfProgFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
var PrepareForTestWithLibbpfProg = android.GroupFixturePreparers(
|
||||||
|
android.FixtureRegisterWithContext(registerLibbpfProgBuildComponents),
|
||||||
|
android.FixtureAddFile("libbpf_headers/Foo.h", nil),
|
||||||
|
android.FixtureAddFile("libbpf_headers/Android.bp", []byte(`
|
||||||
|
genrule {
|
||||||
|
name: "libbpf_headers",
|
||||||
|
out: ["foo.h",],
|
||||||
|
}
|
||||||
|
`)),
|
||||||
|
genrule.PrepareForTestWithGenRuleBuildComponents,
|
||||||
|
)
|
||||||
|
|
||||||
|
type LibbpfProgProperties struct {
|
||||||
|
// source paths to the files.
|
||||||
|
Srcs []string `android:"path"`
|
||||||
|
|
||||||
|
// additional cflags that should be used to build the libbpf variant of
|
||||||
|
// the C/C++ module.
|
||||||
|
Cflags []string `android:"arch_variant"`
|
||||||
|
|
||||||
|
// list of directories relative to the Blueprint file that will
|
||||||
|
// be added to the include path using -I
|
||||||
|
Local_include_dirs []string `android:"arch_variant"`
|
||||||
|
|
||||||
|
// optional subdirectory under which this module is installed into.
|
||||||
|
Relative_install_path string
|
||||||
|
}
|
||||||
|
|
||||||
|
type libbpfProg struct {
|
||||||
|
android.ModuleBase
|
||||||
|
properties LibbpfProgProperties
|
||||||
|
objs android.Paths
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ android.ImageInterface = (*libbpfProg)(nil)
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) ImageMutatorBegin(ctx android.BaseModuleContext) {}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) ExtraImageVariations(ctx android.BaseModuleContext) []string {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) SetImageVariation(ctx android.BaseModuleContext, variation string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
ctx.AddDependency(ctx.Module(), libbpfProgDepTag, "libbpf_headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
var cFlagsDeps android.Paths
|
||||||
|
cflags := []string{
|
||||||
|
"-nostdlibinc",
|
||||||
|
|
||||||
|
// Make paths in deps files relative
|
||||||
|
"-no-canonical-prefixes",
|
||||||
|
|
||||||
|
"-O2",
|
||||||
|
"-Wall",
|
||||||
|
"-Werror",
|
||||||
|
"-Wextra",
|
||||||
|
|
||||||
|
"-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 " + ctx.ModuleDir(),
|
||||||
|
"-g", //Libbpf builds require BTF data
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS != "darwin" {
|
||||||
|
cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||||
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||||
|
if depTag == libbpfProgDepTag {
|
||||||
|
if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
|
||||||
|
cFlagsDeps = append(cFlagsDeps, genRule.GeneratedDeps()...)
|
||||||
|
dirs := genRule.GeneratedHeaderDirs()
|
||||||
|
for _, dir := range dirs {
|
||||||
|
cflags = append(cflags, "-I "+dir.String())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
depName := ctx.OtherModuleName(dep)
|
||||||
|
ctx.ModuleErrorf("module %q is not a genrule", depName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, dir := range android.PathsForModuleSrc(ctx, libbpf.properties.Local_include_dirs) {
|
||||||
|
cflags = append(cflags, "-I "+dir.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
cflags = append(cflags, libbpf.properties.Cflags...)
|
||||||
|
|
||||||
|
srcs := android.PathsForModuleSrc(ctx, libbpf.properties.Srcs)
|
||||||
|
|
||||||
|
for _, src := range srcs {
|
||||||
|
if strings.ContainsRune(src.Base(), '_') {
|
||||||
|
ctx.ModuleErrorf("invalid character '_' in source name")
|
||||||
|
}
|
||||||
|
obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
|
||||||
|
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: libbpfProgCcRule,
|
||||||
|
Input: src,
|
||||||
|
Implicits: cFlagsDeps,
|
||||||
|
Output: obj,
|
||||||
|
Args: map[string]string{
|
||||||
|
"cFlags": strings.Join(cflags, " "),
|
||||||
|
"ccCmd": "${config.ClangBin}/clang",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
objStripped := android.ObjPathWithExt(ctx, "", src, "o")
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: libbpfProgStripRule,
|
||||||
|
Input: obj,
|
||||||
|
Output: objStripped,
|
||||||
|
Args: map[string]string{
|
||||||
|
"stripCmd": "${config.ClangBin}/llvm-strip",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
libbpf.objs = append(libbpf.objs, objStripped.WithoutRel())
|
||||||
|
}
|
||||||
|
|
||||||
|
installDir := android.PathForModuleInstall(ctx, "etc", "bpf/libbpf")
|
||||||
|
if len(libbpf.properties.Relative_install_path) > 0 {
|
||||||
|
installDir = installDir.Join(ctx, libbpf.properties.Relative_install_path)
|
||||||
|
}
|
||||||
|
for _, obj := range libbpf.objs {
|
||||||
|
ctx.PackageFile(installDir, obj.Base(), obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
|
||||||
|
|
||||||
|
ctx.SetOutputFiles(libbpf.objs, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (libbpf *libbpfProg) 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
|
||||||
|
localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf/libbpf"
|
||||||
|
if len(libbpf.properties.Relative_install_path) > 0 {
|
||||||
|
localModulePath += "/" + libbpf.properties.Relative_install_path
|
||||||
|
}
|
||||||
|
for _, obj := range libbpf.objs {
|
||||||
|
objName := name + "_" + obj.Base()
|
||||||
|
names = append(names, objName)
|
||||||
|
fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf.obj")
|
||||||
|
fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
|
||||||
|
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)
|
||||||
|
// AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
|
||||||
|
for _, extra := range data.Extra {
|
||||||
|
extra(w, nil)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
||||||
|
fmt.Fprintln(w)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf")
|
||||||
|
fmt.Fprintln(w, "LOCAL_MODULE := ", name)
|
||||||
|
android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", names)
|
||||||
|
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LibbpfProgFactory() android.Module {
|
||||||
|
module := &libbpfProg{}
|
||||||
|
|
||||||
|
module.AddProperties(&module.properties)
|
||||||
|
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
|
||||||
|
return module
|
||||||
|
}
|
69
bpf/libbpf/libbpf_prog_test.go
Normal file
69
bpf/libbpf/libbpf_prog_test.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright 2024 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// 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 libbpf_prog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"android/soong/android"
|
||||||
|
"android/soong/cc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
os.Exit(m.Run())
|
||||||
|
}
|
||||||
|
|
||||||
|
var prepareForLibbpfProgTest = android.GroupFixturePreparers(
|
||||||
|
cc.PrepareForTestWithCcDefaultModules,
|
||||||
|
android.FixtureMergeMockFs(
|
||||||
|
map[string][]byte{
|
||||||
|
"bpf.c": nil,
|
||||||
|
"bpf_invalid_name.c": nil,
|
||||||
|
"BpfTest.cpp": nil,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
PrepareForTestWithLibbpfProg,
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLibbpfProgDataDependency(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
libbpf_prog {
|
||||||
|
name: "bpf.o",
|
||||||
|
srcs: ["bpf.c"],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_test {
|
||||||
|
name: "vts_test_binary_bpf_module",
|
||||||
|
srcs: ["BpfTest.cpp"],
|
||||||
|
data: [":bpf.o"],
|
||||||
|
gtest: false,
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
prepareForLibbpfProgTest.RunTestWithBp(t, bp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLibbpfProgSourceName(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
libbpf_prog {
|
||||||
|
name: "bpf_invalid_name.o",
|
||||||
|
srcs: ["bpf_invalid_name.c"],
|
||||||
|
}
|
||||||
|
`
|
||||||
|
prepareForLibbpfProgTest.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
|
||||||
|
`invalid character '_' in source name`)).
|
||||||
|
RunTestWithBp(t, bp)
|
||||||
|
}
|
Reference in New Issue
Block a user