| // Copyright 2017 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; |
| |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableList.Builder; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.analysis.RuleContext; |
| import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration; |
| import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables; |
| import java.util.regex.Pattern; |
| |
| /** Handles creation of CppCompileAction used to compile linkstamp sources. */ |
| public class CppLinkstampCompileHelper { |
| |
| /** |
| * Creates {@link CppCompileAction} to compile linkstamp source |
| * |
| * @param inputsForInvalidation: see {@link CppCompileAction#inputsForInvalidation} |
| */ |
| public static CppCompileAction createLinkstampCompileAction( |
| RuleContext ruleContext, |
| Artifact sourceFile, |
| Artifact outputFile, |
| Iterable<Artifact> compilationInputs, |
| Iterable<Artifact> nonCodeInputs, |
| Iterable<Artifact> inputsForInvalidation, |
| ImmutableList<Artifact> buildInfoHeaderArtifacts, |
| Iterable<String> additionalLinkstampDefines, |
| CcToolchainProvider ccToolchainProvider, |
| boolean codeCoverageEnabled, |
| CppConfiguration cppConfiguration, |
| String fdoBuildStamp, |
| FeatureConfiguration featureConfiguration, |
| boolean needsPic, |
| String labelReplacement, |
| String outputReplacement, |
| CppSemantics semantics) { |
| CppCompileActionBuilder builder = |
| new CppCompileActionBuilder(ruleContext, ccToolchainProvider) |
| .addMandatoryInputs(compilationInputs) |
| .setVariables( |
| getVariables( |
| sourceFile, |
| outputFile, |
| labelReplacement, |
| outputReplacement, |
| additionalLinkstampDefines, |
| buildInfoHeaderArtifacts, |
| featureConfiguration, |
| cppConfiguration, |
| ccToolchainProvider, |
| needsPic, |
| fdoBuildStamp, |
| codeCoverageEnabled)) |
| .setFeatureConfiguration(featureConfiguration) |
| .setSourceFile(sourceFile) |
| .setSemantics(semantics) |
| .setOutputs(outputFile, null) |
| .setInputsForInvalidation(inputsForInvalidation) |
| .setBuiltinIncludeFiles(buildInfoHeaderArtifacts) |
| .addMandatoryInputs(nonCodeInputs) |
| .setCppConfiguration(cppConfiguration) |
| .setActionName(CppCompileAction.LINKSTAMP_COMPILE); |
| semantics.finalizeCompileActionBuilder(ruleContext, builder); |
| return builder.buildOrThrowIllegalStateException(); |
| } |
| |
| private static ImmutableList<String> computeAllLinkstampDefines( |
| String labelReplacement, |
| String outputReplacement, |
| Iterable<String> additionalLinkstampDefines, |
| CppConfiguration cppConfiguration, |
| String fdoBuildStamp, |
| boolean codeCoverageEnabled) { |
| String labelPattern = Pattern.quote("${LABEL}"); |
| String outputPathPattern = Pattern.quote("${OUTPUT_PATH}"); |
| Builder<String> defines = |
| ImmutableList.<String>builder() |
| .add("GPLATFORM=\"" + cppConfiguration + "\"") |
| .add("BUILD_COVERAGE_ENABLED=" + (codeCoverageEnabled ? "1" : "0")) |
| // G3_VERSION_INFO and G3_TARGET_NAME are C string literals that normally |
| // contain the label of the target being linked. However, they are set |
| // differently when using shared native deps. In that case, a single .so file |
| // is shared by multiple targets, and its contents cannot depend on which |
| // target(s) were specified on the command line. So in that case we have |
| // to use the (obscure) name of the .so file instead, or more precisely |
| // the path of the .so file relative to the workspace root. |
| .add("G3_VERSION_INFO=\"${LABEL}\"") |
| .add("G3_TARGET_NAME=\"${LABEL}\"") |
| // G3_BUILD_TARGET is a C string literal containing the output of this |
| // link. (An undocumented and untested invariant is that G3_BUILD_TARGET is the |
| // location of the executable, either absolutely, or relative to the directory part of |
| // BUILD_INFO.) |
| .add("G3_BUILD_TARGET=\"${OUTPUT_PATH}\"") |
| .addAll(additionalLinkstampDefines); |
| |
| if (fdoBuildStamp != null) { |
| defines.add(CppConfiguration.FDO_STAMP_MACRO + "=\"" + fdoBuildStamp + "\""); |
| } |
| |
| return defines |
| .build() |
| .stream() |
| .map( |
| define -> |
| define |
| .replaceAll(labelPattern, labelReplacement) |
| .replaceAll(outputPathPattern, outputReplacement)) |
| .collect(ImmutableList.toImmutableList()); |
| } |
| |
| private static Variables getVariables( |
| Artifact sourceFile, |
| Artifact outputFile, |
| String labelReplacement, |
| String outputReplacement, |
| Iterable<String> additionalLinkstampDefines, |
| ImmutableList<Artifact> buildInfoHeaderArtifacts, |
| FeatureConfiguration featureConfiguration, |
| CppConfiguration cppConfiguration, |
| CcToolchainProvider ccToolchainProvider, |
| boolean needsPic, |
| String fdoBuildStamp, |
| boolean codeCoverageEnabled) { |
| // TODO(b/34761650): Remove all this hardcoding by separating a full blown compile action. |
| Preconditions.checkArgument( |
| featureConfiguration.actionIsConfigured(CppCompileAction.LINKSTAMP_COMPILE)); |
| |
| Variables.Builder variables = new Variables.Builder(ccToolchainProvider.getBuildVariables()); |
| // We need to force inclusion of build_info headers |
| variables.addStringSequenceVariable( |
| CcCommon.INCLUDES_VARIABLE_NAME, |
| buildInfoHeaderArtifacts |
| .stream() |
| .map(Artifact::getExecPathString) |
| .collect(ImmutableList.toImmutableList())); |
| // Input/Output files. |
| variables.addStringVariable( |
| CcCompilationHelper.SOURCE_FILE_VARIABLE_NAME, sourceFile.getExecPathString()); |
| variables.addStringVariable( |
| CcCompilationHelper.OUTPUT_FILE_VARIABLE_NAME, outputFile.getExecPathString()); |
| variables.addStringVariable( |
| CcCompilationHelper.OUTPUT_OBJECT_FILE_VARIABLE_NAME, outputFile.getExecPathString()); |
| // Include directories for (normal includes with ".", empty quote- and system- includes). |
| variables.addStringSequenceVariable( |
| CcCompilationHelper.INCLUDE_PATHS_VARIABLE_NAME, ImmutableList.of(".")); |
| variables.addStringSequenceVariable( |
| CcCompilationHelper.QUOTE_INCLUDE_PATHS_VARIABLE_NAME, ImmutableList.of()); |
| variables.addStringSequenceVariable( |
| CcCompilationHelper.SYSTEM_INCLUDE_PATHS_VARIABLE_NAME, ImmutableList.of()); |
| // Legacy flags coming from fields such as compiler_flag |
| variables.addLazyStringSequenceVariable( |
| CcCompilationHelper.LEGACY_COMPILE_FLAGS_VARIABLE_NAME, |
| CcCompilationHelper.getLegacyCompileFlagsSupplier( |
| cppConfiguration, |
| ccToolchainProvider, |
| sourceFile.getExecPathString(), |
| ImmutableSet.of())); |
| // Unfilterable flags coming from unfiltered_cxx_flag fields |
| variables.addLazyStringSequenceVariable( |
| CcCompilationHelper.UNFILTERED_COMPILE_FLAGS_VARIABLE_NAME, |
| CcCompilationHelper.getUnfilteredCompileFlagsSupplier( |
| ccToolchainProvider, ImmutableSet.of())); |
| // Collect all preprocessor defines, and in each replace ${LABEL} by labelReplacements, and |
| // ${OUTPUT_PATH} with outputPathReplacement. |
| variables.addStringSequenceVariable( |
| CcCompilationHelper.PREPROCESSOR_DEFINES_VARIABLE_NAME, |
| computeAllLinkstampDefines( |
| labelReplacement, |
| outputReplacement, |
| additionalLinkstampDefines, |
| cppConfiguration, |
| fdoBuildStamp, |
| codeCoverageEnabled)); |
| // For dynamic libraries, produce position independent code. |
| if (needsPic) { |
| variables.addStringVariable(CcCompilationHelper.PIC_VARIABLE_NAME, ""); |
| } |
| |
| return variables.build(); |
| } |
| } |