1// 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" 20 "strings" 21 22 "android/soong/android" 23 _ "android/soong/cc/config" 24 25 "github.com/google/blueprint" 26) 27 28func init() { 29 registerBpfBuildComponents(android.InitRegistrationContext) 30 pctx.Import("android/soong/cc/config") 31} 32 33var ( 34 pctx = android.NewPackageContext("android/soong/bpf") 35 36 ccRule = pctx.AndroidRemoteStaticRule("ccRule", android.RemoteRuleSupports{Goma: true}, 37 blueprint.RuleParams{ 38 Depfile: "${out}.d", 39 Deps: blueprint.DepsGCC, 40 Command: "$ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in", 41 CommandDeps: []string{"$ccCmd"}, 42 }, 43 "ccCmd", "cFlags") 44) 45 46func registerBpfBuildComponents(ctx android.RegistrationContext) { 47 ctx.RegisterModuleType("bpf", BpfFactory) 48} 49 50var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents) 51 52// BpfModule interface is used by the apex package to gather information from a bpf module. 53type BpfModule interface { 54 android.Module 55 56 OutputFiles(tag string) (android.Paths, error) 57} 58 59type BpfProperties struct { 60 Srcs []string `android:"path"` 61 Cflags []string 62 Include_dirs []string 63} 64 65type bpf struct { 66 android.ModuleBase 67 68 properties BpfProperties 69 70 objs android.Paths 71} 72 73func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) { 74 cflags := []string{ 75 "-nostdlibinc", 76 77 // Make paths in deps files relative 78 "-no-canonical-prefixes", 79 80 "-O2", 81 "-isystem bionic/libc/include", 82 "-isystem bionic/libc/kernel/uapi", 83 // The architecture doesn't matter here, but asm/types.h is included by linux/types.h. 84 "-isystem bionic/libc/kernel/uapi/asm-arm64", 85 "-isystem bionic/libc/kernel/android/uapi", 86 // TODO(b/149785767): only give access to specific file with AID_* constants 87 "-I system/core/libcutils/include", 88 "-I system/bpf/progs/include", 89 "-I " + ctx.ModuleDir(), 90 } 91 92 for _, dir := range android.PathsForSource(ctx, bpf.properties.Include_dirs) { 93 cflags = append(cflags, "-I "+dir.String()) 94 } 95 96 cflags = append(cflags, bpf.properties.Cflags...) 97 98 srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs) 99 100 for _, src := range srcs { 101 obj := android.ObjPathWithExt(ctx, "", src, "o") 102 103 ctx.Build(pctx, android.BuildParams{ 104 Rule: ccRule, 105 Input: src, 106 Output: obj, 107 Args: map[string]string{ 108 "cFlags": strings.Join(cflags, " "), 109 "ccCmd": "${config.ClangBin}/clang", 110 }, 111 }) 112 113 bpf.objs = append(bpf.objs, obj.WithoutRel()) 114 } 115} 116 117func (bpf *bpf) AndroidMk() android.AndroidMkData { 118 return android.AndroidMkData{ 119 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { 120 var names []string 121 fmt.Fprintln(w) 122 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) 123 fmt.Fprintln(w) 124 for _, obj := range bpf.objs { 125 objName := name + "_" + obj.Base() 126 names = append(names, objName) 127 fmt.Fprintln(w, "include $(CLEAR_VARS)") 128 fmt.Fprintln(w, "LOCAL_MODULE := ", objName) 129 data.Entries.WriteLicenseVariables(w) 130 fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String()) 131 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base()) 132 fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") 133 fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf") 134 fmt.Fprintln(w, "include $(BUILD_PREBUILT)") 135 fmt.Fprintln(w) 136 } 137 fmt.Fprintln(w, "include $(CLEAR_VARS)") 138 fmt.Fprintln(w, "LOCAL_MODULE := ", name) 139 data.Entries.WriteLicenseVariables(w) 140 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(names, " ")) 141 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)") 142 }, 143 } 144} 145 146// Implements OutputFileFileProducer interface so that the obj output can be used in the data property 147// of other modules. 148func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) { 149 switch tag { 150 case "": 151 return bpf.objs, nil 152 default: 153 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 154 } 155} 156 157var _ android.OutputFileProducer = (*bpf)(nil) 158 159func BpfFactory() android.Module { 160 module := &bpf{} 161 162 module.AddProperties(&module.properties) 163 164 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) 165 return module 166} 167