blob: 492e1a47cbc05416a08f2a8eea4afbc9d6066b47 [file] [log] [blame]
// 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.analysis;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.devtools.build.lib.analysis.config.Fragment;
import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.devtools.build.lib.util.ClassName;
import java.util.List;
/**
* Provides a user-friendly list of the {@link Fragment}s and {@link
* com.google.devtools.build.lib.analysis.config.FragmentOptions} required by this target and its
* transitive dependencies.
*
* <p>See {@link com.google.devtools.build.lib.analysis.config.RequiredFragmentsUtil} for details.
*/
@Immutable
public final class RequiredConfigFragmentsProvider implements TransitiveInfoProvider {
@SerializationConstant
public static final RequiredConfigFragmentsProvider EMPTY =
new RequiredConfigFragmentsProvider(
ImmutableSet.of(),
FragmentClassSet.of(ImmutableSet.of()),
ImmutableSet.of(),
ImmutableSet.of());
private final ImmutableSet<Class<? extends FragmentOptions>> optionsClasses;
private final FragmentClassSet fragmentClasses;
private final ImmutableSet<String> defines;
private final ImmutableSet<Label> starlarkOptions;
private RequiredConfigFragmentsProvider(
ImmutableSet<Class<? extends FragmentOptions>> optionsClasses,
FragmentClassSet fragmentClasses,
ImmutableSet<String> defines,
ImmutableSet<Label> starlarkOptions) {
this.optionsClasses = optionsClasses;
this.fragmentClasses = fragmentClasses;
this.defines = defines;
this.starlarkOptions = starlarkOptions;
}
public ImmutableSet<Class<? extends FragmentOptions>> getOptionsClasses() {
return optionsClasses;
}
public FragmentClassSet getFragmentClasses() {
return fragmentClasses;
}
public ImmutableSet<String> getDefines() {
return defines;
}
public ImmutableSet<Label> getStarlarkOptions() {
return starlarkOptions;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add(
"optionsClasses",
Collections2.transform(optionsClasses, ClassName::getSimpleNameWithOuter))
.add("fragmentClasses", fragmentClasses)
.add("defines", defines)
.add("starlarkOptions", starlarkOptions)
.toString();
}
/** Merges the values of one or more {@link RequiredConfigFragmentsProvider} instances. */
public static RequiredConfigFragmentsProvider merge(
List<RequiredConfigFragmentsProvider> providers) {
checkArgument(!providers.isEmpty());
RequiredConfigFragmentsProvider.Builder merged = null;
RequiredConfigFragmentsProvider candidate = EMPTY;
for (RequiredConfigFragmentsProvider provider : providers) {
if (provider == EMPTY) {
continue;
}
if (merged != null) {
merged.merge(provider);
} else if (candidate == EMPTY) {
candidate = provider;
} else {
merged = builder().merge(candidate).merge(provider);
}
}
return merged == null ? candidate : merged.build();
}
public static Builder builder() {
return new Builder();
}
/** Builder for required config fragments. */
public static final class Builder {
private final ImmutableSet.Builder<Class<? extends FragmentOptions>> optionsClasses =
ImmutableSet.builder();
private final ImmutableSet.Builder<Class<? extends Fragment>> fragmentClasses =
ImmutableSortedSet.orderedBy(FragmentClassSet.LEXICAL_FRAGMENT_SORTER);
private final ImmutableSet.Builder<String> defines = ImmutableSet.builder();
private final ImmutableSet.Builder<Label> starlarkOptions = ImmutableSet.builder();
private Builder() {}
public Builder addOptionsClass(Class<? extends FragmentOptions> optionsClass) {
optionsClasses.add(optionsClass);
return this;
}
public Builder addOptionsClasses(Iterable<Class<? extends FragmentOptions>> optionsClasses) {
this.optionsClasses.addAll(optionsClasses);
return this;
}
public Builder addFragmentClasses(Iterable<Class<? extends Fragment>> fragmentClasses) {
this.fragmentClasses.addAll(fragmentClasses);
return this;
}
public Builder addDefine(String define) {
defines.add(define);
return this;
}
public Builder addDefines(Iterable<String> defines) {
this.defines.addAll(defines);
return this;
}
public Builder addStarlarkOption(Label starlarkOption) {
starlarkOptions.add(starlarkOption);
return this;
}
public Builder addStarlarkOptions(Iterable<Label> starlarkOptions) {
this.starlarkOptions.addAll(starlarkOptions);
return this;
}
public Builder merge(RequiredConfigFragmentsProvider provider) {
optionsClasses.addAll(provider.optionsClasses);
fragmentClasses.addAll(provider.fragmentClasses);
defines.addAll(provider.defines);
starlarkOptions.addAll(provider.starlarkOptions);
return this;
}
public RequiredConfigFragmentsProvider build() {
ImmutableSet<Class<? extends FragmentOptions>> optionsClasses = this.optionsClasses.build();
ImmutableSet<Class<? extends Fragment>> fragmentClasses = this.fragmentClasses.build();
ImmutableSet<String> defines = this.defines.build();
ImmutableSet<Label> starlarkOptions = this.starlarkOptions.build();
if (optionsClasses.isEmpty()
&& fragmentClasses.isEmpty()
&& defines.isEmpty()
&& starlarkOptions.isEmpty()) {
return EMPTY;
}
return new RequiredConfigFragmentsProvider(
optionsClasses, FragmentClassSet.of(fragmentClasses), defines, starlarkOptions);
}
}
}