Skip to content

Commit

Permalink
Add bazel help builtin-symbols-as-proto
Browse files Browse the repository at this point in the history
RELNOTES: The new `bazel help builtin-symbols-as-proto` subcommand emits a base64-encoded proto message describing the built-in Starlark types and global symbols. See `src/main/protobuf/builtin.proto` for the message definition.
  • Loading branch information
fmeum committed Apr 9, 2024
1 parent 6288eb9 commit e4da099
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/main/java/com/google/devtools/build/lib/bazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,21 @@ java_library(
],
)

java_library(
name = "builtin_symbols_proto",
resources = [
"//src/main/java/com/google/devtools/build/lib:gen_api_proto",
],
)

java_binary(
name = "BazelServer",
javacopts = [
"-Xlint:all",
],
main_class = "com.google.devtools.build.lib.bazel.Bazel",
runtime_deps = [
":builtin_symbols_proto", # Adding this to :main would create a cycle
":main",
"//src/main/java/com/google/devtools/build/lib/server",
"//src/main/java/com/google/devtools/build/lib/util:simple_log_handler", # See startup_options.cc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeCommandUtils;
Expand All @@ -52,6 +53,8 @@
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParser.HelpVerbosity;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
Expand Down Expand Up @@ -155,6 +158,8 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti
case "flags-as-proto":
emitFlagsAsProtoHelp(runtime, outErr);
return BlazeCommandResult.success();
case "builtin-symbols-as-proto":
return emitBuiltinSymbolsAsProtoHelp(env.getReporter(), outErr);
case "everything-as-html":
new HtmlEmitter(runtime).emit(outErr);
return BlazeCommandResult.success();
Expand Down Expand Up @@ -263,6 +268,29 @@ private static void emitFlagsAsProtoHelp(BlazeRuntime runtime, OutErr outErr) {
outErr.printOut(Base64.getEncoder().encodeToString(collectionBuilder.build().toByteArray()));
}

private BlazeCommandResult emitBuiltinSymbolsAsProtoHelp(Reporter reporter, OutErr outErr) {
try {
byte[] builtinsProtoBytes;
try (var in =
HelpCommand.class
.getClassLoader()
.getResourceAsStream("com/google/devtools/build/lib/builtin.pb")) {
if (in == null) {
throw new IOException("Could not find built-in symbols proto file");
}
try (var bufferedIn = new BufferedInputStream(in)) {
builtinsProtoBytes = bufferedIn.readAllBytes();
}
}
outErr.printOut(Base64.getEncoder().encodeToString(builtinsProtoBytes));
} catch (IOException e) {
String message = "Failed to get built-in symbols proto: " + e.getMessage();
reporter.handle(Event.error(null, message));
return createFailureResult(message, Code.COMMAND_NOT_FOUND);
}
return BlazeCommandResult.success();
}

private static BazelFlagsProto.FlagInfo.Builder createFlagInfo(OptionDefinition option) {
BazelFlagsProto.FlagInfo.Builder flagBuilder = BazelFlagsProto.FlagInfo.newBuilder();
flagBuilder.setName(option.getOptionName());
Expand Down
18 changes: 18 additions & 0 deletions src/test/java/com/google/devtools/build/lib/runtime/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ java_library(
exclude = [
"commands/ConfigCommandTest.java",
"commands/DumpCommandTest.java",
"commands/HelpCommandTest.java",
],
),
deps = [
Expand Down Expand Up @@ -161,6 +162,23 @@ java_test(
],
)

java_test(
name = "HelpCommandTest",
srcs = ["commands/HelpCommandTest.java"],
deps = [
"//src/main/java/com/google/devtools/build/lib:runtime",
"//src/main/java/com/google/devtools/build/lib:runtime/blaze_command_result",
"//src/main/java/com/google/devtools/build/lib/bazel:builtin_symbols_proto",
"//src/main/java/com/google/devtools/build/lib/runtime/commands",
"//src/main/java/com/google/devtools/build/lib/util/io:out-err",
"//src/main/protobuf:builtin_java_proto",
"//src/test/java/com/google/devtools/build/lib/buildtool/util",
"//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
],
)

java_test(
name = "RuntimeTests",
test_class = "com.google.devtools.build.lib.AllTests",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2022 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.runtime.commands;

import static com.google.common.truth.Truth.assertThat;
import static java.util.stream.Collectors.toMap;

import com.google.common.collect.Lists;
import com.google.devtools.build.docgen.builtin.BuiltinProtos;
import com.google.devtools.build.lib.buildtool.util.BuildIntegrationTestCase;
import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.util.io.RecordingOutErr;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link HelpCommand}. */
@RunWith(JUnit4.class)
public final class HelpCommandTest extends BuildIntegrationTestCase {
private BlazeCommandDispatcher dispatcher;
private RecordingOutErr recordingOutErr;

@Before
public void createDispatcher() {
BlazeRuntime runtime = getRuntime();
runtime.getCommandMap().put("help", new HelpCommand());
dispatcher = new BlazeCommandDispatcher(runtime);
}

@Before
public void createRecording() {
recordingOutErr = new RecordingOutErr();
}

private BlazeCommandResult help(String... args) throws InterruptedException {
List<String> params = Lists.newArrayList("help");
Collections.addAll(params, args);
return dispatcher.exec(params, "test", recordingOutErr);
}

@Test
public void wellKnownCallablesInBuiltinSymbolsProto() throws Exception {
assertThat(help("builtin-symbols-as-proto").isSuccess()).isTrue();
assertThat(recordingOutErr.errAsLatin1()).isEmpty();
String base64Proto = recordingOutErr.outAsLatin1();
byte[] rawProto = Base64.getDecoder().decode(base64Proto);
var builtins = BuiltinProtos.Builtins.parseFrom(rawProto);

assertThat(
builtins.getGlobalList().stream()
.filter(BuiltinProtos.Value::hasCallable)
.filter(global -> !global.getCallable().getParamList().isEmpty())
.collect(toMap(BuiltinProtos.Value::getName, BuiltinProtos.Value::getApiContext)))
.containsAtLeast(
"range", BuiltinProtos.ApiContext.ALL,
"glob", BuiltinProtos.ApiContext.BUILD,
"DefaultInfo", BuiltinProtos.ApiContext.BZL);
}
}

0 comments on commit e4da099

Please sign in to comment.