// 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.cpp;

import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.BuildType.NODEP_LABEL;
import static com.google.devtools.build.lib.packages.BuildType.TRISTATE;
import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromFunctions;
import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static com.google.devtools.build.lib.packages.Type.STRING_LIST;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.ALWAYS_LINK_LIBRARY;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.ALWAYS_LINK_PIC_LIBRARY;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.ARCHIVE;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.ASSEMBLER;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.ASSEMBLER_WITH_C_PREPROCESSOR;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.CPP_HEADER;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.CPP_SOURCE;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.C_SOURCE;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.OBJECT_FILE;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.PIC_ARCHIVE;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.PIC_OBJECT_FILE;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.SHARED_LIBRARY;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.VERSIONED_SHARED_LIBRARY;

import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
import com.google.devtools.build.lib.analysis.PlatformConfiguration;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchain;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
import com.google.devtools.build.lib.rules.cpp.CppRuleClasses.CcIncludeScanningRule;
import com.google.devtools.build.lib.rules.cpp.GraphNodeAspect;
import com.google.devtools.build.lib.util.FileTypeSet;

/**
 * Rule class definitions for C++ rules.
 */
public class BazelCppRuleClasses {
  static final SafeImplicitOutputsFunction CC_LIBRARY_DYNAMIC_LIB =
      fromTemplates("%{dirname}lib%{basename}.so");

  static final SafeImplicitOutputsFunction CC_BINARY_IMPLICIT_OUTPUTS =
      fromFunctions(CppRuleClasses.CC_BINARY_STRIPPED, CppRuleClasses.CC_BINARY_DEBUG_PACKAGE);

  static final FileTypeSet ALLOWED_SRC_FILES =
      FileTypeSet.of(
          CPP_SOURCE,
          C_SOURCE,
          CPP_HEADER,
          ASSEMBLER_WITH_C_PREPROCESSOR,
          ASSEMBLER,
          ARCHIVE,
          PIC_ARCHIVE,
          ALWAYS_LINK_LIBRARY,
          ALWAYS_LINK_PIC_LIBRARY,
          SHARED_LIBRARY,
          VERSIONED_SHARED_LIBRARY,
          OBJECT_FILE,
          PIC_OBJECT_FILE);

  static final String[] DEPS_ALLOWED_RULES =
      new String[] {
        "cc_library", "objc_library", "cc_proto_library", "cc_import",
      };

