blob: 7faeaa66114b78579820c1acc8aba2d0fec98f77 [file] [log] [blame]
// Copyright 2014 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.
package com.google.devtools.build.lib.bazel.rules.java;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.test.TestConfiguration;
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaRuleClasses.JavaRule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.rules.java.JavaInfo;
import com.google.devtools.build.lib.rules.java.ProguardLibraryRule;
/**
* Common attributes for Java rules.
*/
public final class BazelJavaLibraryRule implements RuleDefinition {
@Override
public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) {
return ConfigAwareRuleClassBuilder.of(builder)
// For getting the host Java executable.
.requiresHostConfigurationFragments(JavaConfiguration.class)
.originalBuilder()
.requiresConfigurationFragments(
JavaConfiguration.class,
CppConfiguration.class,
// TestConfiguration is only required by the java rules to know when the persistent test
// runner is enabled.
TestConfiguration.class)
/* <!-- #BLAZE_RULE(java_library).IMPLICIT_OUTPUTS -->
<ul>
<li><code>lib<var>name</var>.jar</code>: A Java archive containing the class files.</li>
<li><code>lib<var>name</var>-src.jar</code>: An archive containing the sources ("source
jar").</li>
</ul>
<!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS --> */
.setImplicitOutputsFunction(BazelJavaRuleClasses.JAVA_LIBRARY_IMPLICIT_OUTPUTS)
/* <!-- #BLAZE_RULE(java_library).ATTRIBUTE(data) -->
The list of files needed by this library at runtime.
See general comments about <code>data</code> at
<a href="${link common-definitions#common-attributes}">Attributes common to all build rules
</a>.
<p>
When building a <code>java_library</code>, Bazel doesn't put these files anywhere; if the
<code>data</code> files are generated files then Bazel generates them. When building a
test that depends on this <code>java_library</code> Bazel copies or links the
<code>data</code> files into the runfiles area.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
/* <!-- #BLAZE_RULE(java_library).ATTRIBUTE(deps) -->
The list of libraries to link into this library.
See general comments about <code>deps</code> at
<a href="${link common-definitions#common-attributes}">Attributes common to all build rules
</a>.
<p>
The jars built by <code>java_library</code> rules listed in <code>deps</code> will be on
the compile-time classpath of this rule. Furthermore the transitive closure of their
<code>deps</code>, <code>runtime_deps</code> and <code>exports</code> will be on the
runtime classpath.
</p>
<p>
By contrast, targets in the <code>data</code> attribute are included in the runfiles but
on neither the compile-time nor runtime classpath.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
/* <!-- #BLAZE_RULE(java_library).ATTRIBUTE(exports) -->
Exported libraries.
<p>
Listing rules here will make them available to parent rules, as if the parents explicitly
depended on these rules. This is not true for regular (non-exported) <code>deps</code>.
</p>
<p>
Summary: a rule <i>X</i> can access the code in <i>Y</i> if there exists a dependency
path between them that begins with a <code>deps</code> edge followed by zero or more
<code>exports</code> edges. Let's see some examples to illustrate this.
</p>
<p>
Assume <i>A</i> depends on <i>B</i> and <i>B</i> depends on <i>C</i>. In this case
C is a <em>transitive</em> dependency of A, so changing C's sources and rebuilding A will
correctly rebuild everything. However A will not be able to use classes in C. To allow
that, either A has to declare C in its <code>deps</code>, or B can make it easier for A
(and anything that may depend on A) by declaring C in its (B's) <code>exports</code>
attribute.
</p>
<p>
The closure of exported libraries is available to all direct parent rules. Take a slightly
different example: A depends on B, B depends on C and D, and also exports C but not D.
Now A has access to C but not to D. Now, if C and D exported some libraries, C' and D'
respectively, A could only access C' but not D'.
</p>
<p>
Important: an exported rule is not a regular dependency. Sticking to the previous example,
if B exports C and wants to also use C, it has to also list it in its own
<code>deps</code>.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(
attr("exports", LABEL_LIST)
.allowedRuleClasses(BazelJavaRuleClasses.ALLOWED_RULES_IN_DEPS)
.allowedFileTypes(/*May not have files in exports!*/ )
.mandatoryProvidersList(BazelJavaRuleClasses.MANDATORY_JAVA_PROVIDER_ONLY))
/* <!-- #BLAZE_RULE(java_library).ATTRIBUTE(neverlink) -->
Whether this library should only be used for compilation and not at runtime.
Useful if the library will be provided by the runtime environment during execution. Examples
of such libraries are the IDE APIs for IDE plug-ins or <code>tools.jar</code> for anything
running on a standard JDK.
<p>
Note that <code>neverlink = 1</code> does not prevent the compiler from inlining material
from this library into compilation targets that depend on it, as permitted by the Java
Language Specification (e.g., <code>static final</code> constants of <code>String</code>
or of primitive types). The preferred use case is therefore when the runtime library is
identical to the compilation library.
</p>
<p>
If the runtime library differs from the compilation library then you must ensure that it
differs only in places that the JLS forbids compilers to inline (and that must hold for
all future versions of the JLS).
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("neverlink", BOOLEAN).value(false))
.override(attr("javacopts", STRING_LIST))
/* <!-- #BLAZE_RULE(java_library).ATTRIBUTE(exported_plugins) -->
The list of <code><a href="#${link java_plugin}">java_plugin</a></code>s (e.g. annotation
processors) to export to libraries that directly depend on this library.
<p>
The specified list of <code>java_plugin</code>s will be applied to any library which
directly depends on this library, just as if that library had explicitly declared these
labels in <code><a href="${link java_library.plugins}">plugins</a></code>.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(
attr("exported_plugins", LABEL_LIST)
.cfg(HostTransition.createFactory())
.allowedRuleClasses("java_plugin")
.allowedFileTypes())
.advertiseSkylarkProvider(SkylarkProviderIdentifier.forKey(JavaInfo.PROVIDER.getKey()))
.addRequiredToolchains(CppRuleClasses.ccToolchainTypeAttribute(env))
.build();
}
@Override
public Metadata getMetadata() {
return RuleDefinition.Metadata.builder()
.name("java_library")
.ancestors(JavaRule.class, ProguardLibraryRule.class)
.factoryClass(BazelJavaLibrary.class)
.build();
}
}
/*<!-- #BLAZE_RULE (NAME = java_library, TYPE = LIBRARY, FAMILY = Java) -->
<p>This rule compiles and links sources into a <code>.jar</code> file.</p>
${IMPLICIT_OUTPUTS}
<!-- #END_BLAZE_RULE -->*/