Skip to content

Commit

Permalink
Expose object files in the C++ Sandwich API
Browse files Browse the repository at this point in the history
With these it is now possible to:

1) implement --start-lib/--end-lib behavior in Starlark rules
2) do the right thing when ThinLTO is enabled and objects actually contain bitcode files

RELNOTES: None.
PiperOrigin-RevId: 274176867
  • Loading branch information
hlopko authored and copybara-github committed Oct 11, 2019
1 parent 836a353 commit 9ce04ba
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.LibraryToLinkApi;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import java.util.List;
import javax.annotation.Nullable;

Expand Down Expand Up @@ -58,6 +60,15 @@ public Artifact getDynamicLibraryForRuntimeOrNull(boolean linkingStatically) {
@Nullable
public abstract ImmutableList<Artifact> getObjectFiles();

@Nullable
@Override
public SkylarkList<Artifact> getObjectFilesForStarlark() {
if (getObjectFiles() == null) {
return MutableList.empty();
}
return SkylarkList.createImmutable(getObjectFiles());
}

@Nullable
public abstract ImmutableMap<Artifact, LtoBackendArtifacts> getSharedNonLtoBackends();

Expand All @@ -71,6 +82,15 @@ public Artifact getDynamicLibraryForRuntimeOrNull(boolean linkingStatically) {
@Nullable
public abstract ImmutableList<Artifact> getPicObjectFiles();

@Nullable
@Override
public SkylarkList<Artifact> getPicObjectFilesForStarlark() {
if (getPicObjectFiles() == null) {
return MutableList.empty();
}
return SkylarkList.createImmutable(getPicObjectFiles());
}

@Nullable
public abstract ImmutableMap<Artifact, LtoBackendArtifacts> getPicSharedNonLtoBackends();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.syntax.SkylarkList;

/**
* A library the user can link to. This is different from a simple linker input in that it also has
Expand All @@ -28,6 +29,20 @@
category = SkylarkModuleCategory.BUILTIN,
doc = "A library the user can link against.")
public interface LibraryToLinkApi<FileT extends FileApi> {
@SkylarkCallable(
name = "objects",
allowReturnNones = true,
doc = "<code>List</code> of object files in the library.",
structField = true)
SkylarkList<FileT> getObjectFilesForStarlark();

@SkylarkCallable(
name = "pic_objects",
allowReturnNones = true,
doc = "<code>List</code> of pic object files in the library.",
structField = true)
SkylarkList<FileT> getPicObjectFilesForStarlark();

@SkylarkCallable(
name = "static_library",
allowReturnNones = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.packages.SkylarkInfo;
import com.google.devtools.build.lib.packages.SkylarkProvider;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.packages.util.Crosstool.CcToolchainConfig;
import com.google.devtools.build.lib.packages.util.MockCcSupport;
Expand All @@ -51,8 +52,10 @@
import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.StringValueParser;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.testutil.TestConstants;
Expand Down Expand Up @@ -5504,6 +5507,96 @@ public void testApiWithAspectsOnTargetsInExternalRepos() throws Exception {
assertThat(getConfiguredTarget("//b:b")).isNotNull();
}

@Test
public void testObjectsApi() throws Exception {
useConfiguration("--compilation_mode=opt");
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(CppRuleClasses.SUPPORTS_PIC, CppRuleClasses.PIC));

scratchObjectsProvidingRule();

Provider.Key key =
new SkylarkProvider.SkylarkKey(
Label.parseAbsolute("//foo:foo.bzl", ImmutableMap.of()), "FooInfo");
LibraryToLink fooLibrary =
Iterables.getOnlyElement(
getConfiguredTarget("//foo:dep")
.get(CcInfo.PROVIDER)
.getCcLinkingContext()
.getLibraries()
.toList());
SkylarkInfo fooInfo =
(SkylarkInfo) getConfiguredTarget("//foo:foo").get(SkylarkProviderIdentifier.forKey(key));

assertThat(fooLibrary.getObjectFiles()).isEqualTo(fooInfo.getValue("objects"));
assertThat(fooLibrary.getPicObjectFiles()).isEqualTo(fooInfo.getValue("pic_objects"));
}

@Test
public void testObjectsApiNeverReturningNones() throws Exception {
scratchObjectsProvidingRule();

Provider.Key key =
new SkylarkProvider.SkylarkKey(
Label.parseAbsolute("//foo:foo.bzl", ImmutableMap.of()), "FooInfo");

// Default toolchain is without PIC support, so pic_objects should be None
SkylarkInfo fooInfoForPic =
(SkylarkInfo) getConfiguredTarget("//foo:foo").get(SkylarkProviderIdentifier.forKey(key));

Object picObjects = fooInfoForPic.getValue("pic_objects");
assertThat(picObjects).isNotEqualTo(Runtime.NONE);
assertThat((MutableList) picObjects).isEmpty();

// With PIC and the default compilation_mode which is fastbuild C++ rules only produce PIC
// objects.
AnalysisMock.get()
.ccSupport()
.setupCcToolchainConfig(
mockToolsConfig,
CcToolchainConfig.builder()
.withFeatures(CppRuleClasses.SUPPORTS_PIC, CppRuleClasses.PIC));
invalidatePackages();
SkylarkInfo fooInfoForNoPic =
(SkylarkInfo) getConfiguredTarget("//foo:foo").get(SkylarkProviderIdentifier.forKey(key));

Object objects = fooInfoForNoPic.getValue("objects");
assertThat(objects).isNotEqualTo(Runtime.NONE);
assertThat((MutableList) objects).isEmpty();
}

private void scratchObjectsProvidingRule() throws IOException {
scratch.file(
"foo/BUILD",
"load(':foo.bzl', 'foo')",
"foo(",
" name = 'foo',",
" dep = ':dep',",
")",
"cc_library(",
" name = 'dep',",
" srcs = ['dep.cc'],",
")");
scratch.file(
"foo/foo.bzl",
"FooInfo = provider(fields=['objects', 'pic_objects'])",
"",
"def _foo_impl(ctx):",
" lib = ctx.attr.dep[CcInfo].linking_context.libraries_to_link.to_list()[0]",
" return [FooInfo(objects=lib.objects, pic_objects=lib.pic_objects)]",
"",
"foo = rule(",
" implementation = _foo_impl,",
" attrs = {",
" 'dep': attr.label(),",
" }",
")");
}

private static void createFiles(
Scratch scratch, String bzlFilePath, String compileProviderLines, String linkProviderLines)
throws Exception {
Expand Down

0 comments on commit 9ce04ba

Please sign in to comment.