  /** Common attributes for all rules that need a C++ toolchain. */
  public static final class CcToolchainRequiringRule implements RuleDefinition {
    @Override
    @SuppressWarnings("unchecked")
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          .add(
              attr(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, LABEL)
                  .mandatoryProviders(CcToolchainProvider.PROVIDER.id())
                  .value(CppRuleClasses.ccToolchainAttribute(env)))
          .add(
              attr(CcToolchain.CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME, NODEP_LABEL)
                  .value(CppRuleClasses.ccToolchainTypeAttribute(env)))
          .setPreferredDependencyPredicate(Predicates.<String>or(CPP_SOURCE, C_SOURCE, CPP_HEADER))
          .requiresConfigurationFragments(PlatformConfiguration.class)
          .addRequiredToolchains(CppRuleClasses.ccToolchainTypeAttribute(env))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$cc_toolchain_requiring_rule")
          .ancestors(CcIncludeScanningRule.class)
          .type(RuleClassType.ABSTRACT)
          .build();
    }
  }

  /**
   * Common attributes for C++ rules.
   */
  public static final class CcBaseRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          /*<!-- #BLAZE_RULE($cc_base_rule).ATTRIBUTE(copts) -->
          Add these options to the C++ compilation command.
          Subject to <a href="${link make-variables}">"Make variable"</a> substitution and
          <a href="${link common-definitions#sh-tokenization}">Bourne shell tokenization</a>.
          <p>
            Each string in this attribute is added in the given order to <code>COPTS</code> before
            compiling the binary target. The flags take effect only for compiling this target, not
            its dependencies, so be careful about header files included elsewhere.  All paths should
            be relative to the workspace, not to the current package.
          </p>
          <p>
            If the package declares the <a href="${link package.features}">feature</a>
            <code>no_copts_tokenization</code>, Bourne shell tokenization applies only to strings
            that consist of a single "Make" variable.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("copts", STRING_LIST))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$cc_base_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(CcToolchainRequiringRule.class)
          .build();
    }
  }

  /**
   * Helper rule class.
   */
  public static final class CcDeclRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          /*<!-- #BLAZE_RULE($cc_decl_rule).ATTRIBUTE(defines) -->
          List of defines to add to the compile line.
          Subject to <a href="${link make-variables}">"Make" variable</a> substitution and
          <a href="${link common-definitions#sh-tokenization}">Bourne shell tokenization</a>.
          Each string, which must consist of a single Bourne shell token,
          is prepended with <code>-D</code> and added to the compile command line to this target,
          as well as to every rule that depends on it. Be very careful, since this may have
          far-reaching effects.  When in doubt, add define values to
          <a href="#cc_binary.local_defines"><code>local_defines</code></a> instead.
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("defines", STRING_LIST))
          /*<!-- #BLAZE_RULE($cc_decl_rule).ATTRIBUTE(local_defines) -->
          List of defines to add to the compile line.
          Subject to <a href="${link make-variables}">"Make" variable</a> substitution and
          <a href="${link common-definitions#sh-tokenization}">Bourne shell tokenization</a>.
          Each string, which must consist of a single Bourne shell token,
          is prepended with <code>-D</code> and added to the compile command line for this target,
          but not to its dependents.
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("local_defines", STRING_LIST))
          /*<!-- #BLAZE_RULE($cc_decl_rule).ATTRIBUTE(includes) -->
          List of include dirs to be added to the compile line.
          <p>
          Subject to <a href="${link make-variables}">"Make variable"</a> substitution.
          Each string is prepended with <code>-isystem</code> and added to <code>COPTS</code>.
          Unlike <a href="#cc_binary.copts">COPTS</a>, these flags are added for this rule
          and every rule that depends on it. (Note: not the rules it depends upon!) Be
          very careful, since this may have far-reaching effects.  When in doubt, add
          "-I" flags to <a href="#cc_binary.copts">COPTS</a> instead.
          </p>
          <p>
          Headers must be added to srcs or hdrs, otherwise they will not be available to dependent
          rules when compilation is sandboxed (the default).
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("includes", STRING_LIST))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$cc_decl_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(BaseRuleClasses.RuleBase.class)
          .build();
    }
  }

  /**
   * Helper rule class.
   */
  public static final class CcRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, final RuleDefinitionEnvironment env) {
      return builder
          /*<!-- #BLAZE_RULE($cc_rule).ATTRIBUTE(srcs) -->
          The list of C and C++ files that are processed to create the target.
          These are C/C++ source and header files, either non-generated (normal source
          code) or generated.
          <p>All <code>.cc</code>, <code>.c</code>, and <code>.cpp</code> files will
             be compiled. These might be generated files: if a named file is in
             the <code>outs</code> of some other rule, this rule
             will automatically depend on that other rule.
          </p>
          <p>A <code>.h</code> file will not be compiled, but will be available for
             inclusion by sources in this rule. Both <code>.cc</code> and
             <code>.h</code> files can directly include headers listed in
             these <code>srcs</code> or in the <code>hdrs</code> of any rule listed in
             the <code>deps</code> argument.
          </p>
          <p>All <code>#include</code>d files must be mentioned in the
             <code>srcs</code> attribute of this rule, or in the
             <code>hdrs</code> attribute of referenced <code>cc_library()</code>s.
             The recommended style is for headers associated with a library to be
             listed in that library's <code>hdrs</code> attribute, and any remaining
             headers associated with this rule's sources to be listed in
             <code>srcs</code>. See <a href="#hdrs">"Header inclusion checking"</a>
             for a more detailed description.
          </p>
          <p>If a rule's name is in the <code>srcs</code>,
             then this rule automatically depends on that one.
             If the named rule's <code>outs</code> are C or C++
             source files, they are compiled into this rule;
             if they are library files, they are linked in.
          </p>
          <p>
            Permitted <code>srcs</code> file types:
          </p>
          <ul>
            <li>C and C++ source files: <code>.c</code>, <code>.cc</code>, <code>.cpp</code>,
              <code>.cxx</code>, <code>.c++</code>, <code>.C</code></li>
            <li>C and C++ header files: <code>.h</code>, <code>.hh</code>, <code>.hpp</code>,
              <code>.hxx</code>, <code>.inc</code>, <code>.inl</code>, <code>.H</code></li>
            <li>Assembler with C preprocessor: <code>.S</code></li>
            <li>Archive: <code>.a</code>, <code>.pic.a</code></li>
            <li>"Always link" library: <code>.lo</code>, <code>.pic.lo</code></li>
            <li>Shared library, versioned or unversioned: <code>.so</code>,
              <code>.so.<i>version</i></code></li>
            <li>Object file: <code>.o</code>, <code>.pic.o</code></li>
          </ul>
          <p>
            ...and any rules that produce those files.
            Different extensions denote different programming languages in
            accordance with gcc convention.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(
              attr("srcs", LABEL_LIST)
                  .direct_compile_time_input()
                  .allowedFileTypes(ALLOWED_SRC_FILES))
          /*<!-- #BLAZE_RULE($cc_rule).ATTRIBUTE(deps) -->
          The list of other libraries to be linked in to the binary target.
          <p>These can be <code>cc_library</code> or <code>objc_library</code>
          targets.</p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .override(
              attr("deps", LABEL_LIST)
                  .allowedRuleClasses(DEPS_ALLOWED_RULES)
                  .allowedFileTypes(CppFileTypes.LINKER_SCRIPT)
                  .skipAnalysisTimeFileTypeCheck()
                  .mandatoryProviders(SkylarkProviderIdentifier.forKey(CcInfo.PROVIDER.getKey())))
          /*<!-- #BLAZE_RULE($cc_rule).ATTRIBUTE(win_def_file) -->
          The Windows DEF file to be passed to linker.
          <p>This attribute should only be used when Windows is the target platform.
          It can be used to <a href="https://msdn.microsoft.com/en-us/library/d91k01sh.aspx">
          export symbols</a> during linking a shared library.</p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("win_def_file", LABEL).allowedFileTypes(CppFileTypes.WINDOWS_DEF_FILE))
          .add(
              attr("reexport_deps", LABEL_LIST)
                  .allowedRuleClasses(DEPS_ALLOWED_RULES)
                  .allowedFileTypes())
          /*<!-- #BLAZE_RULE($cc_rule).ATTRIBUTE(linkopts) -->
          Add these flags to the C++ linker command.
          Subject to <a href="make-variables.html">"Make" variable</a> substitution,
          <a href="common-definitions.html#sh-tokenization">
          Bourne shell tokenization</a> and
          <a href="common-definitions.html#label-expansion">label expansion</a>.
          Each string in this attribute is added to <code>LINKOPTS</code> before
          linking the binary target.
          <p>
            Each element of this list that does not start with <code>$</code> or <code>-</code> is
            assumed to be the label of a target in <code>deps</code>.  The
            list of files generated by that target is appended to the linker
            options.  An error is reported if the label is invalid, or is
            not declared in <code>deps</code>.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("linkopts", STRING_LIST))
          /*<!-- #BLAZE_RULE($cc_rule).ATTRIBUTE(nocopts) -->
          Remove matching options from the C++ compilation command.
          Subject to <a href="${link make-variables}">"Make" variable</a> substitution.
          The value of this attribute is interpreted as a regular expression.
          Any preexisting <code>COPTS</code> that match this regular expression
          (including values explicitly specified in the rule's <a
          href="#cc_binary.copts">copts</a> attribute) will be removed from
          <code>COPTS</code> for purposes of compiling this rule.
          This attribute should rarely be needed.
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("nocopts", STRING))
          /*<!-- #BLAZE_RULE($cc_rule).ATTRIBUTE(linkstatic) -->
           For <a href="${link cc_binary}"><code>cc_binary</code></a> and
           <a href="${link cc_test}"><code>cc_test</code></a>: link the binary in static
           mode. For <code>cc_library.linkstatic</code>: see below.
           <p>
             By default this option is on for <code>cc_binary</code> and off for the rest.
           </p>
           <p>
             If enabled and this is a binary or test, this option tells the build tool to link in
             <code>.a</code>'s instead of <code>.so</code>'s for user libraries whenever possible.
             Some system libraries may still be linked dynamically, as are libraries for which
             there is no static library. So the resulting executable will still be dynamically
             linked, hence only <i>mostly</i> static.
           </p>
           <p>There are really three different ways to link an executable:</p>
           <ul>
           <li> STATIC with fully_static_link feature, in which everything is linked statically;
             e.g. "<code>gcc -static foo.o libbar.a libbaz.a -lm</code>".<br/>
             This mode is enabled by specifying <code>fully_static_link</code> in the
             <a href="${link common-definitions#features}"><code>features</code></a> attribute.</li>
           <li> STATIC, in which all user libraries are linked statically (if a static
             version is available), but where system libraries (excluding C/C++ runtime libraries)
             are linked dynamically, e.g. "<code>gcc foo.o libfoo.a libbaz.a -lm</code>".<br/>
             This mode is enabled by specifying <code>linkstatic=True</code>.</li>
           <li> DYNAMIC, in which all libraries are linked dynamically (if a dynamic version is
             available), e.g. "<code>gcc foo.o libfoo.so libbaz.so -lm</code>".<br/>
             This mode is enabled by specifying <code>linkstatic=False</code>.</li>
           </ul>
           <p>
           The <code>linkstatic</code> attribute has a different meaning if used on a
           <a href="${link cc_library}"><code>cc_library()</code></a> rule.
           For a C++ library, <code>linkstatic=True</code> indicates that only
           static linking is allowed, so no <code>.so</code> will be produced. linkstatic=False does
           not prevent static libraries from being created. The attribute is meant to control the
           creation of dynamic libraries.
           </p>
           <p>
           If <code>linkstatic=False</code>, then the build tool will create symlinks to
           depended-upon shared libraries in the <code>*.runfiles</code> area.
           </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("linkstatic", BOOLEAN).value(true))
          .add(
              attr("$def_parser", LABEL)
                  .cfg(HostTransition.createFactory())
                  .singleArtifact()
                  .value(
                      new Attribute.ComputedDefault() {
                        @Override
                        public Object getDefault(AttributeMap rule) {
                          // Every cc_rule depends implicitly on the def_parser tool.
                          // The only exceptions are the rules for building def_parser itself.
                          // To avoid cycles in the dependency graph, return null for rules under
                          // @bazel_tools//third_party/def_parser and @bazel_tools//tools/cpp
                          String label = rule.getLabel().toString();
                          String toolsRepository = env.getToolsRepository();
                          return label.startsWith(toolsRepository + "//third_party/def_parser")
                                  // @bazel_tools//tools/cpp:malloc and @bazel_tools//tools/cpp:stl
                                  // are implicit dependencies of all cc rules,
                                  // thus a dependency of the def_parser.
                                  || label.startsWith(toolsRepository + "//tools/cpp")
                              ? null
                              : env.getToolsLabel("//tools/def_parser:def_parser");
                        }
                      }))
          .build();
    }
    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$cc_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(CcDeclRule.class, CcBaseRule.class)
          .build();
    }
  }

  /**
   * Helper rule class.
   */
  public static final class CcLibraryBaseRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          /*<!-- #BLAZE_RULE($cc_library).ATTRIBUTE(hdrs) -->
           The list of header files published by
           this library to be directly included by sources in dependent rules.
          <p>This is the strongly preferred location for declaring header files that
             describe the interface for the library. These headers will be made
             available for inclusion by sources in this rule or in dependent rules.
             Headers not meant to be included by a client of this library should be
             listed in the <code>srcs</code> attribute instead, even if they are
             included by a published header. See <a href="#hdrs">"Header inclusion
             checking"</a> for a more detailed description. </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(
              attr("hdrs", LABEL_LIST)
                  .orderIndependent()
                  .direct_compile_time_input()
                  .allowedFileTypes(FileTypeSet.ANY_FILE))
          /* <!-- #BLAZE_RULE($cc_library).ATTRIBUTE(strip_include_prefix) -->
          The prefix to strip from the paths of the headers of this rule.

          <p>When set, the headers in the <code>hdrs</code> attribute of this rule are accessible
          at their path with this prefix cut off.

          <p>If it's a relative path, it's taken as a package-relative one. If it's an absolute one,
          it's understood as a repository-relative path.

          <p>The prefix in the <code>include_prefix</code> attribute is added after this prefix is
          stripped.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("strip_include_prefix", STRING))
          /* <!-- #BLAZE_RULE($cc_library).ATTRIBUTE(include_prefix) -->
          The prefix to add to the paths of the headers of this rule.

          <p>When set, the headers in the <code>hdrs</code> attribute of this rule are accessible
          at is the value of this attribute prepended to their repository-relative path.

          <p>The prefix in the <code>strip_include_prefix</code> attribute is removed before this
          prefix is added.
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(attr("include_prefix", STRING))
          /* <!-- #BLAZE_RULE($cc_library).ATTRIBUTE(textual_hdrs) -->
           The list of header files published by
           this library to be textually included by sources in dependent rules.
          <p>This is the location for declaring header files that cannot be compiled on their own;
             that is, they always need to be textually included by other source files to build valid
             code.</p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
          .add(
              attr("textual_hdrs", LABEL_LIST)
                  .orderIndependent()
                  .direct_compile_time_input()
                  .legacyAllowAnyFileType())
          // TODO(bazel-team): document or remove.
          .add(attr("linkstamp", LABEL).allowedFileTypes(CPP_SOURCE, C_SOURCE))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$cc_library")
          .type(RuleClassType.ABSTRACT)
          .ancestors(CcRule.class)
          .build();
    }
  }

  /** Helper rule class. */
  public static final class CcBinaryBaseRule implements RuleDefinition {
    private final GraphNodeAspect graphNodeAspect;

    public CcBinaryBaseRule(GraphNodeAspect graphNodeAspect) {
      this.graphNodeAspect = graphNodeAspect;
    }

    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          /*<!-- #BLAZE_RULE($cc_binary_base).ATTRIBUTE(additional_linker_inputs) -->
           Pass these files to the C++ linker command.
           <p>
           For example, compiled Windows .res files can be provided here to be embedded in
           the binary target.
           </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(
              attr("additional_linker_inputs", LABEL_LIST)
                  .orderIndependent()
                  .direct_compile_time_input()
                  .allowedFileTypes(FileTypeSet.ANY_FILE))
          .override(
              attr("deps", LABEL_LIST)
                  .allowedRuleClasses(DEPS_ALLOWED_RULES)
                  .allowedFileTypes(CppFileTypes.LINKER_SCRIPT)
                  .skipAnalysisTimeFileTypeCheck()
                  .mandatoryProviders(SkylarkProviderIdentifier.forKey(CcInfo.PROVIDER.getKey()))
                  .aspect(graphNodeAspect, GraphNodeAspect.ASPECT_PARAMETERS))
          .add(
              attr("dynamic_deps", LABEL_LIST)
                  .allowedFileTypes(FileTypeSet.NO_FILE)
                  .mandatoryProvidersList(
                      ImmutableList.of(
                          ImmutableList.of(
                              SkylarkProviderIdentifier.forKey(
                                  BazelCppSemantics.CC_SHARED_INFO_PROVIDER)),
                          ImmutableList.of(
                              SkylarkProviderIdentifier.forKey(
                                  BazelCppSemantics.CC_SHARED_INFO_PROVIDER_RULES_CC)))))
          /*<!-- #BLAZE_RULE($cc_binary_base).ATTRIBUTE(malloc) -->
          Override the default dependency on malloc.
          <p>
            By default, C++ binaries are linked against <code>//tools/cpp:malloc</code>,
            which is an empty library so the binary ends up using libc malloc.
            This label must refer to a <code>cc_library</code>. If compilation is for a non-C++
            rule, this option has no effect. The value of this attribute is ignored if
            <code>linkshared=True</code> is specified.
          </p>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(
              attr("malloc", LABEL)
                  .value(env.getToolsLabel("//tools/cpp:malloc"))
                  .allowedFileTypes()
                  .allowedRuleClasses("cc_library")
                  .aspect(graphNodeAspect, GraphNodeAspect.ASPECT_PARAMETERS))
          .add(attr(":default_malloc", LABEL).value(CppRuleClasses.DEFAULT_MALLOC))
          /*<!-- #BLAZE_RULE($cc_binary_base).ATTRIBUTE(stamp) -->
          Enable link stamping.
          Whether to encode build information into the binary. Possible values:
          <ul>
            <li><code>stamp = 1</code>: Stamp the build information into the
              binary. Stamped binaries are only rebuilt when their dependencies
              change. Use this if there are tests that depend on the build
              information.</li>
            <li><code>stamp = 0</code>: Always replace build information by constant
              values. This gives good build result caching.</li>
            <li><code>stamp = -1</code>: Embedding of build information is controlled
              by the <a href="../user-manual.html#flag--stamp">--[no]stamp</a> flag.</li>
          </ul>
          <!-- #END_BLAZE_RULE.ATTRIBUTE -->*/
          .add(attr("stamp", TRISTATE).value(TriState.AUTO))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$cc_binary_base")
          .type(RuleClassType.ABSTRACT)
          .ancestors(CcRule.class)
          .build();
    }
  }
}
