# 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
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 ordinarydeps
, 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
.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:
{name}_nativedeps.so
, where
{name}
is the name
attribute of this java_binary rule.
Unused code is not removed by the linker in this configuration.{name}_nativedeps
, where {name}
is the name
attribute of this java_binary rule. In this case,
the linker will remove any code it thinks is unused from the resulting binary,
which means any C++ code accessed only via JNI may not be linked in unless
that cc_library
target specifies alwayslink = True
.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.
These compiler options are passed to javac after the global compiler options.
""", ), "add_exports": attr.string_list( doc = """ Allow this library to access the givenmodule
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.
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.
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:
stamp = 1
: Always stamp the build information into the binary, even in
--nostamp
builds. This
setting should be avoided, since it potentially kills remote caching for the
binary and any downstream actions that depend on it.
stamp = 0
: Always replace build information by constant values. This
gives good build result caching.
stamp = -1
: Embedding of build information is controlled by the
--[no]stamp
flag.
Stamped binaries are not rebuilt unless their dependencies change.
""", ), "use_testrunner": attr.bool( default = False, doc = semantics.DOCS.for_attribute("use_testrunner") + """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.
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.