Skip to content

Commit

Permalink
Add the flag --auto_output_filter=[none,all,packages,subpackages] to …
Browse files Browse the repository at this point in the history
…Bazel.

While compiler warnings and debugging output can be valuable, they can
also make your build log hard to read: Ever had the problem of spotting an error
in 150.000 lines of compiler warnings? Or do you only want to see warnings that
come from the code you're actually working on? Bazel now has a flag to help you
out: With the new flag --auto_output_filter=[none,all,packages,subpackages] you
can instruct Bazel to not print any warnings (--auto_output_filter=all), print
only warnings from the packages explicitly listed as targets on your
command-line (--auto_output_filter=packages) or from those packages and all
their subpackages (--auto_output_filter=subpackages). The flag
--auto_output_filter=none means "don't filter anything", thus results in all
warnings being printed (which is also Bazel's current default behavior). Output from failing commands will always be printed, no matter to which package it belongs.

RELNOTES: Bazel now supports hiding compiler warnings for targets that you're not explicitly building (see https://docs.bazel.build/versions/master/user-manual.html#flag--auto_output_filter).
PiperOrigin-RevId: 251419807
  • Loading branch information
philwo authored and copybara-github committed Jun 4, 2019
1 parent b7eca20 commit 62dd174
Show file tree
Hide file tree
Showing 13 changed files with 869 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ filegroup(
"//src/main/java/com/google/devtools/build/lib:srcs",
"//src/main/java/com/google/devtools/build/lib/includescanning:srcs",
"//src/main/java/com/google/devtools/build/lib/network:srcs",
"//src/main/java/com/google/devtools/build/lib/outputfilter:srcs",
"//src/main/java/com/google/devtools/build/skydoc:srcs",
"//src/main/java/com/google/devtools/build/skyframe:srcs",
"//src/main/java/com/google/devtools/common/options:srcs",
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/google/devtools/build/lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/dynamic",
"//src/main/java/com/google/devtools/build/lib/metrics:metrics_module",
"//src/main/java/com/google/devtools/build/lib/network:connectivity",
"//src/main/java/com/google/devtools/build/lib/outputfilter",
"//src/main/java/com/google/devtools/build/lib/profiler/callcounts:callcounts_module",
"//src/main/java/com/google/devtools/build/lib/profiler/memory:allocationtracker_module",
"//src/main/java/com/google/devtools/build/lib/remote",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public final class Bazel {
com.google.devtools.build.lib.bazel.repository.RepositoryResolvedModule.class,
com.google.devtools.build.lib.bazel.repository.CacheHitReportingModule.class,
com.google.devtools.build.lib.bazel.SpawnLogModule.class,
com.google.devtools.build.lib.outputfilter.OutputFilteringModule.class,
com.google.devtools.build.lib.ssd.SsdModule.class,
com.google.devtools.build.lib.worker.WorkerModule.class,
com.google.devtools.build.lib.remote.RemoteModule.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright 2019 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.outputfilter;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSortedSet;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.OutputFilter;
import com.google.devtools.build.lib.events.OutputFilter.RegexOutputFilter;
import com.google.devtools.common.options.EnumConverter;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.regex.Pattern;

/**
* Implementation of various settings for the {@code --auto_output_filter}
* option.
*
* <p>Note that any actions owned by the system owner (typically just the build info
* action) are treated specially: They are not filtered out by these auto filters.
*/
public enum AutoOutputFilter {
/**
* Generates an empty output filter (i.e. one that matches everything).
*/
NONE {
@Override
public OutputFilter getFilter(Iterable<Label> targets) {
return OutputFilter.OUTPUT_EVERYTHING;
}
},

/**
* Generates an output filter that matches nothing.
*/
ALL {
@Override
public OutputFilter getFilter(Iterable<Label> targets) {
return OutputFilter.OUTPUT_NOTHING;
}
},

/**
* Generates an output filter that matches all targets that are in the same
* package as a target on the command line. {@code //java/foo} and
* {@code //javatests/foo} are treated like a single package.
*/
PACKAGES {
@Override
public OutputFilter getFilter(Iterable<Label> targets) {
Pattern pattern = Pattern.compile(SYSTEM_ACTION_REGEX + "|"
+ "^//" + getPkgRegex(getPackages(targets)) + ":");
return RegexOutputFilter.forPattern(pattern);
}
},

/**
* Generates an output filter that matches all targets that are in the same
* package or in a subpackage of a target on the command line.
* {@code //java/foo} and {@code //javatests/foo} are treated like a single
* package.
*/
SUBPACKAGES {
@Override
public OutputFilter getFilter(Iterable<Label> targets) {
List<String> packages = new ArrayList<>();

String previous = null;
for (String pkg : getPackages(targets)) {
if (previous != null && pkg.startsWith(previous + "/")) {
// We already have a super-package in the list, so this package does
// not need to be added.
continue;
}
packages.add(pkg);
previous = pkg;
}

Pattern pattern = Pattern.compile(SYSTEM_ACTION_REGEX + "|"
+ "^//" + getPkgRegex(packages) + "[/:]");
return RegexOutputFilter.forPattern(pattern);
}
};

/** An empty pattern */
private static final String SYSTEM_ACTION_NAME = "(unknown)";
private static final String SYSTEM_ACTION_REGEX = SYSTEM_ACTION_NAME;

/** Returns an output filter regex for a set of requested targets. */
public abstract OutputFilter getFilter(Iterable<Label> targets);

/**
* Returns the package names of a some targets as an alphabetically sorted list. If there are
* targets under {@code //java/...} or {@code //javatests/...}, a string starting with
* "java(tests)?" is added instead.
*/
protected SortedSet<String> getPackages(Iterable<Label> targets) {
ImmutableSortedSet.Builder<String> packages = ImmutableSortedSet.naturalOrder();
for (Label label : targets) {
String name = label.getPackageName();
// Treat //java/foo and //javatests/foo as one package
if (name.startsWith("java/") || name.startsWith("javatests/")) {
name = "java(tests)?" + name.substring(name.indexOf('/'));
}
packages.add(name);
}
return packages.build();
}

/**
* Builds a regular expression that matches one of several strings. Characters
* that have a special meaning in regular expressions will not be escaped.
*/
protected String getPkgRegex(Iterable<String> strings) {
return "(" + Joiner.on('|').join(strings) + ")";
}

/**
* A converter for the {@code --auto_output_filter} option.
*/
public static class Converter extends EnumConverter<AutoOutputFilter> {
public Converter() {
super(AutoOutputFilter.class, "automatic output filter");
}
}
}
22 changes: 22 additions & 0 deletions src/main/java/com/google/devtools/build/lib/outputfilter/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package(
default_visibility = ["//src:__subpackages__"],
)

filegroup(
name = "srcs",
srcs = glob(["*"]),
)

java_library(
name = "outputfilter",
srcs = glob(["*.java"]),
deps = [
"//src/main/java/com/google/devtools/build/lib:build-request-options",
"//src/main/java/com/google/devtools/build/lib:events",
"//src/main/java/com/google/devtools/build/lib:packages-internal",
"//src/main/java/com/google/devtools/build/lib:runtime",
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/common/options",
"//third_party:guava",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2019 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.outputfilter;

import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.Subscribe;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
import com.google.devtools.build.lib.buildtool.buildevent.BuildStartingEvent;
import com.google.devtools.build.lib.events.OutputFilter.RegexOutputFilter;
import com.google.devtools.build.lib.pkgcache.TargetParsingCompleteEvent;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import java.util.regex.Pattern;

/**
* Blaze module implementing output filtering.
*/
public final class OutputFilteringModule extends BlazeModule {
/**
* Options controlling output filtering.
*/
public static class Options extends OptionsBase {
@Option(
name = "auto_output_filter",
converter = AutoOutputFilter.Converter.class,
defaultValue = "none",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
effectTags = {OptionEffectTag.UNKNOWN},
help =
"If --output_filter is not specified, then the value for this option is used "
+ "create a filter automatically. Allowed values are 'none' (filter nothing "
+ "/ show everything), 'all' (filter everything / show nothing), 'packages' "
+ "(include output from rules in packages mentioned on the Blaze command line), "
+ "and 'subpackages' (like 'packages', but also include subpackages). For the "
+ "'packages' and 'subpackages' values //java/foo and //javatests/foo are treated "
+ "as one package)'.")
public AutoOutputFilter autoOutputFilter;
}

private CommandEnvironment env;
private AutoOutputFilter autoOutputFilter;

@Override
public Iterable<Class<? extends OptionsBase>> getCommandOptions(Command command) {
return "build".equals(command.name()) ? ImmutableList.of(Options.class) : ImmutableList.of();
}

@Override
public void beforeCommand(CommandEnvironment env) {
this.env = env;
env.getEventBus().register(this);
}

@Override
public void afterCommand() {
this.env = null;
this.autoOutputFilter = null;
}

@Subscribe
@SuppressWarnings("unused")
public void buildStarting(BuildStartingEvent event) {
BuildRequestOptions requestOptions = env.getOptions().getOptions(BuildRequestOptions.class);
Pattern outputFilter =
(requestOptions != null) && (requestOptions.outputFilter != null)
? requestOptions.outputFilter.regexPattern()
: null;
if (outputFilter != null) {
// Coarse-grained initialization of the output filter. This only has an
// effect if the --output_filter option is given. The auto output filter is
// only initialized later, when we know all targets. For now this is good
// enough, as the target parsing only loads packages that are mentioned on
// the command line (which are included by all auto output filters).
env.getReporter().setOutputFilter(RegexOutputFilter.forPattern(outputFilter));
} else {
this.autoOutputFilter = env.getOptions().getOptions(Options.class).autoOutputFilter;
}
}

@Subscribe
@SuppressWarnings("unused")
public void targetParsingComplete(TargetParsingCompleteEvent event) {
if (autoOutputFilter != null) {
env.getReporter().setOutputFilter(autoOutputFilter.getFilter(event.getLabels()));
}
}
}
1 change: 1 addition & 0 deletions src/test/java/com/google/devtools/build/lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ filegroup(
"//src/test/java/com/google/devtools/build/lib/buildeventstream:srcs",
"//src/test/java/com/google/devtools/build/lib/buildeventstream/transports:srcs",
"//src/test/java/com/google/devtools/build/lib/buildtool:srcs",
"//src/test/java/com/google/devtools/build/lib/outputfilter:srcs",
"//src/test/java/com/google/devtools/build/lib/packages/util/mock:srcs",
"//src/test/java/com/google/devtools/build/lib/profiler:srcs",
"//src/test/java/com/google/devtools/build/lib/profiler/callcounts:srcs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public Throwable getException() {
* that may not have been initialized yet.
*/
protected PathFragment getDesiredWorkspaceRelative() {
return PathFragment.create("workspace");
return PathFragment.create(TestConstants.WORKSPACE_NAME);
}

protected InternalTestExecutionMode getInternalTestExecutionMode() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2019 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.buildtool.util;

import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.testutil.TestConstants;

/** Get the workspace status module for tests. */
public class TestWorkspaceStatusModule {
public static BlazeModule getModule() {
try {
Class<?> moduleClass = Class.forName(TestConstants.TEST_WORKSPACE_STATUS_MODULE);
return (BlazeModule) moduleClass.getConstructor().newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}
Loading

0 comments on commit 62dd174

Please sign in to comment.