/*
* Copyright 2015-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.halide;
import com.facebook.buck.cxx.Archive;
import com.facebook.buck.cxx.CxxDescriptionEnhancer;
import com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.cxx.CxxPreprocessables;
import com.facebook.buck.cxx.CxxPreprocessorDep;
import com.facebook.buck.cxx.CxxPreprocessorInput;
import com.facebook.buck.cxx.HeaderVisibility;
import com.facebook.buck.cxx.ImmutableCxxPreprocessorInputCacheKey;
import com.facebook.buck.cxx.Linker;
import com.facebook.buck.cxx.NativeLinkable;
import com.facebook.buck.cxx.NativeLinkableInput;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.NoopBuildRule;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.args.Arg;
import com.facebook.buck.rules.args.SourcePathArg;
import com.google.common.base.Preconditions;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import java.util.Optional;
import java.util.regex.Pattern;
public class HalideLibrary extends NoopBuildRule implements CxxPreprocessorDep, NativeLinkable {
private final BuildRuleParams params;
private final BuildRuleResolver ruleResolver;
private final Optional<Pattern> supportedPlatformsRegex;
private final LoadingCache<
CxxPreprocessables.CxxPreprocessorInputCacheKey,
ImmutableMap<BuildTarget, CxxPreprocessorInput>>
transitiveCxxPreprocessorInputCache =
CxxPreprocessables.getTransitiveCxxPreprocessorInputCache(this);
protected HalideLibrary(
BuildRuleParams params,
BuildRuleResolver ruleResolver,
Optional<Pattern> supportedPlatformsRegex) {
super(params);
this.params = params;
this.ruleResolver = ruleResolver;
this.supportedPlatformsRegex = supportedPlatformsRegex;
}
private boolean isPlatformSupported(CxxPlatform cxxPlatform) {
return !supportedPlatformsRegex.isPresent()
|| supportedPlatformsRegex.get().matcher(cxxPlatform.getFlavor().toString()).find();
}
@Override
public Iterable<? extends CxxPreprocessorDep> getCxxPreprocessorDeps(CxxPlatform cxxPlatform) {
if (!isPlatformSupported(cxxPlatform)) {
return ImmutableList.of();
}
return FluentIterable.from(getBuildDeps()).filter(CxxPreprocessorDep.class);
}
@Override
public CxxPreprocessorInput getCxxPreprocessorInput(
CxxPlatform cxxPlatform, HeaderVisibility headerVisibility)
throws NoSuchBuildTargetException {
if (!isPlatformSupported(cxxPlatform)) {
return CxxPreprocessorInput.EMPTY;
}
switch (headerVisibility) {
case PUBLIC:
return CxxPreprocessables.getCxxPreprocessorInput(
params,
ruleResolver,
/* hasHeaderSymlinkTree */ true,
cxxPlatform,
headerVisibility,
CxxPreprocessables.IncludeType.SYSTEM,
ImmutableMultimap.of(),
ImmutableList.of());
case PRIVATE:
return CxxPreprocessorInput.EMPTY;
}
throw new RuntimeException("Invalid header visibility: " + headerVisibility);
}
@Override
public ImmutableMap<BuildTarget, CxxPreprocessorInput> getTransitiveCxxPreprocessorInput(
CxxPlatform cxxPlatform, HeaderVisibility headerVisibility) {
return transitiveCxxPreprocessorInputCache.getUnchecked(
ImmutableCxxPreprocessorInputCacheKey.of(cxxPlatform, headerVisibility));
}
@Override
public Iterable<NativeLinkable> getNativeLinkableDeps() {
return FluentIterable.from(getDeclaredDeps()).filter(NativeLinkable.class);
}
@Override
public Iterable<NativeLinkable> getNativeLinkableDepsForPlatform(CxxPlatform cxxPlatform) {
if (!isPlatformSupported(cxxPlatform)) {
return ImmutableList.of();
}
return getNativeLinkableDeps();
}
@Override
public Iterable<NativeLinkable> getNativeLinkableExportedDeps() {
return ImmutableList.of();
}
private Arg requireLibraryArg(CxxPlatform cxxPlatform, Linker.LinkableDepType type)
throws NoSuchBuildTargetException {
BuildRule rule =
ruleResolver.requireRule(
getBuildTarget()
.withFlavors(
CxxDescriptionEnhancer.flavorForLinkableDepType(type),
cxxPlatform.getFlavor()));
if (rule instanceof Archive) {
return ((Archive) rule).toArg();
} else {
return SourcePathArg.of(Preconditions.checkNotNull(rule.getSourcePathToOutput()));
}
}
@Override
public NativeLinkableInput getNativeLinkableInput(
CxxPlatform cxxPlatform, Linker.LinkableDepType type) throws NoSuchBuildTargetException {
if (!isPlatformSupported(cxxPlatform)) {
return NativeLinkableInput.of();
}
return NativeLinkableInput.of(
ImmutableList.of(requireLibraryArg(cxxPlatform, type)),
ImmutableSet.of(),
ImmutableSet.of());
}
@Override
public NativeLinkable.Linkage getPreferredLinkage(CxxPlatform cxxPlatform) {
return NativeLinkable.Linkage.STATIC;
}
@Override
public ImmutableMap<String, SourcePath> getSharedLibraries(CxxPlatform cxxPlatform) {
return ImmutableMap.of();
}
}