Imported Upstream version 1.24.3
[platform/upstream/grpc.git] / third_party / upb / bazel / build_defs.bzl
1 """Internal rules for building upb."""
2
3 load(":upb_proto_library.bzl", "GeneratedSrcsInfo")
4
5 def _librule(name):
6     return name + "_lib"
7
8 def _get_real_short_path(file):
9     # For some reason, files from other archives have short paths that look like:
10     #   ../com_google_protobuf/google/protobuf/descriptor.proto
11     short_path = file.short_path
12     if short_path.startswith("../"):
13         second_slash = short_path.index("/", 3)
14         short_path = short_path[second_slash + 1:]
15     return short_path
16
17 def _get_real_root(file):
18     real_short_path = _get_real_short_path(file)
19     return file.path[:-len(real_short_path) - 1]
20
21 def _get_real_roots(files):
22     roots = {}
23     for file in files:
24         real_root = _get_real_root(file)
25         if real_root:
26             roots[real_root] = True
27     return roots.keys()
28
29 def lua_cclibrary(name, srcs, hdrs = [], deps = [], luadeps = []):
30     lib_rule = name + "_lib"
31     so_rule = "lib" + name + ".so"
32     so_file = _remove_prefix(name, "lua/") + ".so"
33
34     native.cc_library(
35         name = _librule(name),
36         hdrs = hdrs,
37         srcs = srcs,
38         deps = deps + [_librule(dep) for dep in luadeps] + ["@lua//:liblua_headers"],
39     )
40
41     native.cc_binary(
42         name = so_rule,
43         linkshared = True,
44         deps = [_librule(name)],
45         linkopts = select({
46             ":darwin": [
47                 "-undefined dynamic_lookup",
48             ],
49             "//conditions:default": [],
50         }),
51     )
52
53     native.genrule(
54         name = name + "_copy",
55         srcs = [":" + so_rule],
56         outs = [so_file],
57         cmd = "cp $< $@",
58     )
59
60     native.filegroup(
61         name = name,
62         data = [so_file],
63     )
64
65 def _remove_prefix(str, prefix):
66     if not str.startswith(prefix):
67         fail("%s doesn't start with %s" % (str, prefix))
68     return str[len(prefix):]
69
70 def _remove_suffix(str, suffix):
71     if not str.endswith(suffix):
72         fail("%s doesn't end with %s" % (str, suffix))
73     return str[:-len(suffix)]
74
75 def lua_library(name, srcs, strip_prefix, luadeps = []):
76     outs = [_remove_prefix(src, strip_prefix + "/") for src in srcs]
77     native.genrule(
78         name = name + "_copy",
79         srcs = srcs,
80         outs = outs,
81         cmd = "cp $(SRCS) $(@D)",
82     )
83
84     native.filegroup(
85         name = name,
86         data = outs + luadeps,
87     )
88
89 def make_shell_script(name, contents, out):
90     contents = contents.replace("$", "$$")
91     native.genrule(
92         name = "gen_" + name,
93         outs = [out],
94         cmd = "(cat <<'HEREDOC'\n%s\nHEREDOC\n) > $@" % contents,
95     )
96
97 def _lua_binary_or_test(name, luamain, luadeps, rule):
98     script = name + ".sh"
99
100     make_shell_script(
101         name = "gen_" + name,
102         out = script,
103         contents = """
104 BASE=$(dirname $(rlocation upb/upb_c.so))
105 export LUA_CPATH="$BASE/?.so"
106 export LUA_PATH="$BASE/?.lua"
107 $(rlocation lua/lua) $(rlocation upb/tools/upbc.lua) "$@"
108 """,
109     )
110
111     rule(
112         name = name,
113         srcs = [script],
114         data = ["@lua//:lua", luamain] + luadeps,
115     )
116
117 def lua_binary(name, luamain, luadeps = []):
118     _lua_binary_or_test(name, luamain, luadeps, native.sh_binary)
119
120 def lua_test(name, luamain, luadeps = []):
121     _lua_binary_or_test(name, luamain, luadeps, native.sh_test)
122
123 def generated_file_staleness_test(name, outs, generated_pattern):
124     """Tests that checked-in file(s) match the contents of generated file(s).
125
126     The resulting test will verify that all output files exist and have the
127     correct contents.  If the test fails, it can be invoked with --fix to
128     bring the checked-in files up to date.
129
130     Args:
131       name: Name of the rule.
132       outs: the checked-in files that are copied from generated files.
133       generated_pattern: the pattern for transforming each "out" file into a
134         generated file.  For example, if generated_pattern="generated/%s" then
135         a file foo.txt will look for generated file generated/foo.txt.
136     """
137
138     script_name = name + ".py"
139     script_src = "//:tools/staleness_test.py"
140
141     # Filter out non-existing rules so Blaze doesn't error out before we even
142     # run the test.
143     existing_outs = native.glob(include = outs)
144
145     # The file list contains a few extra bits of information at the end.
146     # These get unpacked by the Config class in staleness_test_lib.py.
147     file_list = outs + [generated_pattern, native.package_name() or ".", name]
148
149     native.genrule(
150         name = name + "_makescript",
151         outs = [script_name],
152         srcs = [script_src],
153         testonly = 1,
154         cmd = "cat $(location " + script_src + ") > $@; " +
155               "sed -i.bak -e 's|INSERT_FILE_LIST_HERE|" + "\\\n  ".join(file_list) + "|' $@",
156     )
157
158     native.py_test(
159         name = name,
160         srcs = [script_name],
161         data = existing_outs + [generated_pattern % file for file in outs],
162         deps = [
163             "//:staleness_test_lib",
164         ],
165     )
166
167 # upb_amalgamation() rule, with file_list aspect.
168
169 SrcList = provider(
170     fields = {
171         "srcs": "list of srcs",
172     },
173 )
174
175 def _file_list_aspect_impl(target, ctx):
176     if GeneratedSrcsInfo in target:
177         srcs = target[GeneratedSrcsInfo]
178         return [SrcList(srcs = srcs.srcs + srcs.hdrs)]
179
180     srcs = []
181     for src in ctx.rule.attr.srcs:
182         srcs += src.files.to_list()
183     for hdr in ctx.rule.attr.hdrs:
184         srcs += hdr.files.to_list()
185     for hdr in ctx.rule.attr.textual_hdrs:
186         srcs += hdr.files.to_list()
187     return [SrcList(srcs = srcs)]
188
189 _file_list_aspect = aspect(
190     implementation = _file_list_aspect_impl,
191 )
192
193 def _upb_amalgamation(ctx):
194     inputs = []
195     for lib in ctx.attr.libs:
196         inputs += lib[SrcList].srcs
197     srcs = [src for src in inputs if src.path.endswith("c")]
198     ctx.actions.run(
199         inputs = inputs,
200         outputs = ctx.outputs.outs,
201         arguments = [ctx.bin_dir.path + "/"] + [f.path for f in srcs] + ["-I" + root for root in _get_real_roots(inputs)],
202         progress_message = "Making amalgamation",
203         executable = ctx.executable.amalgamator,
204     )
205     return []
206
207 upb_amalgamation = rule(
208     attrs = {
209         "amalgamator": attr.label(
210             executable = True,
211             cfg = "host",
212         ),
213         "libs": attr.label_list(aspects = [_file_list_aspect]),
214         "outs": attr.output_list(),
215     },
216     implementation = _upb_amalgamation,
217 )
218
219 def licenses(*args):
220     # No-op (for Google-internal usage).
221     pass