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