1616Common code for reuse across java_* rules
1717"""
1818
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" )
1921load ("@rules_cc//cc/common:cc_info.bzl" , "CcInfo" )
22+ load ("//java/common:java_semantics.bzl" , "semantics" )
2023load ("//java/common/rules:android_lint.bzl" , "android_lint_subrule" )
2124load ("//java/private:boot_class_path_info.bzl" , "BootClassPathInfo" )
2225load ("//java/private:java_common_internal.bzl" , "target_kind" )
@@ -124,6 +127,7 @@ def basic_java_library(
124127 resources = list (resources )
125128 resources .extend (properties )
126129
130+ native_libraries = _collect_native_libraries (deps , runtime_deps , exports )
127131 java_info , compilation_info = compile_action (
128132 ctx ,
129133 ctx .outputs .classjar ,
@@ -138,7 +142,7 @@ def basic_java_library(
138142 resources ,
139143 resource_jars ,
140144 classpath_resources ,
141- _collect_native_libraries ( deps , runtime_deps , exports ) ,
145+ native_libraries ,
142146 javacopts ,
143147 neverlink ,
144148 ctx .fragments .java .strict_java_deps ,
@@ -150,6 +154,25 @@ def basic_java_library(
150154 )
151155 target = {"JavaInfo" : java_info }
152156
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+
153176 output_groups = dict (
154177 compilation_outputs = compilation_info .files_to_build ,
155178 _source_jars = java_info .transitive_source_jars ,
@@ -234,6 +257,82 @@ def _collect_native_libraries(*attrs):
234257 """
235258 return _filter_provider (CcInfo , * attrs )
236259
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+
237336def construct_defaultinfo (ctx , files_to_build , files , neverlink , * extra_attrs ):
238337 """Constructs DefaultInfo for Java library like rule.
239338
0 commit comments