16
16
Common code for reuse across java_* rules
17
17
"""
18
18
19
+ load ("@rules_cc//cc:find_cc_toolchain.bzl" , "CC_TOOLCHAIN_TYPE" , "find_cc_toolchain" )
20
+ load ("@rules_cc//cc/common:cc_common.bzl" , "cc_common" )
19
21
load ("@rules_cc//cc/common:cc_info.bzl" , "CcInfo" )
22
+ load ("//java/common:java_semantics.bzl" , "semantics" )
20
23
load ("//java/common/rules:android_lint.bzl" , "android_lint_subrule" )
21
24
load ("//java/private:boot_class_path_info.bzl" , "BootClassPathInfo" )
22
25
load ("//java/private:java_common_internal.bzl" , "target_kind" )
@@ -124,6 +127,7 @@ def basic_java_library(
124
127
resources = list (resources )
125
128
resources .extend (properties )
126
129
130
+ native_libraries = _collect_native_libraries (deps , runtime_deps , exports )
127
131
java_info , compilation_info = compile_action (
128
132
ctx ,
129
133
ctx .outputs .classjar ,
@@ -138,7 +142,7 @@ def basic_java_library(
138
142
resources ,
139
143
resource_jars ,
140
144
classpath_resources ,
141
- _collect_native_libraries ( deps , runtime_deps , exports ) ,
145
+ native_libraries ,
142
146
javacopts ,
143
147
neverlink ,
144
148
ctx .fragments .java .strict_java_deps ,
@@ -150,6 +154,25 @@ def basic_java_library(
150
154
)
151
155
target = {"JavaInfo" : java_info }
152
156
157
+ if native_libraries :
158
+ native_header_cc_info = _make_native_header_cc_info (ctx , java_info )
159
+ dependencies_cc_info = cc_common .merge_cc_infos (cc_infos = native_libraries )
160
+
161
+ target ["CcInfo" ] = cc_common .merge_cc_infos (
162
+ cc_infos = [
163
+ native_header_cc_info ,
164
+ # Native dependencies have the same semantics as
165
+ # `cc_library#implementation_deps`. We only want to propagate
166
+ # `Cc{Debug,Linking}Context` to libraries depending on this.
167
+ CcInfo (
168
+ linking_context = dependencies_cc_info .linking_context ,
169
+ debug_context = dependencies_cc_info .debug_context (),
170
+ ),
171
+ ],
172
+ )
173
+ else :
174
+ target ["CcInfo" ] = _make_native_header_cc_info (ctx , java_info )
175
+
153
176
output_groups = dict (
154
177
compilation_outputs = compilation_info .files_to_build ,
155
178
_source_jars = java_info .transitive_source_jars ,
@@ -234,6 +257,82 @@ def _collect_native_libraries(*attrs):
234
257
"""
235
258
return _filter_provider (CcInfo , * attrs )
236
259
260
+ def _make_native_header_cc_info (ctx , java_info ):
261
+ """Creates a `CcInfo` for compiling and linking against generated headers.
262
+
263
+ Use this call to generate a single header from the `-native.jar` and wrap it
264
+ in `CcInfo` for consumers.
265
+
266
+ Args:
267
+ ctx: (RuleContext) The rule context of the caller.
268
+ java_info: (JavaInfo) The `JavaInfo` provider to extract headers from.
269
+ Returns:
270
+ (CcInfo): The `CcInfo` provider for compiling and linking against
271
+ generated headers.
272
+ """
273
+
274
+ # 1. Check if there's jar with native headers.
275
+ native_headers_jar = java_info .outputs .native_headers
276
+ if not native_headers_jar :
277
+ # There's no jar with native headers. Simply return an empty provider so
278
+ # we have a well-defined API.
279
+ return CcInfo ()
280
+
281
+ # 2. Check if there's a `cc_toolchain` available.
282
+ if CC_TOOLCHAIN_TYPE in ctx .toolchains :
283
+ cc_toolchain = find_cc_toolchain (ctx , mandatory = False )
284
+ else :
285
+ # Work around a bug in `find_cc_toolchain()` which requires a rule to
286
+ # declare an (optional) dependency on the Cc toolchain even if
287
+ # `mandatory = False`.
288
+ cc_toolchain = None
289
+ if not cc_toolchain :
290
+ # No `cc_toolchain` available, so there's no way for users to build
291
+ # native dependencies. Simply return an empty provider so we have a
292
+ # well-defined API.
293
+ return CcInfo ()
294
+
295
+ # 3. Get tool to generate header from jar.
296
+ java_toolchain = semantics .find_java_toolchain (ctx )
297
+ if not java_toolchain .native_header_generator :
298
+ # We don't have a tool to generate the combined header. Simply return an
299
+ # empty provider so we have a well-defined API.
300
+ return CcInfo ()
301
+
302
+ args = ctx .actions .args ()
303
+ args .add ("--jar" , native_headers_jar )
304
+
305
+ native_header = ctx .actions .declare_file ("{}.native.h" .format (ctx .attr .name ))
306
+ args .add ("--output" , native_header )
307
+
308
+ ctx .actions .run (
309
+ executable = java_toolchain .native_header_generator ,
310
+ outputs = [
311
+ native_header ,
312
+ ],
313
+ inputs = [
314
+ native_headers_jar ,
315
+ ],
316
+ mnemonic = "JavaNativeHeader" ,
317
+ progress_message = "Generating native header for %{label}" ,
318
+ toolchain = semantics .JAVA_TOOLCHAIN_TYPE ,
319
+ arguments = [
320
+ args ,
321
+ ],
322
+ )
323
+
324
+ # TODO(yannic): Add `CcCompilationContext` for `jni.h`.
325
+ compilation_context = cc_common .create_compilation_context (
326
+ headers = depset (
327
+ direct = [
328
+ native_header ,
329
+ ],
330
+ ),
331
+ )
332
+ return CcInfo (
333
+ compilation_context = compilation_context ,
334
+ )
335
+
237
336
def construct_defaultinfo (ctx , files_to_build , files , neverlink , * extra_attrs ):
238
337
"""Constructs DefaultInfo for Java library like rule.
239
338
0 commit comments