# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Implementation of java_binary for bazel """ load("@bazel_skylib//lib:paths.bzl", "paths") load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") load("//java/common:java_semantics.bzl", "semantics") load("//java/private:java_common.bzl", "java_common") load("//java/private:java_info.bzl", "JavaInfo", "JavaPluginInfo") load("//java/private:native.bzl", "get_internal_java_common") load(":basic_java_library.bzl", "BASIC_JAVA_LIBRARY_IMPLICIT_ATTRS") load(":rule_util.bzl", "merge_attrs") # copybara: default visibility BootClassPathInfo = java_common.BootClassPathInfo _PLATFORMS_ROOT = semantics.PLATFORMS_ROOT BASIC_JAVA_BINARY_ATTRIBUTES = merge_attrs( BASIC_JAVA_LIBRARY_IMPLICIT_ATTRS, # buildifier: disable=attr-licenses { "srcs": attr.label_list( allow_files = [".java", ".srcjar", ".properties"] + semantics.EXTRA_SRCS_TYPES, flags = ["DIRECT_COMPILE_TIME_INPUT", "ORDER_INDEPENDENT"], doc = """ The list of source files that are processed to create the target. This attribute is almost always required; see exceptions below.

Source files of type .java are compiled. In case of generated .java files it is generally advisable to put the generating rule's name here instead of the name of the file itself. This not only improves readability but makes the rule more resilient to future changes: if the generating rule generates different files in the future, you only need to fix one place: the outs of the generating rule. You should not list the generating rule in deps because it is a no-op.

Source files of type .srcjar are unpacked and compiled. (This is useful if you need to generate a set of .java files with a genrule.)

Rules: if the rule (typically genrule or filegroup) generates any of the files listed above, they will be used the same way as described for source files.

This argument is almost always required, except if a main_class attribute specifies a class on the runtime classpath or you specify the runtime_deps argument.

""", ), "deps": attr.label_list( allow_files = [".jar"], allow_rules = semantics.ALLOWED_RULES_IN_DEPS + semantics.ALLOWED_RULES_IN_DEPS_WITH_WARNING, providers = [ [CcInfo], [JavaInfo], ], flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"], doc = """ The list of other libraries to be linked in to the target. See general comments about deps at Typical attributes defined by most build rules. """, ), "resources": attr.label_list( allow_files = True, flags = ["SKIP_CONSTRAINTS_OVERRIDE", "ORDER_INDEPENDENT"], doc = """ A list of data files to include in a Java jar.

Resources may be source files or generated files.

""" + semantics.DOCS.for_attribute("resources"), ), "runtime_deps": attr.label_list( allow_files = [".jar"], allow_rules = semantics.ALLOWED_RULES_IN_DEPS, providers = [[CcInfo], [JavaInfo]], flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"], doc = """ Libraries to make available to the final binary or test at runtime only. Like ordinary deps, these will appear on the runtime classpath, but unlike them, not on the compile-time classpath. Dependencies needed only at runtime should be listed here. Dependency-analysis tools should ignore targets that appear in both runtime_deps and deps. """, ), "data": attr.label_list( allow_files = True, flags = ["SKIP_CONSTRAINTS_OVERRIDE"], doc = """ The list of files needed by this library at runtime. See general comments about data at Typical attributes defined by most build rules. """ + semantics.DOCS.for_attribute("data"), ), "plugins": attr.label_list( providers = [JavaPluginInfo], allow_files = True, cfg = "exec", doc = """ Java compiler plugins to run at compile-time. Every java_plugin specified in this attribute will be run whenever this rule is built. A library may also inherit plugins from dependencies that use exported_plugins. Resources generated by the plugin will be included in the resulting jar of this rule. """, ), "deploy_env": attr.label_list( providers = [java_common.JavaRuntimeClasspathInfo], allow_files = False, doc = """ A list of other java_binary targets which represent the deployment environment for this binary. Set this attribute when building a plugin which will be loaded by another java_binary.
Setting this attribute excludes all dependencies from the runtime classpath (and the deploy jar) of this binary that are shared between this binary and the targets specified in deploy_env. """, ), "launcher": attr.label( # TODO(b/295221112): add back CcLauncherInfo allow_files = False, doc = """ Specify a binary that will be used to run your Java program instead of the normal bin/java program included with the JDK. The target must be a cc_binary. Any cc_binary that implements the Java Invocation API can be specified as a value for this attribute.

By default, Bazel will use the normal JDK launcher (bin/java or java.exe).

The related --java_launcher Bazel flag affects only those java_binary and java_test targets that have not specified a launcher attribute.

Note that your native (C++, SWIG, JNI) dependencies will be built differently depending on whether you are using the JDK launcher or another launcher:

When using any launcher other than the default JDK launcher, the format of the *_deploy.jar output changes. See the main java_binary docs for details.

""", ), "bootclasspath": attr.label( providers = [BootClassPathInfo], flags = ["SKIP_CONSTRAINTS_OVERRIDE"], doc = "Restricted API, do not use!", ), "neverlink": attr.bool(), "javacopts": attr.string_list( doc = """ Extra compiler options for this binary. Subject to "Make variable" substitution and Bourne shell tokenization.

These compiler options are passed to javac after the global compiler options.

