• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2022 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15""" Implementation of java_binary for bazel """
16
17load("@bazel_skylib//lib:paths.bzl", "paths")
18load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
19load("//java/common:java_semantics.bzl", "semantics")
20load("//java/private:java_common.bzl", "java_common")
21load("//java/private:java_info.bzl", "JavaInfo", "JavaPluginInfo")
22load("//java/private:native.bzl", "get_internal_java_common")
23load(":basic_java_library.bzl", "BASIC_JAVA_LIBRARY_IMPLICIT_ATTRS")
24load(":rule_util.bzl", "merge_attrs")
25
26# copybara: default visibility
27
28BootClassPathInfo = java_common.BootClassPathInfo
29_PLATFORMS_ROOT = semantics.PLATFORMS_ROOT
30
31BASIC_JAVA_BINARY_ATTRIBUTES = merge_attrs(
32    BASIC_JAVA_LIBRARY_IMPLICIT_ATTRS,
33    # buildifier: disable=attr-licenses
34    {
35        "srcs": attr.label_list(
36            allow_files = [".java", ".srcjar", ".properties"] + semantics.EXTRA_SRCS_TYPES,
37            flags = ["DIRECT_COMPILE_TIME_INPUT", "ORDER_INDEPENDENT"],
38            doc = """
39The list of source files that are processed to create the target.
40This attribute is almost always required; see exceptions below.
41<p>
42Source files of type <code>.java</code> are compiled. In case of generated
43<code>.java</code> files it is generally advisable to put the generating rule's name
44here instead of the name of the file itself. This not only improves readability but
45makes the rule more resilient to future changes: if the generating rule generates
46different files in the future, you only need to fix one place: the <code>outs</code> of
47the generating rule. You should not list the generating rule in <code>deps</code>
48because it is a no-op.
49</p>
50<p>
51Source files of type <code>.srcjar</code> are unpacked and compiled. (This is useful if
52you need to generate a set of <code>.java</code> files with a genrule.)
53</p>
54<p>
55Rules: if the rule (typically <code>genrule</code> or <code>filegroup</code>) generates
56any of the files listed above, they will be used the same way as described for source
57files.
58</p>
59
60<p>
61This argument is almost always required, except if a
62<a href="#java_binary.main_class"><code>main_class</code></a> attribute specifies a
63class on the runtime classpath or you specify the <code>runtime_deps</code> argument.
64</p>
65            """,
66        ),
67        "deps": attr.label_list(
68            allow_files = [".jar"],
69            allow_rules = semantics.ALLOWED_RULES_IN_DEPS + semantics.ALLOWED_RULES_IN_DEPS_WITH_WARNING,
70            providers = [
71                [CcInfo],
72                [JavaInfo],
73            ],
74            flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"],
75            doc = """
76The list of other libraries to be linked in to the target.
77See general comments about <code>deps</code> at
78<a href="common-definitions.html#typical-attributes">Typical attributes defined by
79most build rules</a>.
80            """,
81        ),
82        "resources": attr.label_list(
83            allow_files = True,
84            flags = ["SKIP_CONSTRAINTS_OVERRIDE", "ORDER_INDEPENDENT"],
85            doc = """
86A list of data files to include in a Java jar.
87
88<p>
89Resources may be source files or generated files.
90</p>
91            """ + semantics.DOCS.for_attribute("resources"),
92        ),
93        "runtime_deps": attr.label_list(
94            allow_files = [".jar"],
95            allow_rules = semantics.ALLOWED_RULES_IN_DEPS,
96            providers = [[CcInfo], [JavaInfo]],
97            flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"],
98            doc = """
99Libraries to make available to the final binary or test at runtime only.
100Like ordinary <code>deps</code>, these will appear on the runtime classpath, but unlike
101them, not on the compile-time classpath. Dependencies needed only at runtime should be
102listed here. Dependency-analysis tools should ignore targets that appear in both
103<code>runtime_deps</code> and <code>deps</code>.
104            """,
105        ),
106        "data": attr.label_list(
107            allow_files = True,
108            flags = ["SKIP_CONSTRAINTS_OVERRIDE"],
109            doc = """
110The list of files needed by this library at runtime.
111See general comments about <code>data</code>
112at <a href="${link common-definitions#typical-attributes}">Typical attributes defined by
113most build rules</a>.
114            """ + semantics.DOCS.for_attribute("data"),
115        ),
116        "plugins": attr.label_list(
117            providers = [JavaPluginInfo],
118            allow_files = True,
119            cfg = "exec",
120            doc = """
121Java compiler plugins to run at compile-time.
122Every <code>java_plugin</code> specified in this attribute will be run whenever this rule
123is built. A library may also inherit plugins from dependencies that use
124<code><a href="#java_library.exported_plugins">exported_plugins</a></code>. Resources
125generated by the plugin will be included in the resulting jar of this rule.
126            """,
127        ),
128        "deploy_env": attr.label_list(
129            providers = [java_common.JavaRuntimeClasspathInfo],
130            allow_files = False,
131            doc = """
132A list of other <code>java_binary</code> targets which represent the deployment
133environment for this binary.
134Set this attribute when building a plugin which will be loaded by another
135<code>java_binary</code>.<br/> Setting this attribute excludes all dependencies from
136the runtime classpath (and the deploy jar) of this binary that are shared between this
137binary and the targets specified in <code>deploy_env</code>.
138            """,
139        ),
140        "launcher": attr.label(
141            # TODO(b/295221112): add back CcLauncherInfo
142            allow_files = False,
143            doc = """
144Specify a binary that will be used to run your Java program instead of the
145normal <code>bin/java</code> program included with the JDK.
146The target must be a <code>cc_binary</code>. Any <code>cc_binary</code> that
147implements the
148<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html">
149Java Invocation API</a> can be specified as a value for this attribute.
150
151<p>By default, Bazel will use the normal JDK launcher (bin/java or java.exe).</p>
152
153<p>The related <a href="${link user-manual#flag--java_launcher}"><code>
154--java_launcher</code></a> Bazel flag affects only those
155<code>java_binary</code> and <code>java_test</code> targets that have
156<i>not</i> specified a <code>launcher</code> attribute.</p>
157
158<p>Note that your native (C++, SWIG, JNI) dependencies will be built differently
159depending on whether you are using the JDK launcher or another launcher:</p>
160
161<ul>
162<li>If you are using the normal JDK launcher (the default), native dependencies are
163built as a shared library named <code>{name}_nativedeps.so</code>, where
164<code>{name}</code> is the <code>name</code> attribute of this java_binary rule.
165Unused code is <em>not</em> removed by the linker in this configuration.</li>
166
167<li>If you are using any other launcher, native (C++) dependencies are statically
168linked into a binary named <code>{name}_nativedeps</code>, where <code>{name}</code>
169is the <code>name</code> attribute of this java_binary rule. In this case,
170the linker will remove any code it thinks is unused from the resulting binary,
171which means any C++ code accessed only via JNI may not be linked in unless
172that <code>cc_library</code> target specifies <code>alwayslink = True</code>.</li>
173</ul>
174
175<p>When using any launcher other than the default JDK launcher, the format
176of the <code>*_deploy.jar</code> output changes. See the main
177<a href="#java_binary">java_binary</a> docs for details.</p>
178            """,
179        ),
180        "bootclasspath": attr.label(
181            providers = [BootClassPathInfo],
182            flags = ["SKIP_CONSTRAINTS_OVERRIDE"],
183            doc = "Restricted API, do not use!",
184        ),
185        "neverlink": attr.bool(),
186        "javacopts": attr.string_list(
187            doc = """
188Extra compiler options for this binary.
189Subject to <a href="make-variables.html">"Make variable"</a> substitution and
190<a href="common-definitions.html#sh-tokenization">Bourne shell tokenization</a>.
191<p>These compiler options are passed to javac after the global compiler options.</p>
192            """,
193        ),
194        "add_exports": attr.string_list(
195            doc = """
196Allow this library to access the given <code>module</code> or <code>package</code>.
197<p>
198This corresponds to the javac and JVM --add-exports= flags.
199            """,
200        ),
201        "add_opens": attr.string_list(
202            doc = """
203Allow this library to reflectively access the given <code>module</code> or
204<code>package</code>.
205<p>
206This corresponds to the javac and JVM --add-opens= flags.
207            """,
208        ),
209        "main_class": attr.string(
210            doc = """
211Name of class with <code>main()</code> method to use as entry point.
212If a rule uses this option, it does not need a <code>srcs=[...]</code> list.
213Thus, with this attribute one can make an executable from a Java library that already
214contains one or more <code>main()</code> methods.
215<p>
216The value of this attribute is a class name, not a source file. The class must be
217available at runtime: it may be compiled by this rule (from <code>srcs</code>) or
218provided by direct or transitive dependencies (through <code>runtime_deps</code> or
219<code>deps</code>). If the class is unavailable, the binary will fail at runtime; there
220is no build-time check.
221</p>
222            """,
223        ),
224        "jvm_flags": attr.string_list(
225            doc = """
226A list of flags to embed in the wrapper script generated for running this binary.
227Subject to <a href="${link make-variables#location}">$(location)</a> and
228<a href="make-variables.html">"Make variable"</a> substitution, and
229<a href="common-definitions.html#sh-tokenization">Bourne shell tokenization</a>.
230
231<p>The wrapper script for a Java binary includes a CLASSPATH definition
232(to find all the dependent jars) and invokes the right Java interpreter.
233The command line generated by the wrapper script includes the name of
234the main class followed by a <code>"$@"</code> so you can pass along other
235arguments after the classname.  However, arguments intended for parsing
236by the JVM must be specified <i>before</i> the classname on the command
237line.  The contents of <code>jvm_flags</code> are added to the wrapper
238script before the classname is listed.</p>
239
240<p>Note that this attribute has <em>no effect</em> on <code>*_deploy.jar</code>
241outputs.</p>
242            """,
243        ),
244        "deploy_manifest_lines": attr.string_list(
245            doc = """
246A list of lines to add to the <code>META-INF/manifest.mf</code> file generated for the
247<code>*_deploy.jar</code> target. The contents of this attribute are <em>not</em> subject
248to <a href="make-variables.html">"Make variable"</a> substitution.
249            """,
250        ),
251        "stamp": attr.int(
252            default = -1,
253            values = [-1, 0, 1],
254            doc = """
255Whether to encode build information into the binary. Possible values:
256<ul>
257<li>
258  <code>stamp = 1</code>: Always stamp the build information into the binary, even in
259  <a href="${link user-manual#flag--stamp}"><code>--nostamp</code></a> builds. <b>This
260  setting should be avoided</b>, since it potentially kills remote caching for the
261  binary and any downstream actions that depend on it.
262</li>
263<li>
264  <code>stamp = 0</code>: Always replace build information by constant values. This
265  gives good build result caching.
266</li>
267<li>
268  <code>stamp = -1</code>: Embedding of build information is controlled by the
269  <a href="${link user-manual#flag--stamp}"><code>--[no]stamp</code></a> flag.
270</li>
271</ul>
272<p>Stamped binaries are <em>not</em> rebuilt unless their dependencies change.</p>
273            """,
274        ),
275        "use_testrunner": attr.bool(
276            default = False,
277            doc = semantics.DOCS.for_attribute("use_testrunner") + """
278<br/>
279You can use this to override the default
280behavior, which is to use test runner for
281<code>java_test</code> rules,
282and not use it for <code>java_binary</code> rules.  It is unlikely
283you will want to do this.  One use is for <code>AllTest</code>
284rules that are invoked by another rule (to set up a database
285before running the tests, for example).  The <code>AllTest</code>
286rule must be declared as a <code>java_binary</code>, but should
287still use the test runner as its main entry point.
288
289The name of a test runner class can be overridden with <code>main_class</code> attribute.
290            """,
291        ),
292        "use_launcher": attr.bool(
293            default = True,
294            doc = """
295Whether the binary should use a custom launcher.
296
297<p>If this attribute is set to false, the
298<a href="${link java_binary.launcher}">launcher</a> attribute  and the related
299<a href="${link user-manual#flag--java_launcher}"><code>--java_launcher</code></a> flag
300will be ignored for this target.
301            """,
302        ),
303        "env": attr.string_dict(),
304        "classpath_resources": attr.label_list(
305            allow_files = True,
306            doc = """
307<em class="harmful">DO NOT USE THIS OPTION UNLESS THERE IS NO OTHER WAY)</em>
308<p>
309A list of resources that must be located at the root of the java tree. This attribute's
310only purpose is to support third-party libraries that require that their resources be
311found on the classpath as exactly <code>"myconfig.xml"</code>. It is only allowed on
312binaries and not libraries, due to the danger of namespace conflicts.
313</p>
314            """,
315        ),
316        "licenses": attr.license() if hasattr(attr, "license") else attr.string_list(),
317        "_stub_template": attr.label(
318            default = semantics.JAVA_STUB_TEMPLATE_LABEL,
319            allow_single_file = True,
320        ),
321        "_java_toolchain_type": attr.label(default = semantics.JAVA_TOOLCHAIN_TYPE),
322        "_windows_constraints": attr.label_list(
323            default = [paths.join(_PLATFORMS_ROOT, "os:windows")],
324        ),
325        "_build_info_translator": attr.label(default = semantics.BUILD_INFO_TRANSLATOR_LABEL),
326    } | ({} if get_internal_java_common().incompatible_disable_non_executable_java_binary() else {"create_executable": attr.bool(default = True, doc = "Deprecated, use <code>java_single_jar</code> instead.")}),
327)
328
329BASE_TEST_ATTRIBUTES = {
330    "test_class": attr.string(
331        doc = """
332The Java class to be loaded by the test runner.<br/>
333<p>
334  By default, if this argument is not defined then the legacy mode is used and the
335  test arguments are used instead. Set the <code>--nolegacy_bazel_java_test</code> flag
336  to not fallback on the first argument.
337</p>
338<p>
339  This attribute specifies the name of a Java class to be run by
340  this test. It is rare to need to set this. If this argument is omitted,
341  it will be inferred using the target's <code>name</code> and its
342  source-root-relative path. If the test is located outside a known
343  source root, Bazel will report an error if <code>test_class</code>
344  is unset.
345</p>
346<p>
347  For JUnit3, the test class needs to either be a subclass of
348  <code>junit.framework.TestCase</code> or it needs to have a public
349  static <code>suite()</code> method that returns a
350  <code>junit.framework.Test</code> (or a subclass of <code>Test</code>).
351  For JUnit4, the class needs to be annotated with
352  <code>org.junit.runner.RunWith</code>.
353</p>
354<p>
355  This attribute allows several <code>java_test</code> rules to
356  share the same <code>Test</code>
357  (<code>TestCase</code>, <code>TestSuite</code>, ...).  Typically
358  additional information is passed to it
359  (e.g. via <code>jvm_flags=['-Dkey=value']</code>) so that its
360  behavior differs in each case, such as running a different
361  subset of the tests.  This attribute also enables the use of
362  Java tests outside the <code>javatests</code> tree.
363</p>
364        """,
365    ),
366    "env_inherit": attr.string_list(),
367    "_apple_constraints": attr.label_list(
368        default = [
369            paths.join(_PLATFORMS_ROOT, "os:ios"),
370            paths.join(_PLATFORMS_ROOT, "os:macos"),
371            paths.join(_PLATFORMS_ROOT, "os:tvos"),
372            paths.join(_PLATFORMS_ROOT, "os:visionos"),
373            paths.join(_PLATFORMS_ROOT, "os:watchos"),
374        ],
375    ),
376    "_legacy_any_type_attrs": attr.string_list(default = ["stamp"]),
377}
378