-
Notifications
You must be signed in to change notification settings - Fork 36
/
build.bzl
150 lines (132 loc) · 5.26 KB
/
build.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
load("@prelude//:artifacts.bzl", "ArtifactExt", "artifact_ext")
load("@prelude//:paths.bzl", path_utils = "paths")
load("@prelude//cxx:cxx_context.bzl", "get_cxx_toolchain_info")
load("@prelude//cxx:preprocessor.bzl", "CPreprocessorInfo")
load(
"@prelude//linking:shared_libraries.bzl",
"SharedLibrary",
"gen_shared_libs_action",
)
load(
"@prelude//python:manifest.bzl",
"ManifestInfo", # @unused Used as a type
)
load(":providers.bzl", "ThirdPartyBuild", "ThirdPartyBuildInfo", "third_party_build_info")
def project_from_label(label: Label) -> str:
"""
Generate a unique third-party project name for the given label.
"""
return str(label.raw_target())
def prefix_from_label(label: Label, prefix: str = "/usr/local") -> str:
"""
Generate a unique third-party prefix for the given label.
"""
return path_utils.join(prefix, "{}-{}".format(label.name, sha256(str(label.raw_target()))[:7]))
def create_third_party_build_root(
ctx: AnalysisContext,
out: str = "__third_party_build__",
manifests: list[(str, ManifestInfo)] = [],
shared_libs: list[SharedLibrary] = [],
cxx_headers: list[CPreprocessorInfo] = [],
paths: list[(str, Artifact)] = []) -> ArtifactExt:
"""
Installs components into a unix-y install dir which can by used by other
third-party builds.
"""
cmd = cmd_args()
cmd.add(ctx.attrs._create_third_party_build_root[RunInfo])
for dst, manifest in manifests:
cmd.add(
"--manifest",
dst,
cmd_args(manifest.manifest, hidden = [a for a, _ in manifest.artifacts]),
)
for pps in cxx_headers:
for pp in pps.set.value:
for hdr in pp.headers:
cmd.add("--path", path_utils.join("include", hdr.namespace, hdr.name), hdr.artifact)
for dst, path in paths:
cmd.add("--path", dst, path)
def gen(actions, output, shared_libs):
lines = []
if shared_libs:
sh_ext = get_cxx_toolchain_info(ctx).linker_info.shared_library_name_format.format("")
for soname, shared_lib in shared_libs.items():
lines.append(cmd_args("--path", path_utils.join("lib", soname), shared_lib.lib.output))
# Linker link `-l<name>` dynamically (by default) by looking for `lib<name>.so`,
# so make sure this exists by creating it as a symlink (to the versioned name)
# if it doesn't already.
if sh_ext in soname and not soname.endswith(sh_ext):
idx = soname.index(sh_ext)
link_name = soname[:idx + 3]
lines.append(cmd_args("--symlink", path_utils.join("lib", link_name), soname))
return actions.write(output.as_output(), lines)
# Add shlibs via argfsile.
argsfile = gen_shared_libs_action(
actions = ctx.actions,
out = "shared_libs_args.txt",
shared_libs = shared_libs,
gen_action = gen,
)
cmd.add(cmd_args(argsfile, format = "@{}", hidden = [s.lib.output for s in shared_libs]))
out = ctx.actions.declare_output(out, dir = True)
cmd.add(out.as_output())
ctx.actions.run(cmd, category = "third_party_build_root")
return artifact_ext(out)
def create_third_party_build_info(
ctx: AnalysisContext,
project: str | None = None,
prefix: str | None = None,
out: str = "__third_party_build__",
manifests: list[(str, ManifestInfo)] = [],
shared_libs: list[SharedLibrary] = [],
cxx_headers: list[CPreprocessorInfo] = [],
cxx_header_dirs: list[str] = [],
paths: list[(str, Artifact)] = [],
deps: list[Dependency] = []) -> ThirdPartyBuildInfo:
if project == None:
project = project_from_label(ctx.label)
if prefix == None:
prefix = prefix_from_label(ctx.label)
root = create_third_party_build_root(
ctx = ctx,
out = out,
manifests = manifests,
cxx_headers = cxx_headers,
shared_libs = shared_libs,
paths = paths,
)
# Build manifest.
def gen_manifest(actions, output, shared_libs):
manifest = {}
manifest["project"] = project
manifest["prefix"] = prefix
if cxx_header_dirs:
manifest["c_include_paths"] = cxx_header_dirs
manifest["cxx_include_paths"] = cxx_header_dirs
if shared_libs:
manifest["runtime_lib_paths"] = ["lib"]
libs = []
sh_ext = get_cxx_toolchain_info(ctx).linker_info.shared_library_name_format.format("")
for soname in shared_libs:
if sh_ext in soname:
lib = soname.split(sh_ext)[0].removeprefix("lib")
libs.append("-l{}".format(lib))
manifest["libs"] = libs
return actions.write_json(output.as_output(), manifest, pretty = True)
manifest = gen_shared_libs_action(
actions = ctx.actions,
out = out + ".json",
shared_libs = shared_libs,
gen_action = gen_manifest,
)
return third_party_build_info(
actions = ctx.actions,
build = ThirdPartyBuild(
project = project,
prefix = prefix,
root = root,
manifest = manifest,
),
deps = deps,
)