From e2249f91ff84541565d8ba841592a0a8a43fcb66 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Mon, 20 Nov 2023 02:50:36 -0800 Subject: [PATCH] [7.0.0] Backport add_exports/add_opens fixes (#20260) Backport #20036, #20035, and #20037. Fixes #20258. --- .../semantics/BuildLanguageOptions.java | 16 +++ .../lib/rules/java/JavaStarlarkCommon.java | 9 ++ .../starlarkbuildapi/java/JavaCommonApi.java | 6 + .../builtins_bzl/common/java/java_import.bzl | 26 +++-- .../builtins_bzl/common/java/java_info.bzl | 34 ++++-- .../common/java/java_semantics.bzl | 4 + .../rules/java/JavaInfoStarlarkApiTest.java | 107 +++++++++++++++++- .../google/devtools/build/lib/view/java/BUILD | 1 + .../java/JavaImportConfiguredTargetTest.java | 42 +++++++ 9 files changed, 227 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java index 95dbed2aff7a4e..864200429884bf 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java +++ b/src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java @@ -584,6 +584,17 @@ public final class BuildLanguageOptions extends OptionsBase { + "host_javabase in compile will all be removed.") public boolean incompatibleJavaCommonParameters; + @Option( + name = "incompatible_java_info_merge_runtime_module_flags", + defaultValue = "false", + documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, + effectTags = {OptionEffectTag.UNKNOWN}, + metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE}, + help = + "If set to true, the JavaInfo constructor will merge add_exports and " + + "add_opens of runtime_deps in addition to deps and exports.") + public boolean incompatibleJavaInfoMergeRuntimeModuleFlags; + @Option( name = "max_computation_steps", defaultValue = "0", @@ -754,6 +765,9 @@ public StarlarkSemantics toStarlarkSemantics() { INCOMPATIBLE_FIX_PACKAGE_GROUP_REPOROOT_SYNTAX, incompatibleFixPackageGroupReporootSyntax) .setBool(INCOMPATIBLE_JAVA_COMMON_PARAMETERS, incompatibleJavaCommonParameters) + .setBool( + INCOMPATIBLE_JAVA_INFO_MERGE_RUNTIME_MODULE_FLAGS, + incompatibleJavaInfoMergeRuntimeModuleFlags) .setBool(INCOMPATIBLE_NEW_ACTIONS_API, incompatibleNewActionsApi) .setBool(INCOMPATIBLE_NO_ATTR_LICENSE, incompatibleNoAttrLicense) .setBool(INCOMPATIBLE_NO_IMPLICIT_FILE_EXPORT, incompatibleNoImplicitFileExport) @@ -861,6 +875,8 @@ public StarlarkSemantics toStarlarkSemantics() { "+incompatible_do_not_split_linking_cmdline"; public static final String INCOMPATIBLE_JAVA_COMMON_PARAMETERS = "+incompatible_java_common_parameters"; + public static final String INCOMPATIBLE_JAVA_INFO_MERGE_RUNTIME_MODULE_FLAGS = + "-incompatible_java_info_merge_runtime_module_flags"; public static final String INCOMPATIBLE_NEW_ACTIONS_API = "+incompatible_new_actions_api"; public static final String INCOMPATIBLE_NO_ATTR_LICENSE = "+incompatible_no_attr_license"; public static final String INCOMPATIBLE_NO_PACKAGE_DISTRIBS = "-incompatible_no_package_distribs"; diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java index a16547768ac11c..1fc25d99f1fb66 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java @@ -410,6 +410,15 @@ public boolean isDepsetForJavaOutputSourceJarsEnabled(StarlarkThread thread) .getBool(BuildLanguageOptions.INCOMPATIBLE_DEPSET_FOR_JAVA_OUTPUT_SOURCE_JARS); } + @Override + public boolean isJavaInfoMergeRuntimeModuleFlagsEnabled(StarlarkThread thread) + throws EvalException { + checkPrivateAccess(thread); + return thread + .getSemantics() + .getBool(BuildLanguageOptions.INCOMPATIBLE_JAVA_INFO_MERGE_RUNTIME_MODULE_FLAGS); + } + @Override public JavaInfo wrapJavaInfo(Info javaInfo, StarlarkThread thread) throws EvalException, RuleErrorException { diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java index 93829778988927..4d2e0c90f3b1d7 100644 --- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java +++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaCommonApi.java @@ -700,6 +700,12 @@ void checkJavaToolchainIsDeclaredOnRuleForStarlark( useStarlarkThread = true) boolean isDepsetForJavaOutputSourceJarsEnabled(StarlarkThread thread) throws EvalException; + @StarlarkMethod( + name = "_incompatible_java_info_merge_runtime_module_flags", + documented = false, + useStarlarkThread = true) + boolean isJavaInfoMergeRuntimeModuleFlagsEnabled(StarlarkThread thread) throws EvalException; + @StarlarkMethod( name = "wrap_java_info", parameters = {@Param(name = "java_info")}, diff --git a/src/main/starlark/builtins_bzl/common/java/java_import.bzl b/src/main/starlark/builtins_bzl/common/java/java_import.bzl index 5a2ad06d6f068c..011107d39eb4c2 100644 --- a/src/main/starlark/builtins_bzl/common/java/java_import.bzl +++ b/src/main/starlark/builtins_bzl/common/java/java_import.bzl @@ -16,14 +16,14 @@ Definition of java_import rule. """ +load(":common/cc/cc_info.bzl", "CcInfo") load(":common/java/basic_java_library.bzl", "construct_defaultinfo") -load(":common/java/java_semantics.bzl", "semantics") -load(":common/java/proguard_validation.bzl", "validate_proguard_specs") load(":common/java/import_deps_check.bzl", "import_deps_check") -load(":common/cc/cc_info.bzl", "CcInfo") -load(":common/java/java_info.bzl", "JavaInfo") load(":common/java/java_common.bzl", "java_common") load(":common/java/java_common_internal_for_builtins.bzl", _run_ijar_private_for_builtins = "run_ijar") +load(":common/java/java_info.bzl", "JavaInfo") +load(":common/java/java_semantics.bzl", "semantics") +load(":common/java/proguard_validation.bzl", "validate_proguard_specs") PackageSpecificationInfo = _builtins.toplevel.PackageSpecificationInfo @@ -78,7 +78,7 @@ def _check_empty_jars_error(ctx, jars): if len(jars) == 0 and disallow_java_import_empty_jars and not_in_allowlist: fail("empty java_import.jars is no longer supported " + ctx.label.package) -def _create_java_info_with_dummy_output_file(ctx, srcjar, all_deps, exports, runtime_deps_list, neverlink, cc_info_list): +def _create_java_info_with_dummy_output_file(ctx, srcjar, all_deps, exports, runtime_deps_list, neverlink, cc_info_list, add_exports, add_opens): dummy_jar = ctx.actions.declare_file(ctx.label.name + "_dummy.jar") dummy_src_jar = srcjar if dummy_src_jar == None: @@ -94,6 +94,8 @@ def _create_java_info_with_dummy_output_file(ctx, srcjar, all_deps, exports, run neverlink = neverlink, exports = [export[JavaInfo] for export in exports if JavaInfo in export], # Watchout, maybe you need to add them there manually. native_libraries = cc_info_list, + add_exports = add_exports, + add_opens = add_opens, ) def bazel_java_import_rule( @@ -104,7 +106,9 @@ def bazel_java_import_rule( runtime_deps = [], exports = [], neverlink = False, - proguard_specs = []): + proguard_specs = [], + add_exports = [], + add_opens = []): """Implements java_import. This rule allows the use of precompiled .jar files as libraries in other Java rules. @@ -119,6 +123,8 @@ def bazel_java_import_rule( neverlink: (bool) Whether this rule should only be used for compilation and not at runtime. constraints: (list[String]) Rule constraints. proguard_specs: (list[File]) Files to be used as Proguard specification. + add_exports: (list[str]) Allow this library to access the given /. + add_opens: (list[str]) Allow this library to reflectively access the given /. Returns: (list[provider]) A list containing DefaultInfo, JavaInfo, @@ -159,11 +165,13 @@ def bazel_java_import_rule( source_jar = srcjar, exports = [export[JavaInfo] for export in exports if JavaInfo in export], # Watchout, maybe you need to add them there manually. native_libraries = cc_info_list, + add_exports = add_exports, + add_opens = add_opens, )) java_info = java_common.merge(java_infos) else: # TODO(kotlaja): Remove next line once all java_import targets with empty jars attribute are cleaned from depot (b/246559727). - java_info = _create_java_info_with_dummy_output_file(ctx, srcjar, all_deps, exports, runtime_deps_list, neverlink, cc_info_list) + java_info = _create_java_info_with_dummy_output_file(ctx, srcjar, all_deps, exports, runtime_deps_list, neverlink, cc_info_list, add_exports, add_opens) target = {"JavaInfo": java_info} @@ -207,6 +215,8 @@ def _proxy(ctx): ctx.attr.exports, ctx.attr.neverlink, ctx.files.proguard_specs, + ctx.attr.add_exports, + ctx.attr.add_opens, ).values() _ALLOWED_RULES_IN_DEPS_FOR_JAVA_IMPORT = [ @@ -253,6 +263,8 @@ JAVA_IMPORT_ATTRS = { allow_files = True, ), # Additional attrs + "add_exports": attr.string_list(), + "add_opens": attr.string_list(), "licenses": attr.license() if hasattr(attr, "license") else attr.string_list(), "_java_toolchain_type": attr.label(default = semantics.JAVA_TOOLCHAIN_TYPE), } diff --git a/src/main/starlark/builtins_bzl/common/java/java_info.bzl b/src/main/starlark/builtins_bzl/common/java/java_info.bzl index 28623a93ee87f7..1befe6e8db7294 100644 --- a/src/main/starlark/builtins_bzl/common/java/java_info.bzl +++ b/src/main/starlark/builtins_bzl/common/java/java_info.bzl @@ -18,6 +18,7 @@ Definition of JavaInfo and JavaPluginInfo provider. load(":common/cc/cc_common.bzl", "CcNativeLibraryInfo", "cc_common") load(":common/cc/cc_info.bzl", "CcInfo") +load(":common/java/java_semantics.bzl", "semantics") # TODO(hvd): remove this when: # - we have a general provider-type checking API @@ -456,8 +457,7 @@ def java_info_for_compilation( # only differs from the usual java_info.transitive_source_jars in the order of deps transitive = [dep.transitive_source_jars for dep in concatenated_deps.runtimedeps_exports_deps], ), - # the JavaInfo constructor does not add flags from runtime_deps nor support - # adding this target's exports/opens + # the JavaInfo constructor does not add flags from runtime_deps module_flags_info = _create_module_flags_info( add_exports = depset(add_exports, transitive = [ dep.module_flags_info.add_exports @@ -663,7 +663,9 @@ def _javainfo_init( exports = [], exported_plugins = [], jdeps = None, - native_libraries = []): + native_libraries = [], + add_exports = [], + add_opens = []): """The JavaInfo constructor Args: @@ -693,10 +695,15 @@ def _javainfo_init( is typically produced by a compiler. IDEs and other tools can use this information for more efficient processing. Optional. native_libraries: ([CcInfo]) Native library dependencies that are needed for this library. + add_exports: ([str]) The /s this library was given access to. + add_opens: ([str]) The /s this library was given reflective access to. Returns: (dict) arguments to the JavaInfo provider constructor """ + if add_exports or add_opens: + semantics.check_java_info_opens_exports() + result, concatenated_deps = _javainfo_init_base( output_jar, compile_jar, @@ -723,6 +730,19 @@ def _javainfo_init( direct = [output_jar], transitive = [dep.transitive_runtime_jars for dep in concatenated_deps.exports_deps + runtime_deps], ) + + # For backward compatibility, we use deps_exports for add_exports/add_opens + # for the JavaInfo constructor rather than runtimedeps_exports_deps (used + # by java_info_for_compilation). However, runtimedeps_exports_deps makes + # more sense, since add_exports/add_opens from runtime_deps are needed at + # runtime anyway. + # + # TODO: When this flag is removed, move this logic into _javainfo_init_base + # and remove the special case from java_info_for_compilation. + module_flags_deps = concatenated_deps.deps_exports + if _java_common_internal._incompatible_java_info_merge_runtime_module_flags(): + module_flags_deps = concatenated_deps.runtimedeps_exports_deps + result.update( transitive_runtime_jars = transitive_runtime_jars, transitive_source_jars = depset( @@ -734,13 +754,13 @@ def _javainfo_init( ], ), module_flags_info = _create_module_flags_info( - add_exports = depset(transitive = [ + add_exports = depset(add_exports, transitive = [ dep.module_flags_info.add_exports - for dep in concatenated_deps.deps_exports + for dep in module_flags_deps ]), - add_opens = depset(transitive = [ + add_opens = depset(add_opens, transitive = [ dep.module_flags_info.add_opens - for dep in concatenated_deps.deps_exports + for dep in module_flags_deps ]), ), ) diff --git a/src/main/starlark/builtins_bzl/common/java/java_semantics.bzl b/src/main/starlark/builtins_bzl/common/java/java_semantics.bzl index 17f95d07bc393c..fda0c6be861404 100644 --- a/src/main/starlark/builtins_bzl/common/java/java_semantics.bzl +++ b/src/main/starlark/builtins_bzl/common/java/java_semantics.bzl @@ -40,6 +40,9 @@ def _get_default_resource_path(path, segment_extractor): def _compatible_javac_options(*_args): return depset() +def _check_java_info_opens_exports(): + pass + semantics = struct( JAVA_TOOLCHAIN_LABEL = "@bazel_tools//tools/jdk:current_java_toolchain", JAVA_TOOLCHAIN_TYPE = "@bazel_tools//tools/jdk:toolchain_type", @@ -76,4 +79,5 @@ semantics = struct( JAVA_PROTO_TOOLCHAIN = "@rules_java//java/proto:toolchain_type", JAVA_LITE_PROTO_TOOLCHAIN = "@rules_java//java/proto:lite_toolchain_type", PROGUARD_ALLOWLISTER_LABEL = "@bazel_tools//tools/jdk:proguard_whitelister", + check_java_info_opens_exports = _check_java_info_opens_exports, ) diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaInfoStarlarkApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaInfoStarlarkApiTest.java index 5e1b84da5b54aa..5ec8324e8428be 100644 --- a/src/test/java/com/google/devtools/build/lib/rules/java/JavaInfoStarlarkApiTest.java +++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaInfoStarlarkApiTest.java @@ -850,6 +850,7 @@ public void buildHelperCreateJavaInfoWithManifestProto_javaRuleOutputJarsProvide @Test public void buildHelperCreateJavaInfoWithModuleFlags() throws Exception { + setBuildLanguageOptions("--noincompatible_java_info_merge_runtime_module_flags"); ruleBuilder().build(); scratch.file( "foo/BUILD", @@ -857,20 +858,110 @@ public void buildHelperCreateJavaInfoWithModuleFlags() throws Exception { "java_library(", " name = 'my_java_lib_direct',", " srcs = ['java/A.java'],", + " add_exports = ['java.base/java.lang'],", " add_opens = ['java.base/java.lang'],", ")", + "java_library(", + " name = 'my_java_lib_runtime',", + " srcs = ['java/A.java'],", + " add_opens = ['java.base/java.util'],", + ")", + "java_library(", + " name = 'my_java_lib_exports',", + " srcs = ['java/A.java'],", + " add_opens = ['java.base/java.math'],", + ")", "my_rule(", " name = 'my_starlark_rule',", " dep = [':my_java_lib_direct'],", + " dep_runtime = [':my_java_lib_runtime'],", + " dep_exports = [':my_java_lib_exports'],", " output_jar = 'my_starlark_rule_lib.jar',", + " add_exports = ['java.base/java.lang.invoke'],", ")"); assertNoEvents(); JavaModuleFlagsProvider ruleOutputs = fetchJavaInfo().getProvider(JavaModuleFlagsProvider.class); - assertThat(ruleOutputs.toFlags()) - .containsExactly("--add-opens=java.base/java.lang=ALL-UNNAMED"); + if (analysisMock.isThisBazel()) { + assertThat(ruleOutputs.toFlags()) + .containsExactly( + "--add-exports=java.base/java.lang=ALL-UNNAMED", + "--add-exports=java.base/java.lang.invoke=ALL-UNNAMED", + // NB: no java.base/java.util as the JavaInfo constructor doesn't + // look at runtime_deps for module flags. + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.math=ALL-UNNAMED") + .inOrder(); + } else { + // add_exports/add_opens ignored in JavaInfo constructor in #newJavaInfo below + assertThat(ruleOutputs.toFlags()) + .containsExactly( + "--add-exports=java.base/java.lang=ALL-UNNAMED", + // NB: no java.base/java.util as the JavaInfo constructor doesn't + // look at runtime_deps for module flags. + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.math=ALL-UNNAMED") + .inOrder(); + } + } + + @Test + public void buildHelperCreateJavaInfoWithModuleFlagsIncompatibleMergeRuntime() throws Exception { + setBuildLanguageOptions("--incompatible_java_info_merge_runtime_module_flags"); + ruleBuilder().build(); + scratch.file( + "foo/BUILD", + "load(':extension.bzl', 'my_rule')", + "java_library(", + " name = 'my_java_lib_direct',", + " srcs = ['java/A.java'],", + " add_exports = ['java.base/java.lang'],", + " add_opens = ['java.base/java.lang'],", + ")", + "java_library(", + " name = 'my_java_lib_runtime',", + " srcs = ['java/A.java'],", + " add_opens = ['java.base/java.util'],", + ")", + "java_library(", + " name = 'my_java_lib_exports',", + " srcs = ['java/A.java'],", + " add_opens = ['java.base/java.math'],", + ")", + "my_rule(", + " name = 'my_starlark_rule',", + " dep = [':my_java_lib_direct'],", + " dep_runtime = [':my_java_lib_runtime'],", + " dep_exports = [':my_java_lib_exports'],", + " output_jar = 'my_starlark_rule_lib.jar',", + " add_exports = ['java.base/java.lang.invoke'],", + ")"); + assertNoEvents(); + + JavaModuleFlagsProvider ruleOutputs = + fetchJavaInfo().getProvider(JavaModuleFlagsProvider.class); + + if (analysisMock.isThisBazel()) { + assertThat(ruleOutputs.toFlags()) + .containsExactly( + "--add-exports=java.base/java.lang=ALL-UNNAMED", + "--add-exports=java.base/java.lang.invoke=ALL-UNNAMED", + "--add-opens=java.base/java.util=ALL-UNNAMED", + "--add-opens=java.base/java.math=ALL-UNNAMED", + "--add-opens=java.base/java.lang=ALL-UNNAMED") + .inOrder(); + } else { + // add_exports/add_opens ignored in JavaInfo constructor in #newJavaInfo below + assertThat(ruleOutputs.toFlags()) + .containsExactly( + "--add-exports=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.util=ALL-UNNAMED", + "--add-opens=java.base/java.math=ALL-UNNAMED", + "--add-opens=java.base/java.lang=ALL-UNNAMED") + .inOrder(); + } } @Test @@ -1239,8 +1330,14 @@ private String[] newJavaInfo() { " generated_source_jar = ctx.file.generated_source_jar,", " native_headers_jar = ctx.file.native_headers_jar,", " manifest_proto = ctx.file.manifest_proto,", - " native_libraries = dp_libs,", - " )", + " native_libraries = dp_libs,"); + if (analysisMock.isThisBazel()) { + lines.add( + " add_exports = ctx.attr.add_exports,", // + " add_opens = ctx.attr.add_opens,"); + } + lines.add( + " )", // " return [result(property = javaInfo)]"); return lines.build().toArray(new String[] {}); } @@ -1271,6 +1368,8 @@ private void build() throws Exception { " 'generated_source_jar' : attr.label(allow_single_file=True),", " 'native_headers_jar' : attr.label(allow_single_file=True),", " 'manifest_proto' : attr.label(allow_single_file=True),", + " 'add_exports' : attr.string_list(),", + " 'add_opens' : attr.string_list(),", useIJar || stampJar || sourceFiles ? " '_toolchain': attr.label(default = Label('//java/com/google/test:toolchain'))," : "", diff --git a/src/test/java/com/google/devtools/build/lib/view/java/BUILD b/src/test/java/com/google/devtools/build/lib/view/java/BUILD index 529965dee744cf..cc4663c91c0a08 100644 --- a/src/test/java/com/google/devtools/build/lib/view/java/BUILD +++ b/src/test/java/com/google/devtools/build/lib/view/java/BUILD @@ -79,6 +79,7 @@ java_test( "//src/main/java/com/google/devtools/build/lib/collect/nestedset", "//src/main/java/com/google/devtools/build/lib/rules/java:java-compilation", "//src/main/java/com/google/devtools/build/lib/rules/java:java-rules", + "//src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java", "//src/test/java/com/google/devtools/build/lib/actions/util", "//src/test/java/com/google/devtools/build/lib/analysis/util", "//src/test/java/com/google/devtools/build/lib/rules/java:java_compile_action_test_helper", diff --git a/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java index 1ee6e20c389161..4c61412c221e75 100644 --- a/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java +++ b/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java @@ -38,6 +38,7 @@ import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider; import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider; import com.google.devtools.build.lib.rules.java.ProguardSpecProvider; +import com.google.devtools.build.lib.starlarkbuildapi.java.JavaModuleFlagsProviderApi; import com.google.devtools.build.lib.testutil.MoreAsserts; import java.util.Arrays; import java.util.List; @@ -220,6 +221,47 @@ public void testDeps() throws Exception { "java/jarlib2/depjar.jar"); } + @Test + public void testModuleFlags() throws Exception { + if (!analysisMock.isThisBazel()) { + return; + } + + scratch.file( + "java/jarlib2/BUILD", + "java_library(name = 'lib',", + " srcs = ['Main.java'],", + " deps = [':import-jar'])", + "java_import(name = 'import-jar',", + " jars = ['import.jar'],", + " deps = ['//java/jarlib2:depjar'],", + " exports = ['//java/jarlib2:exportjar'],", + ")", + "java_import(name = 'depjar',", + " jars = ['depjar.jar'],", + " add_exports = ['java.base/java.lang'])", + "java_import(name = 'exportjar',", + " jars = ['exportjar.jar'],", + " add_opens = ['java.base/java.util'])"); + + ConfiguredTarget importJar = getConfiguredTarget("//java/jarlib2:import-jar"); + JavaModuleFlagsProviderApi moduleFlagsProvider = + JavaInfo.getJavaInfo(importJar).getJavaModuleFlagsInfo(); + assertThat(moduleFlagsProvider.getAddExports().toList(String.class)) + .containsExactly("java.base/java.lang"); + assertThat(moduleFlagsProvider.getAddOpens().toList(String.class)) + .containsExactly("java.base/java.util"); + + // Check that module flags propagate to Java libraries properly. + ConfiguredTarget lib = getConfiguredTarget("//java/jarlib2:lib"); + JavaModuleFlagsProviderApi libModuleFlagsProvider = + JavaInfo.getJavaInfo(lib).getJavaModuleFlagsInfo(); + assertThat(libModuleFlagsProvider.getAddExports().toList(String.class)) + .containsExactly("java.base/java.lang"); + assertThat(libModuleFlagsProvider.getAddOpens().toList(String.class)) + .containsExactly("java.base/java.util"); + } + @Test public void testSrcJars() throws Exception { ConfiguredTarget jarLibWithSources =