From cc0180041dd1ef801b35ba28c1d34f19ffe22c95 Mon Sep 17 00:00:00 2001 From: Cal Peyser Date: Fri, 1 Jul 2016 13:48:05 +0000 Subject: Implicit outputs to cc_library are also exported in unique output groups. -- MOS_MIGRATED_REVID=126405595 --- .../build/lib/rules/cpp/CcLibraryHelper.java | 42 +++++++++ .../build/lib/rules/cpp/CppRuleClasses.java | 6 ++ .../build/lib/rules/cpp/CppOutputGroupsTest.java | 100 +++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 src/test/java/com/google/devtools/build/lib/rules/cpp/CppOutputGroupsTest.java (limited to 'src') diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java index 206eeb17e0..d6b6a2b2f1 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcLibraryHelper.java @@ -41,6 +41,7 @@ import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.Var import com.google.devtools.build.lib.rules.cpp.CppConfiguration.HeadersCheckingMode; import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType; import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink; +import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileTypeSet; import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; @@ -938,6 +939,11 @@ public final class CcLibraryHelper { dwoArtifacts.getDwoArtifacts(), dwoArtifacts.getPicDwoArtifacts())); providers.put(TransitiveLipoInfoProvider.class, collectTransitiveLipoInfo(ccOutputs)); Map> outputGroups = new TreeMap<>(); + + if (shouldAddLinkerOutputArtifacts(ruleContext, ccOutputs)) { + addLinkerOutputArtifacts(outputGroups); + } + outputGroups.put(OutputGroupProvider.TEMP_FILES, getTemps(ccOutputs)); if (emitCompileProviders) { boolean isLipoCollector = @@ -973,6 +979,42 @@ public final class CcLibraryHelper { cppCompilationContext); } + /** + * Returns true if the appropriate attributes for linker output artifacts are defined, and either + * the compile action produces object files or the build is configured to produce an archive or + * dynamic library even in the absense of object files. + */ + private boolean shouldAddLinkerOutputArtifacts( + RuleContext ruleContext, CcCompilationOutputs ccOutputs) { + return (ruleContext.attributes().has("alwayslink", Type.BOOLEAN) + && ruleContext.attributes().has("linkstatic", Type.BOOLEAN) + && (emitLinkActionsIfEmpty || !ccOutputs.isEmpty())); + } + + /** + * Adds linker output artifacts to the given map, to be registered on the configured target as + * output groups. + */ + private void addLinkerOutputArtifacts(Map> outputGroups) { + NestedSetBuilder archiveFile = new NestedSetBuilder<>(Order.STABLE_ORDER); + NestedSetBuilder dynamicLibrary = new NestedSetBuilder<>(Order.STABLE_ORDER); + + if (ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) { + archiveFile.add( + CppHelper.getLinkedArtifact(ruleContext, Link.LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY)); + } else { + archiveFile.add(CppHelper.getLinkedArtifact(ruleContext, Link.LinkTargetType.STATIC_LIBRARY)); + } + + if (CppRuleClasses.shouldCreateDynamicLibrary(ruleContext.attributes())) { + dynamicLibrary.add( + CppHelper.getLinkedArtifact(ruleContext, Link.LinkTargetType.DYNAMIC_LIBRARY)); + } + + outputGroups.put("archive", archiveFile.build()); + outputGroups.put("dynamic_library", dynamicLibrary.build()); + } + /** * Creates the C/C++ compilation action creator. */ diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java index 7c9aa05675..0736c0b9b9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java @@ -38,6 +38,7 @@ import com.google.devtools.build.lib.packages.AttributeMap; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; import com.google.devtools.build.lib.packages.Rule; import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.InstrumentationSpec; +import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileTypeSet; import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.LipoMode; @@ -46,6 +47,11 @@ import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.LipoM */ public class CppRuleClasses { + /** Returns true if this rule should create a dynamic library. */ + public static boolean shouldCreateDynamicLibrary(AttributeMap rule) { + return !rule.get("linkstatic", Type.BOOLEAN) && CcLibrary.appearsToHaveObjectFiles(rule); + } + /** * Implementation for the :lipo_context_collector attribute. */ diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppOutputGroupsTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppOutputGroupsTest.java new file mode 100644 index 0000000000..5110bddd36 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppOutputGroupsTest.java @@ -0,0 +1,100 @@ +// 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.devtools.build.lib.actions.util.ActionsTestUtil; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests the output groups of cc_library. */ +@RunWith(JUnit4.class) +public class CppOutputGroupsTest extends BuildViewTestCase { + + @Test + public void testStaticLibraryOnlyOutputGroups() throws Exception { + scratch.file("src.cc"); + scratch.file( + "a/BUILD", + "cc_library(name='lib', srcs=['src.cc'], linkstatic=1, alwayslink=0)", + "filegroup(name='group_archive', srcs=[':lib'], output_group = 'archive')", + "filegroup(name='group_dynamic', srcs=[':lib'], output_group = 'dynamic_library')"); + + ConfiguredTarget groupArchive = getConfiguredTarget("//a:group_archive"); + ConfiguredTarget groupDynamic = getConfiguredTarget("//a:group_dynamic"); + + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupArchive))) + .containsExactly("a/liblib.a"); + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupDynamic))).isEmpty(); + } + + @Test + public void testSharedLibraryOnlyOutputGroups() throws Exception { + scratch.file("src.cc"); + scratch.file( + "a/BUILD", + "cc_library(name='lib', srcs=['src.cc'], linkstatic=1, alwayslink=1)", + "filegroup(name='group_archive', srcs=[':lib'], output_group = 'archive')", + "filegroup(name='group_dynamic', srcs=[':lib'], output_group = 'dynamic_library')"); + + ConfiguredTarget groupArchive = getConfiguredTarget("//a:group_archive"); + ConfiguredTarget groupDynamic = getConfiguredTarget("//a:group_dynamic"); + + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupArchive))) + .containsExactly("a/liblib.lo"); + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupDynamic))).isEmpty(); + } + + @Test + public void testStaticAndDynamicLibraryOutputGroups() throws Exception { + scratch.file("src.cc"); + scratch.file( + "a/BUILD", + "cc_library(name='lib', srcs=['src.cc'], linkstatic=0, alwayslink=0)", + "filegroup(name='group_archive', srcs=[':lib'], output_group = 'archive')", + "filegroup(name='group_dynamic', srcs=[':lib'], output_group = 'dynamic_library')"); + + ConfiguredTarget groupArchive = getConfiguredTarget("//a:group_archive"); + ConfiguredTarget groupDynamic = getConfiguredTarget("//a:group_dynamic"); + + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupArchive))) + .containsExactly("a/liblib.a"); + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupDynamic))) + .containsExactly("a/liblib.so"); + } + + @Test + public void testSharedAndDynamicLibraryOutputGroups() throws Exception { + scratch.file("src.cc"); + scratch.file( + "a/BUILD", + "cc_library(name='lib', srcs=['src.cc'], linkstatic=0, alwayslink=1)", + "filegroup(name='group_archive', srcs=[':lib'], output_group = 'archive')", + "filegroup(name='group_dynamic', srcs=[':lib'], output_group = 'dynamic_library')"); + + ConfiguredTarget groupArchive = getConfiguredTarget("//a:group_archive"); + ConfiguredTarget groupDynamic = getConfiguredTarget("//a:group_dynamic"); + + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupArchive))) + .containsExactly("a/liblib.lo"); + assertThat(ActionsTestUtil.prettyArtifactNames(getFilesToBuild(groupDynamic))) + .containsExactly("a/liblib.so"); + } +} -- cgit v1.2.3