/*
* Copyright 2016-present Facebook, Inc.
*
* 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.facebook.buck.cxx;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.RuleKeyObjectSink;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.coercer.FrameworkPath;
import com.facebook.buck.util.OptionalCompat;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
import java.util.Optional;
import org.immutables.value.Value;
@Value.Immutable
@BuckStyleImmutable
abstract class AbstractPreprocessorFlags {
/** File set via {@code -include}. */
@Value.Parameter
public abstract Optional<SourcePath> getPrefixHeader();
/** Other flags included as is. */
@Value.Parameter
@Value.Default
public CxxToolFlags getOtherFlags() {
return CxxToolFlags.of();
}
/** Directories set via {@code -I}. */
@Value.Parameter
public abstract ImmutableSet<CxxHeaders> getIncludes();
/** Directories set via {@code -F}. */
@Value.Parameter
public abstract ImmutableSet<FrameworkPath> getFrameworkPaths();
@Value.Lazy
public CxxIncludePaths getCxxIncludePaths() {
return CxxIncludePaths.of(getIncludes(), getFrameworkPaths());
}
public Iterable<BuildRule> getDeps(SourcePathRuleFinder ruleFinder) {
ImmutableList.Builder<BuildRule> deps = ImmutableList.builder();
deps.addAll(ruleFinder.filterBuildRuleInputs(OptionalCompat.asSet(getPrefixHeader())));
for (CxxHeaders cxxHeaders : getIncludes()) {
deps.addAll(cxxHeaders.getDeps(ruleFinder));
}
for (FrameworkPath frameworkPath : getFrameworkPaths()) {
deps.addAll(frameworkPath.getDeps(ruleFinder));
}
return deps.build();
}
/** Append to rule key the members which are not handled elsewhere. */
public void appendToRuleKey(RuleKeyObjectSink sink, DebugPathSanitizer sanitizer) {
sink.setReflectively("prefixHeader", getPrefixHeader());
sink.setReflectively("includes", getIncludes());
sink.setReflectively("frameworkRoots", getFrameworkPaths());
// Sanitize any relevant paths in the flags we pass to the preprocessor, to prevent them
// from contributing to the rule key.
sink.setReflectively(
"platformPreprocessorFlags", sanitizer.sanitizeFlags(getOtherFlags().getPlatformFlags()));
sink.setReflectively(
"rulePreprocessorFlags", sanitizer.sanitizeFlags(getOtherFlags().getRuleFlags()));
}
public CxxToolFlags getIncludePathFlags(
SourcePathResolver resolver,
PathShortener pathShortener,
Function<FrameworkPath, Path> frameworkPathTransformer,
Preprocessor preprocessor) {
return CxxToolFlags.explicitBuilder()
.addAllRuleFlags(
getCxxIncludePaths()
.getFlags(resolver, pathShortener, frameworkPathTransformer, preprocessor))
.build();
}
public CxxToolFlags getNonIncludePathFlags(
SourcePathResolver resolver, Optional<CxxPrecompiledHeader> pch, Preprocessor preprocessor) {
ExplicitCxxToolFlags.Builder builder = CxxToolFlags.explicitBuilder();
ExplicitCxxToolFlags.addCxxToolFlags(builder, getOtherFlags());
builder.addAllRuleFlags(
preprocessor.prefixOrPCHArgs(
resolver,
getPrefixHeader(),
pch.map(CxxPrecompiledHeader::getSourcePathToOutput).map(resolver::getRelativePath)));
return builder.build();
}
public CxxToolFlags toToolFlags(
SourcePathResolver resolver,
PathShortener pathShortener,
Function<FrameworkPath, Path> frameworkPathTransformer,
Preprocessor preprocessor,
Optional<CxxPrecompiledHeader> pch) {
return CxxToolFlags.concat(
getNonIncludePathFlags(resolver, pch, preprocessor),
getIncludePathFlags(resolver, pathShortener, frameworkPathTransformer, preprocessor));
}
}