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

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.devtools.build.lib.analysis.TransitionMode.TARGET;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.Attribute.LabelLateBoundDefault;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.RuleErrorConsumer;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.cpp.AspectLegalCppSemantics;
import com.google.devtools.build.lib.rules.cpp.CcCommon;
import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper;
import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
import com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcLinkingContext;
import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper;
import com.google.devtools.build.lib.rules.cpp.CcLinkingOutputs;
import com.google.devtools.build.lib.rules.cpp.CcNativeLibraryProvider;
import com.google.devtools.build.lib.rules.cpp.CcToolchain;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppHelper;
import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
import com.google.devtools.build.lib.rules.cpp.CppSemantics;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink;
import com.google.devtools.build.lib.rules.proto.ProtoCommon;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder.Exports;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder.Services;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder.ToolchainInvocation;
import com.google.devtools.build.lib.rules.proto.ProtoConfiguration;
import com.google.devtools.build.lib.rules.proto.ProtoInfo;
import com.google.devtools.build.lib.rules.proto.ProtoLangToolchainProvider;
import com.google.devtools.build.lib.rules.proto.ProtoSourceFileBlacklist;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/** Part of the implementation of cc_proto_library. */
public abstract class CcProtoAspect extends NativeAspectClass implements ConfiguredAspectFactory {

  private static final String PROTO_TOOLCHAIN_ATTR = ":aspect_cc_proto_toolchain";

  private static final LabelLateBoundDefault<?> PROTO_TOOLCHAIN_LABEL =
      LabelLateBoundDefault.fromTargetConfiguration(
          ProtoConfiguration.class,
          Label.parseAbsoluteUnchecked("@com_google_protobuf//:cc_toolchain"),
          (rule, attributes, protoConfig) -> protoConfig.protoToolchainForCc());

  private final CppSemantics cppSemantics;
  private final LabelLateBoundDefault<?> ccToolchainAttrValue;
  private final Label ccToolchainType;

  protected CcProtoAspect(AspectLegalCppSemantics cppSemantics, RuleDefinitionEnvironment env) {
    this.cppSemantics = cppSemantics;
    this.ccToolchainAttrValue = CppRuleClasses.ccToolchainAttribute(env);
    this.ccToolchainType = CppRuleClasses.ccToolchainTypeAttribute(env);
  }

  @Override
  public ConfiguredAspect create(
      ConfiguredTargetAndData ctadBase,
      RuleContext ruleContext,
      AspectParameters parameters,
      String toolsRepository)
      throws InterruptedException, ActionConflictException {
    ProtoInfo protoInfo = checkNotNull(ctadBase.getConfiguredTarget().get(ProtoInfo.PROVIDER));

    try {
      ConfiguredAspect.Builder result = new ConfiguredAspect.Builder(ruleContext);
      new Impl(ruleContext, protoInfo, cppSemantics, ccToolchainType).addProviders(result);
      return result.build();
    } catch (RuleErrorException e) {
      ruleContext.ruleError(e.getMessage());
      return null;
    }
  }

  @Override
  public AspectDefinition getDefinition(AspectParameters aspectParameters) {
    AspectDefinition.Builder result =
        new AspectDefinition.Builder(this)
            .propagateAlongAttribute("deps")
            .requiresConfigurationFragments(CppConfiguration.class, ProtoConfiguration.class)
            .requireStarlarkProviders(ProtoInfo.PROVIDER.id())
            .addRequiredToolchains(ccToolchainType)
            .add(
                attr(PROTO_TOOLCHAIN_ATTR, LABEL)
                    .mandatoryNativeProviders(ImmutableList.of(ProtoLangToolchainProvider.class))
                    .value(PROTO_TOOLCHAIN_LABEL))
            .add(
                attr(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, LABEL)
                    .mandatoryProviders(CcToolchainProvider.PROVIDER.id())
                    .value(ccToolchainAttrValue));

    return result.build();
  }

  private static class Impl {

