bpf.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. package bpf
  15. import (
  16. "fmt"
  17. "io"
  18. "path/filepath"
  19. "strings"
  20. "android/soong/android"
  21. "android/soong/bazel"
  22. "github.com/google/blueprint"
  23. "github.com/google/blueprint/proptools"
  24. )
  25. func init() {
  26. registerBpfBuildComponents(android.InitRegistrationContext)
  27. pctx.Import("android/soong/cc/config")
  28. }
  29. var (
  30. pctx = android.NewPackageContext("android/soong/bpf")
  31. ccRule = pctx.AndroidRemoteStaticRule("ccRule", android.RemoteRuleSupports{Goma: true},
  32. blueprint.RuleParams{
  33. Depfile: "${out}.d",
  34. Deps: blueprint.DepsGCC,
  35. Command: "$ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
  36. CommandDeps: []string{"$ccCmd"},
  37. },
  38. "ccCmd", "cFlags")
  39. stripRule = pctx.AndroidStaticRule("stripRule",
  40. blueprint.RuleParams{
  41. Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
  42. `--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
  43. CommandDeps: []string{"$stripCmd"},
  44. },
  45. "stripCmd")
  46. )
  47. func registerBpfBuildComponents(ctx android.RegistrationContext) {
  48. ctx.RegisterModuleType("bpf", BpfFactory)
  49. }
  50. var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents)
  51. // BpfModule interface is used by the apex package to gather information from a bpf module.
  52. type BpfModule interface {
  53. android.Module
  54. OutputFiles(tag string) (android.Paths, error)
  55. // Returns the sub install directory if the bpf module is included by apex.
  56. SubDir() string
  57. }
  58. type BpfProperties struct {
  59. // source paths to the files.
  60. Srcs []string `android:"path"`
  61. // additional cflags that should be used to build the bpf variant of
  62. // the C/C++ module.
  63. Cflags []string
  64. // directories (relative to the root of the source tree) that will
  65. // be added to the include paths using -I.
  66. Include_dirs []string
  67. // optional subdirectory under which this module is installed into.
  68. Sub_dir string
  69. // if set to true, generate BTF debug info for maps & programs.
  70. Btf *bool
  71. Vendor *bool
  72. VendorInternal bool `blueprint:"mutated"`
  73. }
  74. type bpf struct {
  75. android.ModuleBase
  76. android.BazelModuleBase
  77. properties BpfProperties
  78. objs android.Paths
  79. }
  80. var _ android.ImageInterface = (*bpf)(nil)
  81. func (bpf *bpf) ImageMutatorBegin(ctx android.BaseModuleContext) {}
  82. func (bpf *bpf) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
  83. return !proptools.Bool(bpf.properties.Vendor)
  84. }
  85. func (bpf *bpf) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
  86. return false
  87. }
  88. func (bpf *bpf) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
  89. return false
  90. }
  91. func (bpf *bpf) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
  92. return false
  93. }
  94. func (bpf *bpf) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
  95. return false
  96. }
  97. func (bpf *bpf) ExtraImageVariations(ctx android.BaseModuleContext) []string {
  98. if proptools.Bool(bpf.properties.Vendor) {
  99. return []string{"vendor"}
  100. }
  101. return nil
  102. }
  103. func (bpf *bpf) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
  104. bpf.properties.VendorInternal = variation == "vendor"
  105. }
  106. func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  107. cflags := []string{
  108. "-nostdlibinc",
  109. // Make paths in deps files relative
  110. "-no-canonical-prefixes",
  111. "-O2",
  112. "-isystem bionic/libc/include",
  113. "-isystem bionic/libc/kernel/uapi",
  114. // The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
  115. "-isystem bionic/libc/kernel/uapi/asm-arm64",
  116. "-isystem bionic/libc/kernel/android/uapi",
  117. "-I frameworks/libs/net/common/native/bpf_headers/include/bpf",
  118. // TODO(b/149785767): only give access to specific file with AID_* constants
  119. "-I system/core/libcutils/include",
  120. "-I " + ctx.ModuleDir(),
  121. }
  122. for _, dir := range android.PathsForSource(ctx, bpf.properties.Include_dirs) {
  123. cflags = append(cflags, "-I "+dir.String())
  124. }
  125. cflags = append(cflags, bpf.properties.Cflags...)
  126. if proptools.Bool(bpf.properties.Btf) {
  127. cflags = append(cflags, "-g")
  128. }
  129. srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
  130. for _, src := range srcs {
  131. if strings.ContainsRune(filepath.Base(src.String()), '_') {
  132. ctx.ModuleErrorf("invalid character '_' in source name")
  133. }
  134. obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
  135. ctx.Build(pctx, android.BuildParams{
  136. Rule: ccRule,
  137. Input: src,
  138. Output: obj,
  139. Args: map[string]string{
  140. "cFlags": strings.Join(cflags, " "),
  141. "ccCmd": "${config.ClangBin}/clang",
  142. },
  143. })
  144. if proptools.Bool(bpf.properties.Btf) {
  145. objStripped := android.ObjPathWithExt(ctx, "", src, "o")
  146. ctx.Build(pctx, android.BuildParams{
  147. Rule: stripRule,
  148. Input: obj,
  149. Output: objStripped,
  150. Args: map[string]string{
  151. "stripCmd": "${config.ClangBin}/llvm-strip",
  152. },
  153. })
  154. bpf.objs = append(bpf.objs, objStripped.WithoutRel())
  155. } else {
  156. bpf.objs = append(bpf.objs, obj.WithoutRel())
  157. }
  158. }
  159. }
  160. func (bpf *bpf) AndroidMk() android.AndroidMkData {
  161. return android.AndroidMkData{
  162. Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
  163. var names []string
  164. fmt.Fprintln(w)
  165. fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
  166. fmt.Fprintln(w)
  167. var localModulePath string
  168. if bpf.properties.VendorInternal {
  169. localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/bpf"
  170. } else {
  171. localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
  172. }
  173. if len(bpf.properties.Sub_dir) > 0 {
  174. localModulePath += "/" + bpf.properties.Sub_dir
  175. }
  176. for _, obj := range bpf.objs {
  177. objName := name + "_" + obj.Base()
  178. names = append(names, objName)
  179. fmt.Fprintln(w, "include $(CLEAR_VARS)")
  180. fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
  181. data.Entries.WriteLicenseVariables(w)
  182. fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
  183. fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
  184. fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
  185. fmt.Fprintln(w, localModulePath)
  186. fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
  187. fmt.Fprintln(w)
  188. }
  189. fmt.Fprintln(w, "include $(CLEAR_VARS)")
  190. fmt.Fprintln(w, "LOCAL_MODULE := ", name)
  191. data.Entries.WriteLicenseVariables(w)
  192. fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(names, " "))
  193. fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
  194. },
  195. }
  196. }
  197. // Implements OutputFileFileProducer interface so that the obj output can be used in the data property
  198. // of other modules.
  199. func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
  200. switch tag {
  201. case "":
  202. return bpf.objs, nil
  203. default:
  204. return nil, fmt.Errorf("unsupported module reference tag %q", tag)
  205. }
  206. }
  207. func (bpf *bpf) SubDir() string {
  208. return bpf.properties.Sub_dir
  209. }
  210. var _ android.OutputFileProducer = (*bpf)(nil)
  211. func BpfFactory() android.Module {
  212. module := &bpf{}
  213. module.AddProperties(&module.properties)
  214. android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
  215. android.InitBazelModule(module)
  216. return module
  217. }
  218. type bazelBpfAttributes struct {
  219. Srcs bazel.LabelListAttribute
  220. Copts bazel.StringListAttribute
  221. Absolute_includes bazel.StringListAttribute
  222. Btf *bool
  223. // TODO(b/249528391): Add support for sub_dir
  224. }
  225. // bpf bp2build converter
  226. func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
  227. if ctx.ModuleType() != "bpf" {
  228. return
  229. }
  230. srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, b.properties.Srcs))
  231. copts := bazel.MakeStringListAttribute(b.properties.Cflags)
  232. absolute_includes := bazel.MakeStringListAttribute(b.properties.Include_dirs)
  233. btf := b.properties.Btf
  234. attrs := bazelBpfAttributes{
  235. Srcs: srcs,
  236. Copts: copts,
  237. Absolute_includes: absolute_includes,
  238. Btf: btf,
  239. }
  240. props := bazel.BazelTargetModuleProperties{
  241. Rule_class: "bpf",
  242. Bzl_load_location: "//build/bazel/rules/bpf:bpf.bzl",
  243. }
  244. ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: b.Name()}, &attrs)
  245. }