Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / bazel / grpc_build_system.bzl
1 # Copyright 2016 gRPC authors.
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
15 #
16 # This is for the gRPC build system. This isn't intended to be used outsite of
17 # the BUILD file for gRPC. It contains the mapping for the template system we
18 # use to generate other platform's build system files.
19 #
20 # Please consider that there should be a high bar for additions and changes to
21 # this file.
22 # Each rule listed must be re-written for Google's internal build system, and
23 # each change must be ported from one to the other.
24 #
25
26 load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
27 load("//bazel:copts.bzl", "GRPC_DEFAULT_COPTS")
28 load("@upb//bazel:upb_proto_library.bzl", "upb_proto_library")
29 load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
30
31 # The set of pollers to test against if a test exercises polling
32 POLLERS = ["epollex", "epoll1", "poll"]
33
34 def if_not_windows(a):
35     return select({
36         "//:windows": [],
37         "//:windows_msvc": [],
38         "//conditions:default": a,
39     })
40
41 def if_mac(a):
42     return select({
43         "//:mac_x86_64": a,
44         "//conditions:default": [],
45     })
46
47 def _get_external_deps(external_deps):
48     ret = []
49     for dep in external_deps:
50         if dep == "address_sorting":
51             ret += ["//third_party/address_sorting"]
52         elif dep == "xxhash":
53             ret += ["//third_party/xxhash"]
54         elif dep == "cares":
55             ret += select({
56                 "//:grpc_no_ares": [],
57                 "//conditions:default": ["//external:cares"],
58             })
59         elif dep == "cronet_c_for_grpc":
60             ret += ["//third_party/objective_c/Cronet:cronet_c_for_grpc"]
61         elif dep.startswith("absl/"):
62             ret += ["@com_google_absl//" + dep]
63         else:
64             ret += ["//external:" + dep]
65     return ret
66
67 def _update_visibility(visibility):
68     if visibility == None:
69         return None
70
71     # Visibility rules prefixed with '@grpc_' are used to flag different visibility rule
72     # classes upstream.
73     PUBLIC = ["//visibility:public"]
74     PRIVATE = ["//:__subpackages__"]
75     VISIBILITY_TARGETS = {
76         "alt_gpr_base_legacy": PRIVATE,
77         "alt_grpc++_base_legacy": PRIVATE,
78         "alt_grpc_base_legacy": PRIVATE,
79         "alt_grpc++_base_unsecure_legacy": PRIVATE,
80         "alts_frame_protector": PRIVATE,
81         "channelz": PRIVATE,
82         "client_channel": PRIVATE,
83         "debug_location": PRIVATE,
84         "endpoint_tests": PRIVATE,
85         "grpclb": PRIVATE,
86         "grpc_opencensus_plugin": PUBLIC,
87         "grpc_resolver_fake": PRIVATE,
88         "grpc++_test": PRIVATE,
89         "public": PUBLIC,
90         "ref_counted_ptr": PRIVATE,
91         "trace": PRIVATE,
92         "tsi_interface": PRIVATE,
93         "tsi": PRIVATE,
94         "xds": PRIVATE,
95     }
96     final_visibility = []
97     for rule in visibility:
98         if rule.startswith("@grpc:"):
99             for replacement in VISIBILITY_TARGETS[rule[len("@grpc:"):]]:
100                 final_visibility.append(replacement)
101         else:
102             final_visibility.append(rule)
103     return [x for x in final_visibility]
104
105 def grpc_cc_library(
106         name,
107         srcs = [],
108         public_hdrs = [],
109         hdrs = [],
110         external_deps = [],
111         defines = [],
112         deps = [],
113         select_deps = None,
114         standalone = False,
115         language = "C++",
116         testonly = False,
117         visibility = None,
118         alwayslink = 0,
119         data = [],
120         use_cfstream = False,
121         tags = [],
122         linkstatic = False):
123     visibility = _update_visibility(visibility)
124     copts = []
125     if use_cfstream:
126         copts = if_mac(["-DGRPC_CFSTREAM"])
127     if language.upper() == "C":
128         copts = copts + if_not_windows(["-std=c99"])
129     linkopts = if_not_windows(["-pthread"])
130     if use_cfstream:
131         linkopts = linkopts + if_mac(["-framework CoreFoundation"])
132
133     if select_deps:
134         deps += select(select_deps)
135
136     native.cc_library(
137         name = name,
138         srcs = srcs,
139         defines = defines +
140                   select({
141                       "//:grpc_no_ares": ["GRPC_ARES=0"],
142                       "//conditions:default": [],
143                   }) +
144                   select({
145                       "//:remote_execution": ["GRPC_PORT_ISOLATED_RUNTIME=1"],
146                       "//conditions:default": [],
147                   }) +
148                   select({
149                       "//:grpc_allow_exceptions": ["GRPC_ALLOW_EXCEPTIONS=1"],
150                       "//:grpc_disallow_exceptions": ["GRPC_ALLOW_EXCEPTIONS=0"],
151                       "//conditions:default": [],
152                   }),
153         hdrs = hdrs + public_hdrs,
154         deps = deps + _get_external_deps(external_deps),
155         copts = GRPC_DEFAULT_COPTS + copts,
156         visibility = visibility,
157         testonly = testonly,
158         linkopts = linkopts,
159         includes = [
160             "include",
161             "src/core/ext/upb-generated",  # Once upb code-gen issue is resolved, remove this.
162             "src/core/ext/upbdefs-generated",  # Once upb code-gen issue is resolved, remove this.
163         ],
164         alwayslink = alwayslink,
165         data = data,
166         tags = tags,
167         linkstatic = linkstatic,
168     )
169
170 def grpc_proto_plugin(name, srcs = [], deps = []):
171     native.cc_binary(
172         name = name,
173         srcs = srcs,
174         deps = deps,
175     )
176
177 def grpc_proto_library(
178         name,
179         srcs = [],
180         deps = [],
181         well_known_protos = False,
182         has_services = True,
183         use_external = False,
184         generate_mocks = False):
185     cc_grpc_library(
186         name = name,
187         srcs = srcs,
188         deps = deps,
189         well_known_protos = well_known_protos,
190         proto_only = not has_services,
191         use_external = use_external,
192         generate_mocks = generate_mocks,
193     )
194
195 def ios_cc_test(
196         name,
197         tags = [],
198         **kwargs):
199     ios_test_adapter = "//third_party/objective_c/google_toolbox_for_mac:GTM_GoogleTestRunner_GTM_USING_XCTEST"
200
201     test_lib_ios = name + "_test_lib_ios"
202     ios_tags = tags + ["manual", "ios_cc_test"]
203     if not any([t for t in tags if t.startswith("no_test_ios")]):
204         native.objc_library(
205             name = test_lib_ios,
206             srcs = kwargs.get("srcs"),
207             deps = kwargs.get("deps"),
208             copts = kwargs.get("copts"),
209             tags = ios_tags,
210             alwayslink = 1,
211             testonly = 1,
212         )
213         ios_test_deps = [ios_test_adapter, ":" + test_lib_ios]
214         ios_unit_test(
215             name = name + "_on_ios",
216             size = kwargs.get("size"),
217             tags = ios_tags,
218             minimum_os_version = "9.0",
219             deps = ios_test_deps,
220         )
221
222 def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = None, tags = [], exec_compatible_with = [], exec_properties = {}, shard_count = None, flaky = None, copts = []):
223     copts = copts + if_mac(["-DGRPC_CFSTREAM"])
224     if language.upper() == "C":
225         copts = copts + if_not_windows(["-std=c99"])
226
227     # NOTE: these attributes won't be used for the poller-specific versions of a test
228     # automatically, you need to set them explicitly (if applicable)
229     args = {
230         "srcs": srcs,
231         "args": args,
232         "data": data,
233         "deps": deps + _get_external_deps(external_deps),
234         "copts": GRPC_DEFAULT_COPTS + copts,
235         "linkopts": if_not_windows(["-pthread"]),
236         "size": size,
237         "timeout": timeout,
238         "exec_compatible_with": exec_compatible_with,
239         "exec_properties": exec_properties,
240         "shard_count": shard_count,
241         "flaky": flaky,
242     }
243     if uses_polling:
244         # the vanilla version of the test should run on platforms that only
245         # support a single poller
246         native.cc_test(
247             name = name,
248             testonly = True,
249             tags = (tags + [
250                 "no_linux",  # linux supports multiple pollers
251             ]),
252             **args
253         )
254
255         # on linux we run the same test multiple times, once for each poller
256         for poller in POLLERS:
257             native.sh_test(
258                 name = name + "@poller=" + poller,
259                 data = [name] + data,
260                 srcs = [
261                     "//test/core/util:run_with_poller_sh",
262                 ],
263                 size = size,
264                 timeout = timeout,
265                 args = [
266                     poller,
267                     "$(location %s)" % name,
268                 ] + args["args"],
269                 tags = (tags + ["no_windows", "no_mac"]),
270                 exec_compatible_with = exec_compatible_with,
271                 exec_properties = exec_properties,
272                 shard_count = shard_count,
273                 flaky = flaky,
274             )
275     else:
276         # the test behavior doesn't depend on polling, just generate the test
277         native.cc_test(name = name, tags = tags + ["no_uses_polling"], **args)
278     ios_cc_test(
279         name = name,
280         tags = tags,
281         **args
282     )
283
284 def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False, linkopts = [], tags = [], features = []):
285     copts = []
286     if language.upper() == "C":
287         copts = ["-std=c99"]
288     native.cc_binary(
289         name = name,
290         srcs = srcs,
291         args = args,
292         data = data,
293         testonly = testonly,
294         linkshared = linkshared,
295         deps = deps + _get_external_deps(external_deps),
296         copts = GRPC_DEFAULT_COPTS + copts,
297         linkopts = if_not_windows(["-pthread"]) + linkopts,
298         tags = tags,
299         features = features,
300     )
301
302 def grpc_generate_one_off_targets():
303     # In open-source, grpc_objc* libraries depend directly on //:grpc
304     native.alias(
305         name = "grpc_objc",
306         actual = "//:grpc",
307     )
308
309 def grpc_generate_objc_one_off_targets():
310     pass
311
312 def grpc_sh_test(name, srcs, args = [], data = []):
313     native.sh_test(
314         name = name,
315         srcs = srcs,
316         args = args,
317         data = data,
318     )
319
320 def grpc_sh_binary(name, srcs, data = []):
321     native.sh_binary(
322         name = name,
323         srcs = srcs,
324         data = data,
325     )
326
327 def grpc_py_binary(
328         name,
329         srcs,
330         data = [],
331         deps = [],
332         external_deps = [],
333         testonly = False,
334         python_version = "PY2",
335         **kwargs):
336     native.py_binary(
337         name = name,
338         srcs = srcs,
339         testonly = testonly,
340         data = data,
341         deps = deps + _get_external_deps(external_deps),
342         python_version = python_version,
343         **kwargs
344     )
345
346 def grpc_package(name, visibility = "private", features = []):
347     if visibility == "tests":
348         visibility = ["//test:__subpackages__"]
349     elif visibility == "public":
350         visibility = ["//visibility:public"]
351     elif visibility == "private":
352         visibility = []
353     else:
354         fail("Unknown visibility " + visibility)
355
356     if len(visibility) != 0:
357         native.package(
358             default_visibility = visibility,
359             features = features,
360         )
361
362 def grpc_objc_library(
363         name,
364         srcs = [],
365         hdrs = [],
366         textual_hdrs = [],
367         data = [],
368         deps = [],
369         defines = [],
370         includes = [],
371         visibility = ["//visibility:public"]):
372     """The grpc version of objc_library, only used for the Objective-C library compilation
373
374     Args:
375         name: name of target
376         hdrs: public headers
377         srcs: all source files (.m)
378         textual_hdrs: private headers
379         data: any other bundle resources
380         defines: preprocessors
381         includes: added to search path, always [the path to objc directory]
382         deps: dependencies
383         visibility: visibility, default to public
384     """
385
386     native.objc_library(
387         name = name,
388         hdrs = hdrs,
389         srcs = srcs,
390         textual_hdrs = textual_hdrs,
391         data = data,
392         deps = deps,
393         defines = defines,
394         includes = includes,
395         visibility = visibility,
396     )
397
398 def grpc_upb_proto_library(name, deps):
399     upb_proto_library(name = name, deps = deps)
400
401 def python_config_settings():
402     native.config_setting(
403         name = "python3",
404         flag_values = {"@bazel_tools//tools/python:python_version": "PY3"},
405     )