Skip to content

Commit

Permalink
C++: Exposes C++ Skylark providers to Bazel
Browse files Browse the repository at this point in the history
RELNOTES:none
PiperOrigin-RevId: 202943806
  • Loading branch information
oquenchil authored and Copybara-Service committed Jul 2, 2018
1 parent c7a0155 commit 95a40be
Show file tree
Hide file tree
Showing 12 changed files with 603 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import com.google.devtools.build.lib.bazel.rules.cpp.BazelCcTestRule;
import com.google.devtools.build.lib.bazel.rules.cpp.BazelCppRuleClasses;
import com.google.devtools.build.lib.rules.core.CoreRules;
import com.google.devtools.build.lib.rules.cpp.CcCompilationInfo;
import com.google.devtools.build.lib.rules.cpp.CcHostToolchainAliasRule;
import com.google.devtools.build.lib.rules.cpp.CcImportRule;
import com.google.devtools.build.lib.rules.cpp.CcLibcTopAlias;
import com.google.devtools.build.lib.rules.cpp.CcLinkingInfo;
import com.google.devtools.build.lib.rules.cpp.CcModule;
import com.google.devtools.build.lib.rules.cpp.CcToolchainAliasRule;
import com.google.devtools.build.lib.rules.cpp.CcToolchainRule;
Expand Down Expand Up @@ -76,6 +78,8 @@ public void init(ConfiguredRuleClassProvider.Builder builder) {
builder.addRuleDefinition(new FdoPrefetchHintsRule());

builder.addSkylarkBootstrap(new CcBootstrap(new CcModule()));
builder.addSkylarkAccessibleTopLevels("CcCompilationInfo", CcCompilationInfo.PROVIDER);
builder.addSkylarkAccessibleTopLevels("CcLinkingInfo", CcLinkingInfo.PROVIDER);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.rules.cpp.CcModule.CcSkylarkInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchain;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
Expand Down Expand Up @@ -349,7 +351,9 @@ public Object getDefault(AttributeMap rule) {
attr("deps", LABEL_LIST)
.allowedRuleClasses(DEPS_ALLOWED_RULES)
.allowedFileTypes(CppFileTypes.LINKER_SCRIPT)
.skipAnalysisTimeFileTypeCheck())
.skipAnalysisTimeFileTypeCheck()
.mandatoryProviders(
SkylarkProviderIdentifier.forKey(CcSkylarkInfo.PROVIDER.getKey())))
/*<!-- #BLAZE_RULE($cc_rule).ATTRIBUTE(win_def_file) -->
The Windows DEF file to be passed to linker.
<p>This attribute should only be used when Windows is the target platform.
Expand Down
107 changes: 105 additions & 2 deletions src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,24 @@
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.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.NativeInfo;
import com.google.devtools.build.lib.packages.NativeProvider;
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.rules.cpp.CcModule.CcSkylarkInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcModuleApi;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.CcSkylarkInfoApi;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.SkylarkDict;
Expand All @@ -33,7 +44,32 @@

/** A module that contains Skylark utilities for C++ support. */
public class CcModule
implements CcModuleApi<CcToolchainProvider, FeatureConfiguration, CcToolchainVariables> {
implements CcModuleApi<
CcToolchainProvider,
FeatureConfiguration,
CcToolchainVariables,
LibraryToLink,
CcLinkParams,
CcSkylarkInfo> {

/**
* C++ Skylark rules should have this provider so that native rules can depend on them. This will
* eventually go away once b/73921130 is fixed.
*/
@Immutable
@AutoCodec
public static final class CcSkylarkInfo extends NativeInfo implements CcSkylarkInfoApi {
public static final ObjectCodec<CcSkylarkInfo> CODEC = new CcModule_CcSkylarkInfo_AutoCodec();

public static final NativeProvider<CcSkylarkInfo> PROVIDER =
new NativeProvider<CcSkylarkInfo>(CcSkylarkInfo.class, "CcSkylarkInfo") {};

@AutoCodec.Instantiator
@VisibleForSerialization
CcSkylarkInfo() {
super(PROVIDER);
}
}

@Override
public Provider getCcToolchainProvider() {
Expand Down Expand Up @@ -182,12 +218,79 @@ protected static <T> T convertFromNoneable(Object obj, @Nullable T defaultValue)
}

/** Converts an object that can be the either SkylarkNestedSet or None into NestedSet. */
protected NestedSet<String> asStringNestedSet(Object o) throws EvalException {
protected NestedSet<String> asStringNestedSet(Object o) {
SkylarkNestedSet skylarkNestedSet = convertFromNoneable(o, /* defaultValue= */ null);
if (skylarkNestedSet != null) {
return skylarkNestedSet.getSet(String.class);
} else {
return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
}

@Override
public LibraryToLink createLibraryLinkerInput(
SkylarkRuleContext skylarkRuleContext, Artifact library, String skylarkArtifactCategory)
throws EvalException {
CcCommon.checkRuleWhitelisted(skylarkRuleContext);
ArtifactCategory artifactCategory =
ArtifactCategory.fromString(
skylarkArtifactCategory,
skylarkRuleContext.getRuleContext().getRule().getLocation(),
"artifact_category");
return LinkerInputs.opaqueLibraryToLink(
library, artifactCategory, CcLinkingOutputs.libraryIdentifierOf(library));
}

@Override
public LibraryToLink createSymlinkLibraryLinkerInput(
SkylarkRuleContext skylarkRuleContext, CcToolchainProvider ccToolchain, Artifact library) {
Artifact dynamicLibrarySymlink =
SolibSymlinkAction.getDynamicLibrarySymlink(
skylarkRuleContext.getRuleContext(),
ccToolchain.getSolibDirectory(),
library,
/* preserveName= */ true,
/* prefixConsumer= */ true,
skylarkRuleContext.getRuleContext().getConfiguration());
return LinkerInputs.solibLibraryToLink(
dynamicLibrarySymlink, library, CcLinkingOutputs.libraryIdentifierOf(library));
}

@Override
public CcLinkParams createCcLinkParams(
SkylarkRuleContext skylarkRuleContext,
Object skylarkLibrariesToLink,
Object skylarkDynamicLibrariesForRuntime,
Object skylarkUserLinkFlags)
throws EvalException {
CcCommon.checkRuleWhitelisted(skylarkRuleContext);

SkylarkNestedSet librariesToLink = convertFromNoneable(skylarkLibrariesToLink, null);
SkylarkNestedSet dynamicLibrariesForRuntime =
convertFromNoneable(skylarkDynamicLibrariesForRuntime, null);
SkylarkNestedSet userLinkFlags = convertFromNoneable(skylarkUserLinkFlags, null);

CcLinkParams.Builder builder = CcLinkParams.builder();
if (librariesToLink != null) {
builder.addLibraries(librariesToLink.toCollection(LibraryToLink.class));
}
if (dynamicLibrariesForRuntime != null) {
builder.addDynamicLibrariesForRuntime(
dynamicLibrariesForRuntime.toCollection(Artifact.class));
}
if (userLinkFlags != null) {
builder.addLinkOpts(userLinkFlags.toCollection(String.class));
}
return builder.build();
}

@Override
public CcSkylarkInfo createCcSkylarkInfo(Object skylarkRuleContextObject) throws EvalException {
SkylarkRuleContext skylarkRuleContext =
convertFromNoneable(skylarkRuleContextObject, /* defaultValue= */ null);
if (skylarkRuleContext != null) {
CcCommon.checkRuleWhitelisted(skylarkRuleContext);
}
return new CcSkylarkInfo();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,19 @@
package com.google.devtools.build.lib.rules.cpp;

import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.LinkerInputApi;

/**
* Something that appears on the command line of the linker. Since we sometimes expand archive files
* to their constituent object files, we need to keep information whether a certain file contains
* embedded objects and if so, the list of the object files themselves.
*/
public interface LinkerInput {
public interface LinkerInput extends LinkerInputApi {
/**
* Returns the type of the linker input.
*/
ArtifactCategory getArtifactCategory();

/** Returns the artifact that is the input of the linker. */
@SkylarkCallable(name = "artifact", doc = "Artifact passed to the linker.")
Artifact getArtifact();

/**
* Returns the original library to link. If this library is a solib symlink, returns the
* artifact the symlink points to, otherwise, the library itself.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
import com.google.devtools.build.lib.concurrent.ThreadSafety;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.LibraryToLinkApi;

/**
* Factory for creating new {@link LinkerInput} objects.
Expand Down Expand Up @@ -154,12 +153,7 @@ public boolean isFake() {
* A library the user can link to. This is different from a simple linker input in that it also
* has a library identifier.
*/
@SkylarkModule(
name = "LibraryToLink",
category = SkylarkModuleCategory.BUILTIN,
documented = false,
doc = "A library the user can link to.")
public interface LibraryToLink extends LinkerInput {
public interface LibraryToLink extends LinkerInput, LibraryToLinkApi {
ImmutableMap<Artifact, Artifact> getLtoBitcodeFiles();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@

package com.google.devtools.build.lib.skylarkbuildapi.cpp;


import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.skylark.SkylarkRuleContext;
import com.google.devtools.build.lib.skylarkbuildapi.ProviderApi;
import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleContextApi;
import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.ParamType;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
Expand All @@ -33,7 +35,10 @@
public interface CcModuleApi<
CcToolchainProviderT extends CcToolchainProviderApi,
FeatureConfigurationT extends FeatureConfigurationApi,
CcToolchainVariablesT extends CcToolchainVariablesApi> {
CcToolchainVariablesT extends CcToolchainVariablesApi,
LibraryToLinkT extends LibraryToLinkApi,
CcLinkParamsT extends CcLinkParamsApi,
CcSkylarkInfoT extends CcSkylarkInfoApi> {

@SkylarkCallable(
name = "CcToolchainInfo",
Expand Down Expand Up @@ -450,4 +455,135 @@ CcToolchainVariablesT getLinkBuildVariables(

@SkylarkCallable(name = "empty_variables", documented = false)
CcToolchainVariablesT getVariables();

@SkylarkCallable(
name = "create_library_to_link",
documented = false,
parameters = {
@Param(
name = "ctx",
doc = "Skylark rule context.",
positional = false,
named = true,
type = SkylarkRuleContext.class),
@Param(
name = "library",
doc = "Library to be linked.",
positional = false,
named = true,
type = Artifact.class),
@Param(
name = "artifact_category",
doc =
"Artifact category. Can be: static_library, alwayslink_static_library, "
+ "dynamic_library or interface_library",
positional = false,
named = true,
type = String.class)
})
LibraryToLinkT createLibraryLinkerInput(
SkylarkRuleContext skylarkRuleContext, Artifact library, String skylarkArtifactCategory)
throws EvalException;

@SkylarkCallable(
name = "create_symlink_library_to_link",
documented = false,
parameters = {
@Param(
name = "ctx",
doc = "Skylark rule context.",
positional = false,
named = true,
type = SkylarkRuleContext.class),
@Param(
name = "cc_toolchain",
doc = "C++ toolchain provider to be used.",
positional = false,
named = true,
type = CcToolchainProviderApi.class),
@Param(
name = "library",
doc = "Library that should be symlinked.",
positional = false,
named = true,
type = Artifact.class),
})
LibraryToLinkT createSymlinkLibraryLinkerInput(
SkylarkRuleContext skylarkRuleContext, CcToolchainProviderT ccToolchain, Artifact library);

@SkylarkCallable(
name = "create_cc_link_params",
doc = "Creates cc link parameters",
parameters = {
@Param(
name = "ctx",
positional = false,
named = true,
type = SkylarkRuleContextApi.class,
doc = "The rule context."),
@Param(
name = "libraries_to_link",
doc =
"List of libraries that should be passed to the linker/archiver. They can be "
+ "static and/or dynamic libraries.",
positional = false,
named = true,
noneable = true,
defaultValue = "None",
allowedTypes = {
@ParamType(type = SkylarkNestedSet.class),
@ParamType(type = NoneType.class)
}),
@Param(
name = "dynamic_libraries_for_runtime",
doc =
"When 'libraries_to_link' has dynamic libraries, then the runtime library can "
+ "be specified as well. This is not obligatory though, as we may provide a "
+ "library for linking and at runtime the actual library will be provided by "
+ "the system.",
positional = false,
named = true,
noneable = true,
defaultValue = "None",
allowedTypes = {
@ParamType(type = SkylarkNestedSet.class),
@ParamType(type = NoneType.class)
}),
@Param(
name = "user_link_flags",
doc = "List of user provided linker flags.",
positional = false,
named = true,
noneable = true,
defaultValue = "None",
allowedTypes = {
@ParamType(type = SkylarkNestedSet.class),
@ParamType(type = NoneType.class)
})
})
CcLinkParamsT createCcLinkParams(
SkylarkRuleContext skylarkRuleContext,
Object skylarkLibrariesToLink,
Object skylarkDynamicLibrariesForRuntime,
Object skylarkUserLinkFlags)
throws EvalException;

@SkylarkCallable(
name = "create_cc_skylark_info",
documented = false,
parameters = {
// TODO(plf): Make this parameter mandatory. Change cc_embed_data.bzl first.
@Param(
name = "ctx",
doc = "Skylark rule context.",
positional = false,
named = true,
noneable = true,
defaultValue = "None",
allowedTypes = {
@ParamType(type = SkylarkRuleContextApi.class),
@ParamType(type = NoneType.class)
})
})
CcSkylarkInfoT createCcSkylarkInfo(Object skylarkRuleContextObject) throws EvalException;
}
Loading

0 comments on commit 95a40be

Please sign in to comment.