// 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.syntax.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.packages.RuleClass.Builder; 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(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=1</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=1</code>, you get a single completely self-contained unit. If you specify both <code>linkstatic=1</code> and <code>linkshared=1</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")) .cfg(BazelCppRuleClasses.LIPO_ON_DEMAND) .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 -->*/