blob: 8c1c0c3f4c637a33dfc4bb5f7d225a82736ca4e4 [file] [log] [blame]
// Copyright 2016 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.cpp;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.bazel.rules.cpp.BazelCppRuleClasses.CcBinaryBaseRule;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
/** Rule definition for cc_binary rules. */
public final class BazelCcBinaryRule implements RuleDefinition {
@Override
public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
return builder
.requiresConfigurationFragments(CppConfiguration.class)
/*<!-- #BLAZE_RULE(cc_binary).IMPLICIT_OUTPUTS -->
<ul>
<li><code><var>name</var>.stripped</code> (only built if explicitly requested): A stripped
version of the binary. <code>strip -g</code> is run on the binary to remove debug
symbols. Additional strip options can be provided on the command line using
<code>--stripopt=-foo</code>. This output is only built if explicitly requested.</li>
<li><code><var>name</var>.dwp</code> (only built if explicitly requested): If
<a href="https://gcc.gnu.org/wiki/DebugFission">Fission</a> is enabled: a debug
information package file suitable for debugging remotely deployed binaries. Else: an
empty file.</li>
</ul>
<!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS -->*/
.setImplicitOutputsFunction(BazelCppRuleClasses.CC_BINARY_IMPLICIT_OUTPUTS)
/*<!-- #BLAZE_RULE(cc_binary).ATTRIBUTE(linkshared) -->
Create a shared library.
To enable this attribute, include <code>linkshared=True</code> in your rule. By default
this option is off. If you enable it, you must name your binary
<code>lib<i>foo</i>.so</code> (or whatever is the naming convention of libraries on the
target platform) for some sensible value of <i>foo</i>.
<p>
The presence of this flag means that linking occurs with the <code>-shared</code> flag
to <code>gcc</code>, and the resulting shared library is suitable for loading into for
example a Java program. However, for build purposes it will never be linked into the
dependent binary, as it is assumed that shared libraries built with a
<a href="#cc_binary">cc_binary</a> rule are only loaded manually by other programs, so
it should not be considered a substitute for the <a href="#cc_library">cc_library</a>
rule. For sake of scalability we recommend avoiding this approach altogether and
simply letting <code>java_library</code> depend on <code>cc_library</code> rules
instead.
</p>
<p>
If you specify both <code>linkopts=['-static']</code> and <code>linkshared=True</code>,
you get a single completely self-contained unit. If you specify both
<code>linkstatic=1</code> and <code>linkshared=True</code>, you get a single, mostly
self-contained unit.
</p>
<!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
.add(
attr("linkshared", BOOLEAN)
.value(false)
.nonconfigurable("used to *determine* the rule's configuration"))
.build();
}
@Override
public Metadata getMetadata() {
return RuleDefinition.Metadata.builder()
.name("cc_binary")
.ancestors(CcBinaryBaseRule.class, BaseRuleClasses.BinaryBaseRule.class)
.factoryClass(BazelCcBinary.class)
.build();
}
}
/*<!-- #BLAZE_RULE (NAME = cc_binary, TYPE = BINARY, FAMILY = C / C++) -->
${IMPLICIT_OUTPUTS}
<!-- #END_BLAZE_RULE -->*/
/*<!-- #BLAZE_RULE (NAME = cc_library, TYPE = LIBRARY, FAMILY = C / C++) -->
<h4 id="hdrs">Header inclusion checking</h4>
<p>
All header files that are used in the build must be declared in the <code>hdrs</code> or
<code>srcs</code> of <code>cc_*</code> rules. This is enforced.
</p>
<p>
For <code>cc_library</code> rules, headers in <code>hdrs</code> comprise the public interface of
the library and can be directly included both from the files in <code>hdrs</code> and
<code>srcs</code> of the library itself as well as from files in <code>hdrs</code> and
<code>srcs</code> of <code>cc_*</code> rules that list the library in their <code>deps</code>.
Headers in <code>srcs</code> must only be directly included from the files in <code>hdrs</code>
and <code>srcs</code> of the library itself. When deciding whether to put a header into
<code>hdrs</code> or <code>srcs</code>, you should ask whether you want consumers of this library
to be able to directly include it. This is roughly the same decision as between
<code>public</code> and <code>private</code> visibility in programming languages.
</p>
<p>
<code>cc_binary</code> and <code>cc_test</code> rules do not have an exported interface, so they
also do not have a <code>hdrs</code> attribute. All headers that belong to the binary or test
directly should be listed in the <code>srcs</code>.
</p>
<p>
To illustrate these rules, look at the following example.
</p>
<pre class="code">
cc_binary(
name = "foo",
srcs = [
"foo.cc",
"foo.h",
],
deps = [":bar"],
)
cc_library(
name = "bar",
srcs = [
"bar.cc",
"bar-impl.h",
],
hdrs = ["bar.h"],
deps = [":baz"],
)
cc_library(
name = "baz",
srcs = [
"baz.cc",
"baz-impl.h",
],
hdrs = ["baz.h"],
)
</pre>
<p>
The allowed direct inclusions in this example are listed in the table below. For example
<code>foo.cc</code> is allowed to directly include <code>foo.h</code> and <code>bar.h</code>, but
not <code>baz.h</code>.
</p>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr><th>Including file</th><th>Allowed inclusions</th></tr>
</thead>
<tbody>
<tr><td>foo.h</td><td>bar.h</td></tr>
<tr><td>foo.cc</td><td>foo.h bar.h</td></tr>
<tr><td>bar.h</td><td>bar-impl.h baz.h</td></tr>
<tr><td>bar-impl.h</td><td>bar.h baz.h</td></tr>
<tr><td>bar.cc</td><td>bar.h bar-impl.h baz.h</td></tr>
<tr><td>baz.h</td><td>baz-impl.h</td></tr>
<tr><td>baz-impl.h</td><td>baz.h</td></tr>
<tr><td>baz.cc</td><td>baz.h baz-impl.h</td></tr>
</tbody>
</table>
<p>
The inclusion checking rules only apply to <em>direct</em>
inclusions. In the example above <code>foo.cc</code> is allowed to
include <code>bar.h</code>, which may include <code>baz.h</code>, which in
turn is allowed to include <code>baz-impl.h</code>. Technically, the
compilation of a <code>.cc</code> file may transitively include any header
file in the <code>hdrs</code> or <code>srcs</code> in
any <code>cc_library</code> in the transitive <code>deps</code> closure. In
this case the compiler may read <code>baz.h</code> and <code>baz-impl.h</code>
when compiling <code>foo.cc</code>, but <code>foo.cc</code> must not
contain <code>#include "baz.h"</code>. For that to be
allowed, <code>baz</code> must be added to the <code>deps</code>
of <code>foo</code>.
</p>
<p>
Unfortunately Bazel currently cannot distinguish between direct and transitive
inclusions, so it cannot detect error cases where a file illegally includes a
header directly that is only allowed to be included transitively. For example,
Bazel would not complain if in the example above <code>foo.cc</code> directly
includes <code>baz.h</code>. This would be illegal, because <code>foo</code>
does not directly depend on <code>baz</code>. Currently, no error is produced
in that case, but such error checking may be added in the future.
</p>
<!-- #END_BLAZE_RULE -->*/