blob: 6ff397d995fb4f21cc6458ae805bc2f6ccba60de [file] [log] [blame]
// Copyright 2015 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.proto;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.cmdline.BazelModuleContext;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.StarlarkInfo;
import com.google.devtools.build.lib.vfs.PathFragment;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Module;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkFunction;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.eval.Tuple;
/** Utility functions for proto_library and proto aspect implementations. */
public class ProtoCommon {
private ProtoCommon() {
throw new UnsupportedOperationException();
}
private static final Interner<PathFragment> PROTO_SOURCE_ROOT_INTERNER =
BlazeInterners.newWeakInterner();
/**
* Returns a memory efficient version of the passed protoSourceRoot.
*
* <p>Any sizable proto graph will contain many {@code .proto} sources with the same source root.
* We can't afford to have all of them represented as individual objects in memory.
*
* @param protoSourceRoot
* @return
*/
static PathFragment memoryEfficientProtoSourceRoot(PathFragment protoSourceRoot) {
return PROTO_SOURCE_ROOT_INTERNER.intern(protoSourceRoot);
}
public static void checkPrivateStarlarkificationAllowlist(StarlarkThread thread)
throws EvalException {
Label label =
((BazelModuleContext) Module.ofInnermostEnclosingStarlarkFunction(thread).getClientData())
.label();
if (!label.getPackageIdentifier().getRepository().toString().equals("@_builtins")) {
throw Starlark.errorf("Rule in '%s' cannot use private API", label.getPackageName());
}
}
public static ImmutableList<Artifact> declareGeneratedFiles(
RuleContext ruleContext, ConfiguredTarget protoTarget, String extension)
throws RuleErrorException, InterruptedException {
StarlarkFunction declareGeneratedFiles =
(StarlarkFunction)
ruleContext.getStarlarkDefinedBuiltin("proto_common_declare_generated_files");
ruleContext.initStarlarkRuleContext();
Sequence<?> outputs =
(Sequence<?>)
ruleContext.callStarlarkOrThrowRuleError(
declareGeneratedFiles,
ImmutableList.of(
/* actions */ ruleContext.getStarlarkRuleContext().actions(),
/* proto_info */ protoTarget.get(ProtoInfo.PROVIDER),
/* extension */ extension),
ImmutableMap.of());
try {
return Sequence.cast(outputs, Artifact.class, "declare_generated_files").getImmutableList();
} catch (EvalException e) {
throw new RuleErrorException(e.getMessageWithStack());
}
}
public static void compile(
RuleContext ruleContext,
ConfiguredTarget protoTarget,
StarlarkInfo protoLangToolchainInfo,
Iterable<Artifact> generatedFiles,
@Nullable Object pluginOutput,
String progressMessage,
String execGroup)
throws RuleErrorException, InterruptedException {
StarlarkFunction compile =
(StarlarkFunction) ruleContext.getStarlarkDefinedBuiltin("proto_common_compile");
ruleContext.initStarlarkRuleContext();
ruleContext.callStarlarkOrThrowRuleError(
compile,
ImmutableList.of(
/* actions */ ruleContext.getStarlarkRuleContext().actions(),
/* proto_info */ protoTarget.get(ProtoInfo.PROVIDER),
/* proto_lang_toolchain_info */ protoLangToolchainInfo,
/* generated_files */ StarlarkList.immutableCopyOf(generatedFiles),
/* plugin_output */ pluginOutput == null ? Starlark.NONE : pluginOutput),
ImmutableMap.of(
"experimental_progress_message",
progressMessage,
"experimental_exec_group",
execGroup));
}
public static Sequence<Artifact> filterSources(
RuleContext ruleContext, ConfiguredTarget protoTarget, StarlarkInfo protoLangToolchainInfo)
throws RuleErrorException, InterruptedException {
StarlarkFunction filterSources =
(StarlarkFunction)
ruleContext.getStarlarkDefinedBuiltin("proto_common_experimental_filter_sources");
ruleContext.initStarlarkRuleContext();
try {
return Sequence.cast(
((Tuple)
ruleContext.callStarlarkOrThrowRuleError(
filterSources,
ImmutableList.of(
/* proto_info */ protoTarget.get(ProtoInfo.PROVIDER),
/* proto_lang_toolchain_info */ protoLangToolchainInfo),
ImmutableMap.of()))
.get(0),
Artifact.class,
"included");
} catch (EvalException e) {
throw new RuleErrorException(e.getMessageWithStack());
}
}
}