    private final TransitiveInfoProviderMap ccLibraryProviders;
    private final ProtoCcHeaderProvider headerProvider;
    private final ImmutableMap<String, NestedSet<Artifact>> outputGroups;

    private final RuleContext ruleContext;
    private final ProtoInfo protoInfo;
    private final CppSemantics cppSemantics;
    private final NestedSetBuilder<Artifact> filesBuilder;
    private final Label ccToolchainType;

    Impl(
        RuleContext ruleContext,
        ProtoInfo protoInfo,
        CppSemantics cppSemantics,
        Label ccToolchainType)
        throws RuleErrorException, InterruptedException {
      this.ruleContext = ruleContext;
      this.protoInfo = protoInfo;
      this.cppSemantics = cppSemantics;
      this.ccToolchainType = ccToolchainType;
      FeatureConfiguration featureConfiguration = getFeatureConfiguration();
      ProtoConfiguration protoConfiguration = ruleContext.getFragment(ProtoConfiguration.class);

      ImmutableList.Builder<TransitiveInfoCollection> depsBuilder = ImmutableList.builder();
      TransitiveInfoCollection runtime = getProtoToolchainProvider().runtime();
      if (runtime != null) {
        depsBuilder.add(runtime);
      }
      depsBuilder.addAll(ruleContext.getPrerequisites("deps", TARGET));
      ImmutableList<TransitiveInfoCollection> deps = depsBuilder.build();

      checkProtoLibrariesInDeps(ruleContext, deps);
      CcCompilationHelper compilationHelper =
          initializeCompilationHelper(featureConfiguration, deps);

      // Compute and register files generated by this proto library.
      Collection<Artifact> outputs = new ArrayList<>();
      if (areSrcsBlacklisted()) {
        registerBlacklistedSrcs(protoInfo, protoConfiguration, compilationHelper);
        headerProvider = null;
      } else if (!protoInfo.getDirectProtoSources().isEmpty()) {
        Collection<Artifact> headers =
            getOutputFiles(protoConfiguration.ccProtoLibraryHeaderSuffixes());
        Collection<Artifact> sources =
            getOutputFiles(protoConfiguration.ccProtoLibrarySourceSuffixes());
        outputs.addAll(headers);
        outputs.addAll(sources);

        compilationHelper.addSources(sources);
        compilationHelper.addPublicHeaders(headers);

        NestedSetBuilder<Artifact> publicHeaderPaths = NestedSetBuilder.stableOrder();
        publicHeaderPaths.addAll(headers);
        headerProvider = new ProtoCcHeaderProvider(publicHeaderPaths.build());
      } else {
        // If this proto_library doesn't have sources, it provides the combined headers of all its
        // direct dependencies. Thus, if a direct dependency does have sources, the generated files
        // are also provided by this library. If a direct dependency does not have sources, it will
        // do the same thing, so that effectively this library looks through all source-less
        // proto_libraries and provides all generated headers of the proto_libraries with sources
        // that it depends on.
        NestedSetBuilder<Artifact> transitiveHeaders = NestedSetBuilder.stableOrder();
        for (ProtoCcHeaderProvider provider :
            ruleContext.getPrerequisites("deps", TARGET, ProtoCcHeaderProvider.class)) {
          compilationHelper.addPublicTextualHeaders(provider.getHeaders());
          transitiveHeaders.addTransitive(provider.getHeaders());
        }
        headerProvider = new ProtoCcHeaderProvider(transitiveHeaders.build());
      }

      filesBuilder = NestedSetBuilder.stableOrder();
      filesBuilder.addAll(outputs);
      createProtoCompileAction(outputs);

      CompilationInfo compilationInfo = compilationHelper.compile();
      CcCompilationOutputs ccCompilationOutputs = compilationInfo.getCcCompilationOutputs();
      CcLinkingHelper ccLinkingHelper = initializeLinkingHelper(featureConfiguration, deps);
      if (ccToolchain(ruleContext).supportsInterfaceSharedLibraries(featureConfiguration)) {
        ccLinkingHelper.emitInterfaceSharedLibraries(true);
      }

      ImmutableList<LibraryToLink> libraryToLink = ImmutableList.of();
      if (!ccCompilationOutputs.isEmpty()) {
        CcLinkingOutputs ccLinkingOutputs = ccLinkingHelper.link(ccCompilationOutputs);
        if (!ccLinkingOutputs.isEmpty()) {
          libraryToLink = ImmutableList.of(ccLinkingOutputs.getLibraryToLink());
        }
      }
      CcNativeLibraryProvider ccNativeLibraryProvider =
          CppHelper.collectNativeCcLibraries(deps, libraryToLink);
      CcLinkingContext ccLinkingContext =
          ccLinkingHelper.buildCcLinkingContextFromLibrariesToLink(
              libraryToLink, compilationInfo.getCcCompilationContext());

      ccLibraryProviders =
          new TransitiveInfoProviderMapBuilder()
              .put(
                  CcInfo.builder()
                      .setCcCompilationContext(compilationInfo.getCcCompilationContext())
                      .setCcLinkingContext(ccLinkingContext)
                      .setCcDebugInfoContext(
                          CppHelper.mergeCcDebugInfoContexts(
                              compilationInfo.getCcCompilationOutputs(),
                              AnalysisUtils.getProviders(deps, CcInfo.PROVIDER)))
                      .build())
              .add(ccNativeLibraryProvider)
              .build();
      outputGroups =
          ImmutableMap.copyOf(
              CcCompilationHelper.buildOutputGroups(compilationInfo.getCcCompilationOutputs()));
      // On Windows, dynamic library is not built by default, so don't add them to filesToBuild.

      if (!libraryToLink.isEmpty()) {
        LibraryToLink artifactsToBuild = libraryToLink.get(0);
        if (artifactsToBuild.getStaticLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getStaticLibrary());
        }
        if (artifactsToBuild.getPicStaticLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getPicStaticLibrary());
        }
        if (!featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
          if (artifactsToBuild.getResolvedSymlinkDynamicLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getResolvedSymlinkDynamicLibrary());
          } else if (artifactsToBuild.getDynamicLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getDynamicLibrary());
          }
          if (artifactsToBuild.getResolvedSymlinkInterfaceLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getResolvedSymlinkInterfaceLibrary());
          } else if (artifactsToBuild.getInterfaceLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getInterfaceLibrary());
          }
        }
      }
    }

    private static void checkProtoLibrariesInDeps(
        RuleErrorConsumer ruleErrorConsumer, Iterable<TransitiveInfoCollection> deps) {
      for (TransitiveInfoCollection dep : deps) {
        if (dep.get(ProtoInfo.PROVIDER) != null && dep.get(CcInfo.PROVIDER) == null) {
          ruleErrorConsumer.attributeError(
              "deps",
              String.format("proto_library '%s' does not produce output for C++", dep.getLabel()));
        }
      }
    }

    private boolean areSrcsBlacklisted() {
      return !new ProtoSourceFileBlacklist(
              ruleContext, getProtoToolchainProvider().blacklistedProtos())
          .checkSrcs(protoInfo.getOriginalDirectProtoSources(), "cc_proto_library");
    }

    private FeatureConfiguration getFeatureConfiguration() {
      ImmutableSet.Builder<String> requestedFeatures = new ImmutableSet.Builder<>();
      requestedFeatures.addAll(ruleContext.getFeatures());
      ImmutableSet.Builder<String> unsupportedFeatures = new ImmutableSet.Builder<>();
      unsupportedFeatures.addAll(ruleContext.getDisabledFeatures());
      unsupportedFeatures.add(CppRuleClasses.PARSE_HEADERS);
      unsupportedFeatures.add(CppRuleClasses.LAYERING_CHECK);
      if (!areSrcsBlacklisted() && !protoInfo.getDirectProtoSources().isEmpty()) {
        requestedFeatures.add(CppRuleClasses.HEADER_MODULES);
      } else {
        unsupportedFeatures.add(CppRuleClasses.HEADER_MODULES);
      }
      FeatureConfiguration featureConfiguration =
          CcCommon.configureFeaturesOrReportRuleError(
              ruleContext,
              requestedFeatures.build(),
              unsupportedFeatures.build(),
              ccToolchain(ruleContext),
              cppSemantics);
      return featureConfiguration;
    }

    private CcCompilationHelper initializeCompilationHelper(
        FeatureConfiguration featureConfiguration, List<TransitiveInfoCollection> deps)
        throws InterruptedException {
      CcCommon common = new CcCommon(ruleContext);
      CcToolchainProvider toolchain = ccToolchain(ruleContext);
      CcCompilationHelper helper =
          new CcCompilationHelper(
                  ruleContext,
                  ruleContext,
                  ruleContext.getLabel(),
                  CppHelper.getGrepIncludes(ruleContext),
                  cppSemantics,
                  featureConfiguration,
                  toolchain,
                  toolchain.getFdoContext(),
                  TargetUtils.getExecutionInfo(
                      ruleContext.getRule(), ruleContext.isAllowTagsPropagation()),
                  /* shouldProcessHeaders= */ true)
              .addCcCompilationContexts(CppHelper.getCompilationContextsFromDeps(deps))
              .addCcCompilationContexts(
                  ImmutableList.of(CcCompilationHelper.getStlCcCompilationContext(ruleContext)))
              .setPurpose(common.getPurpose(cppSemantics));
      // Don't instrument the generated C++ files even when --collect_code_coverage is set.
      helper.setCodeCoverageEnabled(false);

      String protoRoot = protoInfo.getDirectProtoSourceRoot();
      PathFragment repositoryRoot =
          ruleContext.getLabel().getPackageIdentifier().getRepository().getSourceRoot();
      if (protoRoot.equals(".") || protoRoot.equals(repositoryRoot.getPathString())) {
        return helper;
      }

      PathFragment protoRootFragment = PathFragment.create(protoRoot);
      PathFragment binOrGenfiles = ruleContext.getBinOrGenfilesDirectory().getExecPath();
      if (protoRootFragment.startsWith(binOrGenfiles)) {
        protoRootFragment = protoRootFragment.relativeTo(binOrGenfiles);
      }
      PathFragment repositoryPath =
          ruleContext
              .getLabel()
              .getPackageIdentifier()
              .getRepository()
              .getExecPath(
                  ruleContext
                      .getAnalysisEnvironment()
                      .getStarlarkSemantics()
                      .experimentalSiblingRepositoryLayout());
      if (protoRootFragment.startsWith(repositoryPath)) {
        protoRootFragment = protoRootFragment.relativeTo(repositoryPath);
      }

      String stripIncludePrefix =
          PathFragment.create("//").getRelative(protoRootFragment).toString();
      helper.setStripIncludePrefix(stripIncludePrefix);

      return helper;
    }

    private CcLinkingHelper initializeLinkingHelper(
        FeatureConfiguration featureConfiguration, ImmutableList<TransitiveInfoCollection> deps)
        throws InterruptedException {
      CcToolchainProvider toolchain = ccToolchain(ruleContext);
      CcLinkingHelper helper =
          new CcLinkingHelper(
                  ruleContext,
                  ruleContext.getLabel(),
                  ruleContext,
                  ruleContext,
                  cppSemantics,
                  featureConfiguration,
                  toolchain,
                  toolchain.getFdoContext(),
                  ruleContext.getConfiguration(),
                  ruleContext.getFragment(CppConfiguration.class),
                  ruleContext.getSymbolGenerator(),
                  TargetUtils.getExecutionInfo(
                      ruleContext.getRule(), ruleContext.isAllowTagsPropagation()))
              .setGrepIncludes(CppHelper.getGrepIncludes(ruleContext))
              .setTestOrTestOnlyTarget(ruleContext.isTestOnlyTarget());
      helper.addCcLinkingContexts(CppHelper.getLinkingContextsFromDeps(deps));
      // TODO(dougk): Configure output artifact with action_config
      // once proto compile action is configurable from the crosstool.
      if (!toolchain.supportsDynamicLinker(featureConfiguration)) {
        helper.setShouldCreateDynamicLibrary(false);
      }
      return helper;
    }

    private CcToolchainProvider ccToolchain(RuleContext ruleContext) {
      return CppHelper.getToolchain(
          ruleContext,
          ruleContext.getPrerequisite(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, TARGET),
          ccToolchainType);
    }

    private ImmutableSet<Artifact> getOutputFiles(Iterable<String> suffixes) {
      ImmutableSet.Builder<Artifact> result = ImmutableSet.builder();
      for (String suffix : suffixes) {
        result.addAll(
            ProtoCommon.getGeneratedOutputs(
                ruleContext, protoInfo.getDirectProtoSources(), suffix));
      }
      return result.build();
    }

    private static void registerBlacklistedSrcs(
        ProtoInfo protoInfo, ProtoConfiguration protoConfiguration, CcCompilationHelper helper) {
      // Hack: This is a proto_library for descriptor.proto or similar.
      //
      // The headers of those libraries are precomputed . They are also explicitly part of normal
      // cc_library rules that export them in their 'hdrs' attribute, and compile them as header
      // module if requested.
      //
      // The sole purpose of a proto_library with blacklisted srcs is so other proto_library rules
      // can import them from a protocol buffer, as proto_library rules can only depend on other
      // proto library rules.
      ImmutableList.Builder<PathFragment> headers = new ImmutableList.Builder<>();
      for (Artifact source : protoInfo.getDirectProtoSources()) {
        for (String suffix : protoConfiguration.ccProtoLibraryHeaderSuffixes()) {
          headers.add(FileSystemUtils.replaceExtension(source.getRootRelativePath(), suffix));
        }
      }
      // We add the header to the proto_library's module map as additional (textual) header for
      // two reasons:
      // 1. The header will be exported via a normal cc_library, and a header must only be exported
      //    non-textually from one library.
      // 2. We want to allow proto_library rules that depend on the bootstrap-hack proto_library
      //    to be layering-checked; we need to provide a module map for the layering check to work.
      helper.addAdditionalExportedHeaders(headers.build());
    }

    private void createProtoCompileAction(Collection<Artifact> outputs)
        throws InterruptedException {
      PathFragment protoRootFragment = PathFragment.create(protoInfo.getDirectProtoSourceRoot());
      String genfilesPath;
      PathFragment genfilesFragment = ruleContext.getConfiguration().getGenfilesFragment();
      if (protoRootFragment.startsWith(genfilesFragment)) {
        genfilesPath = protoRootFragment.getPathString();
      } else {
        genfilesPath = genfilesFragment.getRelative(protoRootFragment).getPathString();
      }

      ImmutableList.Builder<ToolchainInvocation> invocations = ImmutableList.builder();
      invocations.add(
          new ToolchainInvocation("C++", checkNotNull(getProtoToolchainProvider()), genfilesPath));
      ProtoCompileActionBuilder.registerActions(
          ruleContext,
          invocations.build(),
          protoInfo,
          ruleContext.getLabel(),
          outputs,
          "C++",
          Exports.DO_NOT_USE,
          Services.ALLOW);
    }

    private ProtoLangToolchainProvider getProtoToolchainProvider() {
      return ruleContext.getPrerequisite(
          PROTO_TOOLCHAIN_ATTR, TARGET, ProtoLangToolchainProvider.class);
    }

    public void addProviders(ConfiguredAspect.Builder builder) {
      OutputGroupInfo outputGroupInfo = new OutputGroupInfo(outputGroups);
      builder.addProvider(
          new CcProtoLibraryProviders(
              filesBuilder.build(), ccLibraryProviders, outputGroupInfo));
      builder.addProviders(ccLibraryProviders);
      builder.addNativeDeclaredProvider(outputGroupInfo);
      if (headerProvider != null) {
        builder.addProvider(headerProvider);
      }
    }
  }
}
