blob: 0a8ab0dd6fda7f32c83e7caf5cacd82784532d06 [file] [log] [blame]
// Copyright 2020 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 static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.util.Crosstool.CcToolchainConfig;
import com.google.devtools.build.lib.packages.util.MockCcSupport;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for cc_binary with ThinLTO. */
@RunWith(JUnit4.class)
public class CcBinaryThinLtoTest extends BuildViewTestCase {
@Before
public void createBasePkg() throws IOException {
scratch.overwriteFile(
"base/BUILD", "cc_library(name = 'system_malloc', visibility = ['//visibility:public'])");
}
public void createBuildFiles(String targetName, String... extraCcBinaryParameters)
throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"",
"cc_binary(name = '" + targetName + "',",
" srcs = ['binfile.cc', ],",
" deps = [ ':lib' ], ",
String.join("", extraCcBinaryParameters),
" malloc = '//base:system_malloc')",
"cc_library(name = 'lib',",
" srcs = ['libfile.cc'],",
" hdrs = ['libfile.h'],",
" linkstamp = 'linkstamp.cc',",
" )");
scratch.file("pkg/binfile.cc", "#include \"pkg/libfile.h\"", "int main() { return pkg(); }");
scratch.file("pkg/libfile.cc", "int pkg() { return 42; }");
scratch.file("pkg/libfile.h", "int pkg();");
scratch.file("pkg/linkstamp.cc");
}
public void createTestFiles(String extraTestParameters, String extraLibraryParameters)
throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"cc_test(",
" name = 'bin_test',",
" srcs = ['bin_test.cc', ],",
" deps = [ ':lib' ], ",
extraTestParameters,
" malloc = '//base:system_malloc'",
")",
"cc_test(",
" name = 'bin_test2',",
" srcs = ['bin_test2.cc', ],",
" deps = [ ':lib' ], ",
extraTestParameters,
" malloc = '//base:system_malloc'",
")",
"cc_library(",
" name = 'lib',",
" srcs = ['libfile.cc'],",
" hdrs = ['libfile.h'],",
extraLibraryParameters,
" linkstamp = 'linkstamp.cc',",
")");
scratch.file("pkg/bin_test.cc", "#include \"pkg/libfile.h\"", "int main() { return pkg(); }");
scratch.file("pkg/bin_test2.cc", "#include \"pkg/libfile.h\"", "int main() { return pkg(); }");
scratch.file("pkg/libfile.cc", "int pkg() { return 42; }");
scratch.file("pkg/libfile.h", "int pkg();");
scratch.file("pkg/linkstamp.cc");
}
@Test
public void testActionGraph() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration("--noincompatible_make_thinlto_command_lines_standalone");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
{.o.thinlto.bc,.o.imports} <=[LTOIndexing]=
.o <= [CppCompile] .cc
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
assertThat(ActionsTestUtil.getFirstArtifactEndingWith(linkAction.getInputs(), "linkstamp.o"))
.isNotNull();
List<String> commandLine = linkAction.getLinkCommandLine().getRawLinkArgv();
String prefix = getTargetConfiguration().getOutputDirectory(RepositoryName.MAIN)
.getExecPathString();
assertThat(commandLine)
.containsAtLeast(
prefix + "/bin/pkg/bin.lto.merged.o",
"thinlto_param_file=" + prefix + "/bin/pkg/bin-lto-final.params")
.inOrder();
// We have no bitcode files: all files have pkg/bin.lto/
for (String arg : commandLine) {
if (arg.contains("_objs") && !arg.contains("linkstamp.o")) {
assertThat(arg).contains("pkg/bin.lto");
}
}
assertThat(artifactsToStrings(linkAction.getInputs()))
.containsAtLeast(
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.o",
"bin pkg/bin.lto/pkg/_objs/lib/libfile.pic.o",
"bin pkg/bin-2.params",
"bin pkg/bin-lto-final.params");
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(artifactsToStrings(backendAction.getInputs()))
.containsAtLeast(
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.thinlto.bc",
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.imports");
assertThat(backendAction.getArguments())
.containsAtLeast(
"thinlto_index=" + prefix + "/bin/pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.thinlto.bc",
"thinlto_output_object_file=" + prefix + "/bin/pkg/bin.lto/pkg/_objs/bin/binfile.pic.o",
"thinlto_input_bitcode_file=" + prefix + "/bin/pkg/_objs/bin/binfile.pic.o");
CppLinkAction indexAction =
(CppLinkAction)
getPredecessorByInputName(
backendAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.thinlto.bc");
ConfiguredTargetValue configuredTargetValue =
(ConfiguredTargetValue)
getSkyframeExecutor()
.getEvaluatorForTesting()
.getExistingEntryAtLatestVersion(
ConfiguredTargetKey.of(pkg.getLabel(), getConfiguration(pkg)))
.getValue();
ImmutableList<ActionAnalysisMetadata> linkstampCompileActions =
configuredTargetValue
.getActions()
.stream()
.filter(a -> a.getMnemonic().equals("CppLinkstampCompile"))
.collect(ImmutableList.toImmutableList());
assertThat(linkstampCompileActions).hasSize(1);
ActionAnalysisMetadata linkstampCompileAction = linkstampCompileActions.get(0);
assertThat(indexAction.getInputs().toList())
.doesNotContain(linkstampCompileAction.getOutputs());
assertThat(indexAction.getArguments())
.containsAtLeast(
"param_file=" + prefix + "/bin/pkg/bin-lto-final.params",
"prefix_replace=" + prefix + "/bin;" + prefix + "/bin/pkg/bin.lto",
"thinlto_merged_object_file=" + prefix + "/bin/pkg/bin.lto.merged.o",
"object_suffix_replace=.indexing.o;.o");
assertThat(indexAction.getArguments())
.doesNotContain("thinlto_param_file=" + prefix + "/bin/pkg/bin-lto-final.params");
assertThat(artifactsToStrings(indexAction.getOutputs()))
.containsAtLeast(
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.imports",
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.thinlto.bc",
"bin pkg/bin.lto/pkg/_objs/lib/libfile.pic.o.imports",
"bin pkg/bin.lto/pkg/_objs/lib/libfile.pic.o.thinlto.bc",
"bin pkg/bin-lto-final.params");
assertThat(indexAction.getMnemonic()).isEqualTo("CppLTOIndexing");
assertThat(artifactsToStrings(indexAction.getInputs()))
.containsAtLeast(
"bin pkg/_objs/bin/binfile.pic.indexing.o", "bin pkg/_objs/lib/libfile.pic.indexing.o");
CppCompileAction bitcodeAction =
(CppCompileAction)
getPredecessorByInputName(indexAction, "pkg/_objs/bin/binfile.pic.indexing.o");
assertThat(bitcodeAction.getMnemonic()).isEqualTo("CppCompile");
assertThat(bitcodeAction.getArguments())
.contains("lto_indexing_bitcode=" + prefix + "/bin/pkg/_objs/bin/binfile.pic.indexing.o");
}
@Test
public void testLinkshared() throws Exception {
createBuildFiles("bin.so", "linkshared = 1,");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_PIC,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration();
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin.so");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
Action backendAction =
getPredecessorByInputName(linkAction, "pkg/bin.so.lto/pkg/_objs/bin.so/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
}
@Test
public void testNoLinkstatic() throws Exception {
createBuildFiles("bin", "linkstatic = 0,");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_DYNAMIC_LINKER,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES));
useConfiguration("--noincompatible_make_thinlto_command_lines_standalone");
/*
We follow the chain from the final product backwards to verify intermediate actions.
binary <=[Link]=
.ifso <=[SolibSymlink]=
_S...ifso <=[SolibSymlink]=
.ifso <=[Link]=
.lto/...o <=[LTOBackend]=
{.o.thinlto.bc,.o.imports} <=[LTOIndexing]=
.o <= [CppCompile] .cc
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
List<String> commandLine = linkAction.getLinkCommandLine().getRawLinkArgv();
String prefix = getTargetConfiguration().getOutputDirectory(RepositoryName.MAIN)
.getExecPathString();
assertThat(commandLine).contains("-Wl,@" + prefix + "/bin/pkg/bin-lto-final.params");
// We have no bitcode files: all files have pkg/bin.lto/
for (String arg : commandLine) {
if (arg.contains("_objs") && !arg.contains("linkstamp.o")) {
assertThat(arg).contains("pkg/bin.lto");
}
}
assertThat(artifactsToStrings(linkAction.getInputs()))
.containsAtLeast(
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.o",
"bin _solib_k8/libpkg_Sliblib.ifso",
"bin pkg/bin-2.params",
"bin pkg/bin-lto-final.params");
SolibSymlinkAction solibSymlinkAction =
(SolibSymlinkAction) getPredecessorByInputName(linkAction, "_solib_k8/libpkg_Sliblib.ifso");
assertThat(solibSymlinkAction.getMnemonic()).isEqualTo("SolibSymlink");
CppLinkAction libLinkAction =
(CppLinkAction) getPredecessorByInputName(solibSymlinkAction, "bin/pkg/liblib.ifso");
assertThat(libLinkAction.getMnemonic()).isEqualTo("CppLink");
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(
libLinkAction, "pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(artifactsToStrings(backendAction.getInputs()))
.contains("bin pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o.thinlto.bc");
assertThat(backendAction.getArguments())
.containsAtLeast(
"thinlto_index="
+ prefix
+ "/bin/pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o.thinlto.bc",
"thinlto_output_object_file="
+ prefix
+ "/bin/pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o",
"thinlto_input_bitcode_file=" + prefix + "/bin/pkg/_objs/lib/libfile.pic.o");
CppLinkAction indexAction =
(CppLinkAction)
getPredecessorByInputName(
backendAction, "pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o.thinlto.bc");
assertThat(indexAction.getArguments())
.containsAtLeast(
"param_file=" + prefix + "/bin/pkg/liblib.so-lto-final.params",
"prefix_replace=" + prefix + "/bin;" + prefix + "/bin/pkg/liblib.so.lto",
"object_suffix_replace=.indexing.o;.o");
assertThat(artifactsToStrings(indexAction.getOutputs()))
.containsAtLeast(
"bin pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o.imports",
"bin pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o.thinlto.bc",
"bin pkg/liblib.so-lto-final.params");
assertThat(indexAction.getMnemonic()).isEqualTo("CppLTOIndexing");
assertThat(artifactsToStrings(indexAction.getInputs()))
.contains("bin pkg/_objs/lib/libfile.pic.indexing.o");
CppCompileAction bitcodeAction =
(CppCompileAction)
getPredecessorByInputName(indexAction, "pkg/_objs/lib/libfile.pic.indexing.o");
assertThat(bitcodeAction.getMnemonic()).isEqualTo("CppCompile");
assertThat(bitcodeAction.getArguments())
.contains("lto_indexing_bitcode=" + prefix + "/bin/pkg/_objs/lib/libfile.pic.indexing.o");
}
/** Helper method to get the root prefix from the given dwpFile. */
private static PathFragment dwpRootPrefix(Artifact dwpFile) throws Exception {
return dwpFile
.getExecPath()
.subFragment(
0, dwpFile.getExecPath().segmentCount() - dwpFile.getRootRelativePath().segmentCount());
}
/** Helper method that checks that a .dwp has the expected generating action structure. */
private void validateDwp(
RuleContext ruleContext,
Artifact dwpFile,
CcToolchainProvider toolchain,
List<String> expectedInputs)
throws Exception {
SpawnAction dwpAction = (SpawnAction) getGeneratingAction(dwpFile);
String dwpToolPath = toolchain.getToolPathFragment(Tool.DWP, ruleContext).getPathString();
assertThat(dwpAction.getMnemonic()).isEqualTo("CcGenerateDwp");
assertThat(dwpToolPath).isEqualTo(dwpAction.getCommandFilename());
List<String> commandArgs = dwpAction.getArguments();
// The first argument should be the command being executed.
assertThat(dwpToolPath).isEqualTo(commandArgs.get(0));
// The final two arguments should be "-o dwpOutputFile".
assertThat(commandArgs.subList(commandArgs.size() - 2, commandArgs.size()))
.containsExactly("-o", dwpFile.getExecPathString())
.inOrder();
// The remaining arguments should be the set of .dwo inputs (in any order).
assertThat(commandArgs.subList(1, commandArgs.size() - 2))
.containsExactlyElementsIn(expectedInputs);
}
@Test
public void testFission() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_PIC,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.PER_OBJECT_DEBUG_INFO));
useConfiguration("--fission=yes", "--copt=-g0");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(artifactsToStrings(backendAction.getOutputs()))
.containsExactly(
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.o",
"bin pkg/bin.lto/pkg/_objs/bin/binfile.pic.dwo");
assertThat(backendAction.getArguments()).containsAtLeast("-g0", "per_object_debug_info_option");
backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(artifactsToStrings(backendAction.getOutputs()))
.containsExactly(
"bin pkg/bin.lto/pkg/_objs/lib/libfile.pic.o",
"bin pkg/bin.lto/pkg/_objs/lib/libfile.pic.dwo");
assertThat(backendAction.getArguments()).contains("per_object_debug_info_option");
// Now check the dwp action.
Artifact dwpFile = getFileConfiguredTarget(pkg.getLabel() + ".dwp").getArtifact();
PathFragment rootPrefix = dwpRootPrefix(dwpFile);
RuleContext ruleContext = getRuleContext(pkg);
CcToolchainProvider toolchain =
CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
validateDwp(
ruleContext,
dwpFile,
toolchain,
ImmutableList.of(
rootPrefix + "/pkg/bin.lto/pkg/_objs/lib/libfile.pic.dwo",
rootPrefix + "/pkg/bin.lto/pkg/_objs/bin/binfile.pic.dwo"));
}
@Test
public void testNoLinkstaticFission() throws Exception {
createBuildFiles("bin", "linkstatic = 0,");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES,
CppRuleClasses.SUPPORTS_DYNAMIC_LINKER,
CppRuleClasses.PER_OBJECT_DEBUG_INFO));
useConfiguration("--fission=yes");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
SolibSymlinkAction solibSymlinkAction =
(SolibSymlinkAction) getPredecessorByInputName(linkAction, "_solib_k8/libpkg_Sliblib.ifso");
assertThat(solibSymlinkAction.getMnemonic()).isEqualTo("SolibSymlink");
CppLinkAction libLinkAction =
(CppLinkAction) getPredecessorByInputName(solibSymlinkAction, "bin/pkg/liblib.ifso");
assertThat(libLinkAction.getMnemonic()).isEqualTo("CppLink");
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(
libLinkAction, "pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(artifactsToStrings(backendAction.getOutputs()))
.containsExactly(
"bin pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.o",
"bin pkg/liblib.so.lto/pkg/_objs/lib/libfile.pic.dwo");
assertThat(backendAction.getArguments()).contains("per_object_debug_info_option");
// Check the dwp action.
Artifact dwpFile = getFileConfiguredTarget(pkg.getLabel() + ".dwp").getArtifact();
PathFragment rootPrefix = dwpRootPrefix(dwpFile);
RuleContext ruleContext = getRuleContext(pkg);
CcToolchainProvider toolchain =
CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
validateDwp(
ruleContext,
dwpFile,
toolchain,
ImmutableList.of(rootPrefix + "/pkg/bin.lto/pkg/_objs/bin/binfile.pic.dwo"));
}
@Test
public void testLinkstaticCcTestFission() throws Exception {
createTestFiles("linkstatic = 1,", "");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.THIN_LTO_LINKSTATIC_TESTS_USE_SHARED_NONLTO_BACKENDS,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.PER_OBJECT_DEBUG_INFO));
useConfiguration(
"--fission=yes", "--features=thin_lto_linkstatic_tests_use_shared_nonlto_backends");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin_test");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
// All backends should be shared non-LTO in this case
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(
linkAction, "shared.nonlto/pkg/_objs/bin_test/bin_test.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(artifactsToStrings(backendAction.getOutputs()))
.containsExactly(
"bin shared.nonlto/pkg/_objs/bin_test/bin_test.pic.o",
"bin shared.nonlto/pkg/_objs/bin_test/bin_test.pic.dwo");
assertThat(backendAction.getArguments()).contains("per_object_debug_info_option");
backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "shared.nonlto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(backendAction.getArguments()).contains("-fPIC");
assertThat(artifactsToStrings(backendAction.getOutputs()))
.containsExactly(
"bin shared.nonlto/pkg/_objs/lib/libfile.pic.o",
"bin shared.nonlto/pkg/_objs/lib/libfile.pic.dwo");
assertThat(backendAction.getArguments()).contains("per_object_debug_info_option");
// Now check the dwp action.
Artifact dwpFile = getFileConfiguredTarget(pkg.getLabel() + ".dwp").getArtifact();
PathFragment rootPrefix = dwpRootPrefix(dwpFile);
RuleContext ruleContext = getRuleContext(pkg);
CcToolchainProvider toolchain =
CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
validateDwp(
ruleContext,
dwpFile,
toolchain,
ImmutableList.of(
rootPrefix + "/shared.nonlto/pkg/_objs/lib/libfile.pic.dwo",
rootPrefix + "/shared.nonlto/pkg/_objs/bin_test/bin_test.pic.dwo"));
}
@Test
public void testLinkstaticCcTest() throws Exception {
createTestFiles("linkstatic = 1,", "");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.THIN_LTO_LINKSTATIC_TESTS_USE_SHARED_NONLTO_BACKENDS,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.PER_OBJECT_DEBUG_INFO));
useConfiguration("--features=thin_lto_linkstatic_tests_use_shared_nonlto_backends");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin_test");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
ConfiguredTarget pkg2 = getConfiguredTarget("//pkg:bin_test2");
Artifact pkgArtifact2 = getFilesToBuild(pkg2).getSingleton();
CppLinkAction linkAction2 = (CppLinkAction) getGeneratingAction(pkgArtifact2);
// All backends should be shared non-LTO in this case
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(
linkAction, "shared.nonlto/pkg/_objs/bin_test/bin_test.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "shared.nonlto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(backendAction.getArguments()).contains("-fPIC");
LtoBackendAction backendAction2 =
(LtoBackendAction)
getPredecessorByInputName(linkAction2, "shared.nonlto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction2.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(backendAction).isEqualTo(backendAction2);
}
@Test
public void testTestOnlyTarget() throws Exception {
createBuildFiles("bin", "testonly = 1,");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.THIN_LTO_LINKSTATIC_TESTS_USE_SHARED_NONLTO_BACKENDS,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES));
useConfiguration("--features=thin_lto_linkstatic_tests_use_shared_nonlto_backends");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "shared.nonlto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
}
@Test
public void testUseSharedAllLinkstatic() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.THIN_LTO_ALL_LINKSTATIC_USE_SHARED_NONLTO_BACKENDS,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.SUPPORTS_PIC,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES));
useConfiguration("--features=thin_lto_all_linkstatic_use_shared_nonlto_backends");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "shared.nonlto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
}
private Action getPredecessorByInputName(Action action, String str) {
for (Artifact a : action.getInputs().toList()) {
if (a.getExecPathString().contains(str)) {
return getGeneratingAction(a);
}
}
return null;
}
@Test
public void testAssemblerSource() throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" deps = [ ':lib' ], ",
" malloc = '//base:system_malloc')",
"cc_library(name = 'lib',",
" srcs = ['tracing.cc', 'tracing_x86-64.S'],",
" )");
scratch.file("pkg/binfile.cc", "int main() { return pkg(); }");
scratch.file("pkg/tracing.cc", "// hello");
scratch.file("pkg/tracing_x86-64.S", "NOP");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration();
ConfiguredTarget bin = getConfiguredTarget("//pkg:bin");
Artifact binArtifact = getFilesToBuild(bin).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
Action dataGen = getPredecessorByInputName(linkAction, "tracing_x86-64");
assertWithMessage(linkAction.getInputs().toString()).that(dataGen).isNotNull();
assertThat(dataGen.getMnemonic()).isEqualTo("CppCompile");
}
// Make sure we don't choke on a cc_library without sources and therefore, without bitcode files.
@Test
public void testNoSourceFiles() throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" deps = [ ':lib' ], ",
" malloc = '//base:system_malloc')",
"cc_library(name = 'lib',",
" srcs = ['static.a'],",
" )");
scratch.file("pkg/binfile.cc", "int main() { return 1; }");
scratch.file("pkg/static.a", "xyz");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration();
getConfiguredTarget("//pkg:bin");
}
@Test
public void testFdoInstrument() throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.FDO_INSTRUMENT));
useConfiguration("--fdo_instrument=profiles");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
// If the LtoBackendAction incorrectly tries to add the fdo_instrument
// feature, we will fail with an "unknown variable 'fdo_instrument_path'"
// error. But let's also explicitly confirm that the fdo_instrument
// option didn't end up here.
assertThat(backendAction.getArguments()).doesNotContain("fdo_instrument_option");
}
@Test
public void testLtoIndexOpt() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration(
"--ltoindexopt=anltoindexopt", "--noincompatible_make_thinlto_command_lines_standalone");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
{.o.thinlto.bc,.o.imports} <=[LTOIndexing]=
.o <= [CppCompile] .cc
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
CppLinkAction indexAction =
(CppLinkAction)
getPredecessorByInputName(
backendAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.thinlto.bc");
assertThat(indexAction.getArguments()).contains("anltoindexopt");
}
@Test
public void testLtoStandaloneCommandLines() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration(
"--ltoindexopt=anltoindexopt",
"--incompatible_make_thinlto_command_lines_standalone",
"--features=thin_lto");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
{.o.thinlto.bc,.o.imports} <=[LTOIndexing]=
.o <= [CppCompile] .cc
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
CppLinkAction indexAction =
(CppLinkAction)
getPredecessorByInputName(
backendAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.thinlto.bc");
assertThat(indexAction.getArguments())
.contains("--i_come_from_standalone_lto_index=anltoindexopt");
}
@Test
public void testCopt() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.SUPPORTS_PIC));
useConfiguration("--copt=acopt");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(backendAction.getArguments()).contains("acopt");
}
@Test
public void testPerFileCopt() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration(
"--per_file_copt=binfile\\.cc@copt1",
"--per_file_copt=libfile\\.cc@copt2",
"--per_file_copt=.*\\.cc,-binfile\\.cc@copt2");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getArguments()).contains("copt1");
assertThat(backendAction.getArguments()).doesNotContain("copt2");
backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction.getArguments()).doesNotContain("copt1");
assertThat(backendAction.getArguments()).contains("copt2");
}
@Test
public void testCoptNoCoptAttributes() throws Exception {
createBuildFiles("bin", "copts = ['acopt', 'nocopt1'], nocopts = 'nocopt1|nocopt2',");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration("--copt=nocopt2", "--noincompatible_disable_nocopts");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(backendAction.getArguments()).contains("acopt");
// TODO(b/122303926): Remove when nocopts are removed, or uncomment and fix if not removing.
// assertThat(backendAction.getArguments()).doesNotContain("nocopt1");
// assertThat(backendAction.getArguments()).doesNotContain("nocopt2");
}
@Test
public void testLtoBackendOpt() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_PIC,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_START_END_LIB,
MockCcSupport.USER_COMPILE_FLAGS));
useConfiguration("--ltobackendopt=anltobackendopt");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(backendAction.getArguments())
.containsAtLeast("--default-compile-flag", "anltobackendopt");
}
@Test
public void testPerFileLtoBackendOpt() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration(
"--per_file_ltobackendopt=binfile\\.pic\\.o@ltobackendopt1",
"--per_file_ltobackendopt=.*\\.o,-binfile\\.pic\\.o@ltobackendopt2");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
assertThat(linkAction.getOutputs()).containsExactly(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
assertThat(backendAction.getArguments()).contains("ltobackendopt1");
assertThat(backendAction.getArguments()).doesNotContain("ltobackendopt2");
backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/lib/libfile.pic.o");
assertThat(backendAction.getArguments()).doesNotContain("ltobackendopt1");
assertThat(backendAction.getArguments()).contains("ltobackendopt2");
}
@Test
public void testNoUseLtoIndexingBitcodeFile() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.NO_USE_LTO_INDEXING_BITCODE_FILE,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration("--features=no_use_lto_indexing_bitcode_file");
/*
We follow the chain from the final product backwards.
binary <=[Link]=
.lto/...o <=[LTOBackend]=
{.o.thinlto.bc,.o.imports} <=[LTOIndexing]=
.o <= [CppCompile] .cc
*/
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
Artifact pkgArtifact = getFilesToBuild(pkg).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(pkgArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o");
CppLinkAction indexAction =
(CppLinkAction)
getPredecessorByInputName(
backendAction, "pkg/bin.lto/pkg/_objs/bin/binfile.pic.o.thinlto.bc");
assertThat(indexAction.getArguments()).doesNotContain("object_suffix_replace");
assertThat(artifactsToStrings(indexAction.getInputs()))
.containsAtLeast("bin pkg/_objs/bin/binfile.pic.o", "bin pkg/_objs/lib/libfile.pic.o");
CppCompileAction bitcodeAction =
(CppCompileAction) getPredecessorByInputName(indexAction, "pkg/_objs/bin/binfile.pic.o");
assertThat(bitcodeAction.getArguments()).doesNotContain("lto_indexing_bitcode=");
}
@Test
public void testAutoFdo() throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.afdo", "");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.AUTOFDO));
useConfiguration("--fdo_optimize=pkg/profile.afdo", "--compilation_mode=opt");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// Checks that -fauto-profile is added to the LtoBackendAction.
assertThat(Joiner.on(" ").join(backendAction.getArguments())).containsMatch(
"-fauto-profile=[^ ]*/profile.afdo");
assertThat(ActionsTestUtil.baseArtifactNames(backendAction.getInputs())).contains(
"profile.afdo");
}
private void setupAutoFdoThinLtoCrosstool() throws Exception {
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.AUTOFDO,
CppRuleClasses.ENABLE_AFDO_THINLTO,
CppRuleClasses.AUTOFDO_IMPLICIT_THINLTO));
}
/**
* Tests that ThinLTO is not enabled for AFDO with LLVM without
* --features=autofdo_implicit_thinlto.
*/
@Test
public void testAutoFdoNoImplicitThinLto() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.afdo", "");
setupAutoFdoThinLtoCrosstool();
useConfiguration("--fdo_optimize=pkg/profile.afdo", "--compilation_mode=opt");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/** Tests that --features=autofdo_implicit_thinlto enables ThinLTO for AFDO with LLVM. */
@Test
public void testAutoFdoImplicitThinLto() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.afdo", "");
setupAutoFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.afdo",
"--compilation_mode=opt",
"--features=autofdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// For ThinLTO compilation we should have a non-null backend action
assertThat(backendAction).isNotNull();
}
/**
* Tests that --features=-thin_lto overrides --features=autofdo_implicit_thinlto and prevents
* enabling ThinLTO for AFDO with LLVM.
*/
@Test
public void testAutoFdoImplicitThinLtoDisabledOption() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.afdo", "");
setupAutoFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.afdo",
"--compilation_mode=opt",
"--features=autofdo_implicit_thinlto",
"--features=-thin_lto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/**
* Tests that features=[-thin_lto] in the build rule overrides --features=autofdo_implicit_thinlto
* and prevents enabling ThinLTO for AFDO with LLVM.
*/
@Test
public void testAutoFdoImplicitThinLtoDisabledRule() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" features = ['-thin_lto'],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.afdo", "");
setupAutoFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.afdo",
"--compilation_mode=opt",
"--features=autofdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/**
* Tests that features=[-thin_lto] in the package overrides --features=autofdo_implicit_thinlto
* and prevents enabling ThinLTO for AFDO with LLVM.
*/
@Test
public void testAutoFdoImplicitThinLtoDisabledPackage() throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['-thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.afdo", "");
setupAutoFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.afdo",
"--compilation_mode=opt",
"--features=autofdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
private void setupFdoThinLtoCrosstool() throws Exception {
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.FDO_OPTIMIZE,
CppRuleClasses.ENABLE_FDO_THINLTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
MockCcSupport.FDO_IMPLICIT_THINLTO));
}
/**
* Tests that ThinLTO is not enabled for FDO with LLVM without --features=fdo_implicit_thinlto.
*/
@Test
public void testFdoNoImplicitThinLto() throws Exception {
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(CppRuleClasses.THIN_LTO, CppRuleClasses.SUPPORTS_START_END_LIB));
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.zip", "");
setupFdoThinLtoCrosstool();
useConfiguration("--fdo_optimize=pkg/profile.zip", "--compilation_mode=opt");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/** Tests that --features=fdo_implicit_thinlto enables ThinLTO for FDO with LLVM. */
@Test
public void testFdoImplicitThinLto() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.zip", "");
setupFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.zip",
"--compilation_mode=opt",
"--features=fdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// For ThinLTO compilation we should have a non-null backend action
assertThat(backendAction).isNotNull();
}
/**
* Tests that --features=-thin_lto overrides --features=fdo_implicit_thinlto and prevents enabling
* ThinLTO for FDO with LLVM.
*/
@Test
public void testFdoImplicitThinLtoDisabledOption() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.zip", "");
setupFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.zip",
"--compilation_mode=opt",
"--features=fdo_implicit_thinlto",
"--features=-thin_lto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/**
* Tests that features=[-thin_lto] in the build rule overrides --features=fdo_implicit_thinlto and
* prevents enabling ThinLTO for FDO with LLVM.
*/
@Test
public void testFdoImplicitThinLtoDisabledRule() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" features = ['-thin_lto'],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.zip", "");
setupFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.zip",
"--compilation_mode=opt",
"--features=fdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/**
* Tests that features=[-thin_lto] in the package overrides --features=fdo_implicit_thinlto and
* prevents enabling ThinLTO for FDO with LLVM.
*/
@Test
public void testFdoImplicitThinLtoDisabledPackage() throws Exception {
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(CppRuleClasses.THIN_LTO, CppRuleClasses.SUPPORTS_START_END_LIB));
scratch.file(
"pkg/BUILD",
"package(features = ['-thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')");
scratch.file("pkg/binfile.cc", "int main() {}");
scratch.file("pkg/profile.zip", "");
setupFdoThinLtoCrosstool();
useConfiguration(
"--fdo_optimize=pkg/profile.zip",
"--compilation_mode=opt",
"--features=fdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
private void setupXBinaryFdoThinLtoCrosstool() throws Exception {
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.XBINARYFDO,
CppRuleClasses.ENABLE_XFDO_THINLTO,
MockCcSupport.XFDO_IMPLICIT_THINLTO));
}
/**
* Tests that ThinLTO is not enabled for XFDO with LLVM without
* --features=xbinaryfdo_implicit_thinlto.
*/
@Test
public void testXBinaryFdoNoImplicitThinLto() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ])",
"fdo_profile(name='out.xfdo', profile='profiles.xfdo')");
scratch.file("pkg/binfile.cc", "int main() {}");
setupXBinaryFdoThinLtoCrosstool();
useConfiguration("--xbinary_fdo=//pkg:out.xfdo", "--compilation_mode=opt");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/** Tests that --features=xbinaryfdo_implicit_thinlto enables ThinLTO for XFDO with LLVM. */
@Test
public void testXBinaryFdoImplicitThinLto() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ])",
"fdo_profile(name='out.xfdo', profile='profiles.xfdo')");
scratch.file("pkg/binfile.cc", "int main() {}");
setupXBinaryFdoThinLtoCrosstool();
useConfiguration(
"--xbinary_fdo=//pkg:out.xfdo",
"--compilation_mode=opt",
"--features=xbinaryfdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// For ThinLTO compilation we should have a non-null backend action
assertThat(backendAction).isNotNull();
}
/**
* Tests that --features=-thin_lto overrides --features=xbinaryfdo_implicit_thinlto and prevents
* enabling ThinLTO for XFDO with LLVM.
*/
@Test
public void testXBinaryFdoImplicitThinLtoDisabledOption() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ])",
"fdo_profile(name='out.xfdo', profile='profiles.xfdo')");
scratch.file("pkg/binfile.cc", "int main() {}");
setupXBinaryFdoThinLtoCrosstool();
useConfiguration(
"--xbinary_fdo=//pkg:out.xfdo",
"--compilation_mode=opt",
"--features=xbinaryfdo_implicit_thinlto",
"--features=-thin_lto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/**
* Tests that features=[-thin_lto] in the build rule overrides
* --features=xbinaryfdo_implicit_thinlto and prevents enabling ThinLTO for XFDO with LLVM.
*/
@Test
public void testXBinaryFdoImplicitThinLtoDisabledRule() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" features = ['-thin_lto'])",
"fdo_profile(name='out.xfdo', profile='profiles.xfdo')");
scratch.file("pkg/binfile.cc", "int main() {}");
setupXBinaryFdoThinLtoCrosstool();
useConfiguration(
"--xbinary_fdo=//pkg:out.xfdo",
"--compilation_mode=opt",
"--features=xbinaryfdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
/**
* Tests that features=[-thin_lto] in the package overrides --features=fdo_implicit_thinlto and
* prevents enabling ThinLTO for XFDO with LLVM.
*/
@Test
public void testXBinaryFdoImplicitThinLtoDisabledPackage() throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['-thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ])",
"fdo_profile(name='out.xfdo', profile='profiles.xfdo')");
scratch.file("pkg/binfile.cc", "int main() {}");
setupXBinaryFdoThinLtoCrosstool();
useConfiguration(
"--xbinary_fdo=//pkg:out.xfdo",
"--compilation_mode=opt",
"--features=xbinaryfdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
@Test
public void testXBinaryFdo() throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')",
"fdo_profile(name='out.xfdo', profile='profiles.xfdo')");
scratch.file("pkg/binfile.cc", "int main() {}");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.XBINARYFDO));
useConfiguration("--xbinary_fdo=//pkg:out.xfdo", "--compilation_mode=opt");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
// Checks that -fauto-profile is added to the LtoBackendAction.
assertThat(Joiner.on(" ").join(backendAction.getArguments()))
.containsMatch("-fauto-profile=[^ ]*/profiles.xfdo");
assertThat(ActionsTestUtil.baseArtifactNames(backendAction.getInputs()))
.contains("profiles.xfdo");
}
/**
* Tests that ThinLTO is not enabled for XBINARYFDO with --features=autofdo_implicit_thinlto and
* --features=fdo_implicit_thinlto.
*/
@Test
public void testXBinaryFdoNoAutoFdoOrFdoImplicitThinLto() throws Exception {
scratch.file(
"pkg/BUILD",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ],",
" malloc = '//base:system_malloc')",
"fdo_profile(name='out.xfdo', profile='profiles.xfdo')");
scratch.file("pkg/binfile.cc", "int main() {}");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.ENABLE_FDO_THINLTO,
MockCcSupport.FDO_IMPLICIT_THINLTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.ENABLE_AFDO_THINLTO,
MockCcSupport.AUTOFDO_IMPLICIT_THINLTO,
CppRuleClasses.XBINARYFDO));
useConfiguration(
"--xbinary_fdo=//pkg:out.xfdo",
"--compilation_mode=opt",
"--features=autofdo_implicit_thinlto",
"--features=fdo_implicit_thinlto");
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/pkg/binfile.o");
// We should not have a ThinLTO backend action
assertThat(backendAction).isNull();
}
@Test
public void testPICBackendOrder() throws Exception {
createBuildFiles("bin");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.SUPPORTS_PIC,
CppRuleClasses.SUPPORTS_START_END_LIB));
useConfiguration("--copt=-fno-PIE");
ConfiguredTarget pkg = getConfiguredTarget("//pkg:bin");
LtoBackendAction backendAction =
(LtoBackendAction)
getGeneratingAction(artifactByPath(getFilesToBuild(pkg), "bin", "binfile.pic.o"));
assertThat(backendAction.getMnemonic()).isEqualTo("CcLtoBackendCompile");
assertThat(backendAction.getArguments()).containsAtLeast("-fno-PIE", "-fPIC").inOrder();
}
private void testLLVMCachePrefetchBackendOption(String extraOption, boolean asLabel)
throws Exception {
scratch.file(
"pkg/BUILD",
"package(features = ['thin_lto'])",
"",
"cc_binary(name = 'bin',",
" srcs = ['binfile.cc', ])");
if (asLabel) {
scratch.file(
"fdo/BUILD",
"fdo_prefetch_hints(name='test_profile', profile=':prefetch.afdo')");
} else {
scratch.file(
"fdo/BUILD",
"fdo_prefetch_hints(name='test_profile', absolute_path_profile='/tmp/prefetch.afdo')");
}
scratch.file("pkg/binfile.cc", "int main() {}");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(
CppRuleClasses.THIN_LTO,
CppRuleClasses.SUPPORTS_START_END_LIB,
CppRuleClasses.SUPPORTS_PIC,
MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
CppRuleClasses.AUTOFDO));
useConfiguration(
"--fdo_prefetch_hints=//fdo:test_profile",
"--compilation_mode=opt",
extraOption);
Artifact binArtifact = getFilesToBuild(getConfiguredTarget("//pkg:bin")).getSingleton();
CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(binArtifact);
assertThat(linkAction.getOutputs()).containsExactly(binArtifact);
LtoBackendAction backendAction =
(LtoBackendAction)
getPredecessorByInputName(linkAction, "pkg/bin.lto/pkg/_objs/bin/binfile.o");
String expectedCompilerFlag =
"-Xclang-only=-prefetch-hints-file="
+ (asLabel ? ".*/prefetch.afdo" : "(blaze|bazel)-out/.*/fdo/.*/prefetch.afdo");
assertThat(Joiner.on(" ").join(backendAction.getArguments()))
.containsMatch(
"-Xclang-only=-mllvm " + expectedCompilerFlag);
assertThat(ActionsTestUtil.baseArtifactNames(backendAction.getInputs()))
.contains("prefetch.afdo");
}
@Test
public void testFdoCachePrefetchLLVMOptionsToBackendFromPath() throws Exception {
testLLVMCachePrefetchBackendOption("", false);
}
@Test
public void testFdoCachePrefetchAndFdoLLVMOptionsToBackendFromPath() throws Exception {
testLLVMCachePrefetchBackendOption("--fdo_optimize=./profile.zip", false);
}
@Test
public void testFdoCachePrefetchLLVMOptionsToBackendFromLabel() throws Exception {
testLLVMCachePrefetchBackendOption("", true);
}
@Test
public void testFdoCachePrefetchAndFdoLLVMOptionsToBackendFromLabel() throws Exception {
testLLVMCachePrefetchBackendOption("--fdo_optimize=./profile.zip", true);
}
}