""", ), "add_exports": attr.string_list( doc = """ Allow this library to access the given module or package.

This corresponds to the javac and JVM --add-exports= flags. """, ), "add_opens": attr.string_list( doc = """ Allow this library to reflectively access the given module or package.

This corresponds to the javac and JVM --add-opens= flags. """, ), "main_class": attr.string( doc = """ Name of class with main() method to use as entry point. If a rule uses this option, it does not need a srcs=[...] list. Thus, with this attribute one can make an executable from a Java library that already contains one or more main() methods.

The value of this attribute is a class name, not a source file. The class must be available at runtime: it may be compiled by this rule (from srcs) or provided by direct or transitive dependencies (through runtime_deps or deps). If the class is unavailable, the binary will fail at runtime; there is no build-time check.

""", ), "jvm_flags": attr.string_list( doc = """ A list of flags to embed in the wrapper script generated for running this binary. Subject to $(location) and "Make variable" substitution, and Bourne shell tokenization.

The wrapper script for a Java binary includes a CLASSPATH definition (to find all the dependent jars) and invokes the right Java interpreter. The command line generated by the wrapper script includes the name of the main class followed by a "$@" so you can pass along other arguments after the classname. However, arguments intended for parsing by the JVM must be specified before the classname on the command line. The contents of jvm_flags are added to the wrapper script before the classname is listed.

Note that this attribute has no effect on *_deploy.jar outputs.

""", ), "deploy_manifest_lines": attr.string_list( doc = """ A list of lines to add to the META-INF/manifest.mf file generated for the *_deploy.jar target. The contents of this attribute are not subject to "Make variable" substitution. """, ), "stamp": attr.int( default = -1, values = [-1, 0, 1], doc = """ Whether to encode build information into the binary. Possible values:

Stamped binaries are not rebuilt unless their dependencies change.

""", ), "use_testrunner": attr.bool( default = False, doc = semantics.DOCS.for_attribute("use_testrunner") + """
You can use this to override the default behavior, which is to use test runner for java_test rules, and not use it for java_binary rules. It is unlikely you will want to do this. One use is for AllTest rules that are invoked by another rule (to set up a database before running the tests, for example). The AllTest rule must be declared as a java_binary, but should still use the test runner as its main entry point. The name of a test runner class can be overridden with main_class attribute. """, ), "use_launcher": attr.bool( default = True, doc = """ Whether the binary should use a custom launcher.

If this attribute is set to false, the launcher attribute and the related --java_launcher flag will be ignored for this target. """, ), "env": attr.string_dict(), "classpath_resources": attr.label_list( allow_files = True, doc = """ DO NOT USE THIS OPTION UNLESS THERE IS NO OTHER WAY)

A list of resources that must be located at the root of the java tree. This attribute's only purpose is to support third-party libraries that require that their resources be found on the classpath as exactly "myconfig.xml". It is only allowed on binaries and not libraries, due to the danger of namespace conflicts.

""", ), "licenses": attr.license() if hasattr(attr, "license") else attr.string_list(), "_stub_template": attr.label( default = semantics.JAVA_STUB_TEMPLATE_LABEL, allow_single_file = True, ), "_java_toolchain_type": attr.label(default = semantics.JAVA_TOOLCHAIN_TYPE), "_windows_constraints": attr.label_list( default = [paths.join(_PLATFORMS_ROOT, "os:windows")], ), "_build_info_translator": attr.label(default = semantics.BUILD_INFO_TRANSLATOR_LABEL), } | ({} if get_internal_java_common().incompatible_disable_non_executable_java_binary() else {"create_executable": attr.bool(default = True, doc = "Deprecated, use java_single_jar instead.")}), ) BASE_TEST_ATTRIBUTES = { "test_class": attr.string( doc = """ The Java class to be loaded by the test runner.

By default, if this argument is not defined then the legacy mode is used and the test arguments are used instead. Set the --nolegacy_bazel_java_test flag to not fallback on the first argument.

This attribute specifies the name of a Java class to be run by this test. It is rare to need to set this. If this argument is omitted, it will be inferred using the target's name and its source-root-relative path. If the test is located outside a known source root, Bazel will report an error if test_class is unset.

For JUnit3, the test class needs to either be a subclass of junit.framework.TestCase or it needs to have a public static suite() method that returns a junit.framework.Test (or a subclass of Test). For JUnit4, the class needs to be annotated with org.junit.runner.RunWith.

This attribute allows several java_test rules to share the same Test (TestCase, TestSuite, ...). Typically additional information is passed to it (e.g. via jvm_flags=['-Dkey=value']) so that its behavior differs in each case, such as running a different subset of the tests. This attribute also enables the use of Java tests outside the javatests tree.

""", ), "env_inherit": attr.string_list(), "_apple_constraints": attr.label_list( default = [ paths.join(_PLATFORMS_ROOT, "os:ios"), paths.join(_PLATFORMS_ROOT, "os:macos"), paths.join(_PLATFORMS_ROOT, "os:tvos"), paths.join(_PLATFORMS_ROOT, "os:visionos"), paths.join(_PLATFORMS_ROOT, "os:watchos"), ], ), "_legacy_any_type_attrs": attr.string_list(default = ["stamp"]), }