-
Notifications
You must be signed in to change notification settings - Fork 56
/
abi.bzl
199 lines (158 loc) · 6.09 KB
/
abi.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
"""Helpers to generate abi-specific ghost targets"""
load("@bazel_skylib//lib:paths.bzl", "paths")
load("//:bpf/bpf.bzl", "bpf_program", "bpf_skeleton")
def massage_abi_deps(deps, abi = "latest", additional_targets = []):
"""Given a list of dependencies returns their abi-specific variants
By default it will look for dependencies ending with ':agent', ':ghost' and ':ghost_uapi'
but the caller can specify additional dependencies as well. Once an abi-specific dependency
is identified it will change it to <orig_dep>_<abi_num> (for e.g. ':agent' -> ':agent_84').
This macro is a no-op if abi = 'latest'
Args:
deps: list of dependencies
abi: 'latest' or a specific abi number
additional_targets: list of additional abi-specific targets to massage
Returns:
Modified list of abi-specific dependencies.
"""
if abi == "latest":
return deps
uapi_targets = [
":agent",
":ghost",
":ghost_uapi",
]
if additional_targets:
uapi_targets.extend(additional_targets)
newdeps = []
for d in deps:
if d.endswith(tuple(uapi_targets)):
newdeps.append(d + "_" + str(abi))
else:
newdeps.append(d)
return newdeps
def massage_bpf_skel_hdrs(hdrs, abi = "latest"):
"""Identify bpf skeleton headers and replace them with their abi-specific variants.
This macro is a no-op if abi = 'latest'
Otherwise this function looks for headers ending with '.skel.h' and then changes the path
to include the <abi>.
For e.g. if abi=84 then schedulers/fifo/bpf_fifo.skel.h will be rewritten to
schedulers/fifo/84/bpf_fifo.skel.h
Args:
hdrs: list of headers
abi: 'latest' or a specific abi number
Returns:
Modified list of abi-specific headers
"""
if abi == "latest":
return hdrs
newhdrs = []
for d in hdrs:
if d.endswith(".skel.h"):
newhdrs.append(paths.dirname(d) + "/" + str(abi) + "/" + paths.basename(d))
else:
newhdrs.append(d)
return newhdrs
def define_ghost_uapi(name, abi):
"""Creates a ghost_uapi cc_library target for the specific abi.
define_ghost_uapi(name = 'ghost_uapi', abi = 'latest') will create the ':ghost_uapi' target
for the latest abi.
define_ghost_uapi(name = 'ghost_uapi', abi = 84) will create the ':ghost_uapi_84' target
with GHOST_SELECT_ABI=84 added to 'defines'. The use of 'defines' versus 'local_defines'
is intentional because we want all targets that depend on this abi-specific target to be
able to tell exactly what ABI they are being compiled against.
Args:
name: base name for the cc_library target
abi: 'latest' or a specific abi number
"""
defines = []
if abi != "latest":
name = name + "_" + str(abi)
defines.append("GHOST_SELECT_ABI=" + str(abi))
native.cc_library(
name = name,
srcs = [
"abi/" + str(abi) + "/kernel/ghost.h",
"lib/ghost_uapi.cc",
],
hdrs = [
"lib/ghost_uapi.h",
],
defines = defines,
visibility = [
],
alwayslink = 1,
)
def cc_library_ghost(name, abi, srcs, hdrs, deps, visibility = [], copts = [], linkopts = []):
"""Creates a cc_library target for the specific abi.
If abi == 'latest' then this macro behaves exactly like cc_library and
it creates a cc_library target called <name>.
If abi != 'latest' then the cc_library target is called <name>_<abi>.
Additionally uapi dependent targets in 'deps' are also modified as
described in massage_abi_deps().
Args:
name: base name for the cc_library target
abi: 'latest' or a specific abi number
srcs: source files
hdrs: headers
deps: dependencies
visibility: target visibility
copts: compiler options
linkopts: linker options
"""
if abi != "latest":
name = name + "_" + str(abi)
native.cc_library(
name = name,
srcs = srcs,
hdrs = massage_bpf_skel_hdrs(hdrs, abi),
copts = copts,
linkopts = linkopts,
visibility = visibility,
deps = massage_abi_deps(deps, abi),
)
def bpf_skel_ghost(name, src, hdrs, abi = "latest", objdir = ""):
"""Creates bpf_program and bpf_skeleton targets for an abi-specific bpf program
bpf_skel_ghost("fifo", "bpf_fifo.bpf.c", bpf_fifo_hdrs) will generate:
- bpf object at "schedulers/fifo/bpf_fifo_bpf.o"
- skeleton header at "schedulers/fifo/bpf_fifo.skel.h"
The variant above is designed for agents that bundle a bpf program in their cc_binary.
bpf_skel_ghost("fifo", bpf_fifo.bpf.c, bpf_fifo_hdrs, abi = 84, objdir = "bpf/user") will generate:
- bpf object at "bpf/user/84/bpf_fifo_bpf.o
- skeleton header at "bpf/user/84/bpf_fifo.skel.h"
The variant above is less common and currently used to compile the schedghostidle bpf program
bundled with the agent.
Args:
name: base name for the bpf_program and bpf_skeleton targets
src: bpf source file
hdrs: list of headers to compile the bpf source file
abi: 'latest' or a specific abi number
objdir: optional directory to generate the bpf object and skeleton (default is "schedulers/<name>")
"""
bpf_name = "bpf_" + name
prog_name = bpf_name
skel_name = bpf_name + "_skel"
macros = []
hdrs = list(hdrs) # make a local copy
if not objdir:
objdir = "schedulers/" + name
if abi != "latest":
prog_name += "_" + str(abi)
skel_name += "_" + str(abi)
objdir = objdir + "/" + str(abi)
macros.append("GHOST_SELECT_ABI=" + str(abi))
hdrs.append("//:lib/ghost_uapi.h")
hdrs.append("//:abi/" + str(abi) + "/kernel/ghost.h")
bpf_object = objdir + "/" + bpf_name + "_bpf.o"
skel_hdr = objdir + "/" + bpf_name + ".skel.h"
bpf_program(
name = prog_name,
src = src,
hdrs = hdrs,
bpf_object = bpf_object,
macros = macros,
)
bpf_skeleton(
name = skel_name,
bpf_object = prog_name,
skel_hdr = skel_hdr,
)