Java tutorial
/* * Copyright 2014-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.apple; 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.HeaderSymlinkTree; 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.model.BuildTargets; import com.facebook.buck.model.Flavor; import com.facebook.buck.model.HasOutputName; import com.facebook.buck.model.Pair; import com.facebook.buck.parser.NoSuchBuildTargetException; import com.facebook.buck.rules.AbstractBuildRuleWithResolver; import com.facebook.buck.rules.AddToRuleKey; import com.facebook.buck.rules.BuildContext; import com.facebook.buck.rules.BuildRuleParams; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.BuildTargetSourcePath; import com.facebook.buck.rules.BuildableContext; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.args.Arg; import com.facebook.buck.rules.args.StringArg; import com.facebook.buck.rules.coercer.FrameworkPath; import com.facebook.buck.step.Step; import com.facebook.buck.step.fs.CopyStep; import com.facebook.buck.step.fs.MkdirStep; import com.facebook.buck.step.fs.RmStep; import com.google.common.base.Function; 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.ImmutableSet; import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.regex.Pattern; public class PrebuiltAppleFramework extends AbstractBuildRuleWithResolver implements CxxPreprocessorDep, NativeLinkable, HasOutputName { @AddToRuleKey(stringify = true) private final Path out; @AddToRuleKey private final NativeLinkable.Linkage preferredLinkage; private final BuildRuleResolver ruleResolver; private final SourcePath frameworkPath; private final String frameworkName; private final Function<? super CxxPlatform, ImmutableList<String>> exportedLinkerFlags; private final ImmutableSet<FrameworkPath> frameworks; private final Optional<Pattern> supportedPlatformsRegex; private final Map<Pair<Flavor, Linker.LinkableDepType>, NativeLinkableInput> nativeLinkableCache = new HashMap<>(); private final LoadingCache<CxxPreprocessables.CxxPreprocessorInputCacheKey, ImmutableMap<BuildTarget, CxxPreprocessorInput>> transitiveCxxPreprocessorInputCache = CxxPreprocessables .getTransitiveCxxPreprocessorInputCache(this); public PrebuiltAppleFramework(BuildRuleParams params, BuildRuleResolver ruleResolver, SourcePathResolver pathResolver, SourcePath frameworkPath, Linkage preferredLinkage, ImmutableSet<FrameworkPath> frameworks, Optional<Pattern> supportedPlatformsRegex, Function<? super CxxPlatform, ImmutableList<String>> exportedLinkerFlags) { super(params, pathResolver); this.frameworkPath = frameworkPath; this.ruleResolver = ruleResolver; this.exportedLinkerFlags = exportedLinkerFlags; this.preferredLinkage = preferredLinkage; this.frameworks = frameworks; this.supportedPlatformsRegex = supportedPlatformsRegex; BuildTarget target = params.getBuildTarget(); this.frameworkName = pathResolver.getAbsolutePath(frameworkPath).getFileName().toString(); this.out = BuildTargets.getGenPath(getProjectFilesystem(), target, "%s").resolve(frameworkName); } private boolean isPlatformSupported(CxxPlatform cxxPlatform) { return !supportedPlatformsRegex.isPresent() || supportedPlatformsRegex.get().matcher(cxxPlatform.getFlavor().toString()).find(); } @Override public ImmutableList<Step> getBuildSteps(BuildContext context, BuildableContext buildableContext) { // This file is copied rather than symlinked so that when it is included in an archive zip and // unpacked on another machine, it is an ordinary file in both scenarios. ImmutableList.Builder<Step> builder = ImmutableList.builder(); builder.add(new MkdirStep(getProjectFilesystem(), out.getParent())); builder.add(new RmStep(getProjectFilesystem(), out, RmStep.Mode.FORCED, RmStep.Mode.RECURSIVE)); builder.add(CopyStep.forDirectory(getProjectFilesystem(), context.getSourcePathResolver().getAbsolutePath(frameworkPath), out, CopyStep.DirectoryMode.CONTENTS_ONLY)); buildableContext.recordArtifact(out); return builder.build(); } @Override public Path getPathToOutput() { return out; } @Override public String getOutputName() { return this.frameworkName; } @Override public Iterable<? extends CxxPreprocessorDep> getCxxPreprocessorDeps(CxxPlatform cxxPlatform) { if (!isPlatformSupported(cxxPlatform)) { return ImmutableList.of(); } return FluentIterable.from(getDeps()).filter(CxxPreprocessorDep.class); } @Override public CxxPreprocessorInput getCxxPreprocessorInput(final CxxPlatform cxxPlatform, HeaderVisibility headerVisibility) throws NoSuchBuildTargetException { CxxPreprocessorInput.Builder builder = CxxPreprocessorInput.builder(); switch (headerVisibility) { case PUBLIC: if (isPlatformSupported(cxxPlatform)) { builder.addAllFrameworks(frameworks); ruleResolver.requireRule(this.getBuildTarget()); builder.addFrameworks(FrameworkPath.ofSourcePath(new BuildTargetSourcePath(this.getBuildTarget()))); } return builder.build(); case PRIVATE: return builder.build(); } throw new RuntimeException("Invalid header visibility: " + headerVisibility); } @Override public Optional<HeaderSymlinkTree> getExportedHeaderSymlinkTree(CxxPlatform cxxPlatform) { return Optional.empty(); } @Override public ImmutableMap<BuildTarget, CxxPreprocessorInput> getTransitiveCxxPreprocessorInput( CxxPlatform cxxPlatform, HeaderVisibility headerVisibility) throws NoSuchBuildTargetException { 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<? extends NativeLinkable> getNativeLinkableExportedDeps() { return ImmutableList.of(); } private NativeLinkableInput getNativeLinkableInputUncached(CxxPlatform cxxPlatform, Linker.LinkableDepType type) { if (!isPlatformSupported(cxxPlatform)) { return NativeLinkableInput.of(); } ImmutableList.Builder<Arg> linkerArgsBuilder = ImmutableList.builder(); linkerArgsBuilder .addAll(StringArg.from(Preconditions.checkNotNull(exportedLinkerFlags.apply(cxxPlatform)))); ImmutableSet.Builder<FrameworkPath> frameworkPaths = ImmutableSet.builder(); frameworkPaths.addAll(Preconditions.checkNotNull(frameworks)); frameworkPaths.add(FrameworkPath.ofSourcePath(new BuildTargetSourcePath(this.getBuildTarget()))); if (type == Linker.LinkableDepType.SHARED) { linkerArgsBuilder.addAll( StringArg.from("-rpath", "@loader_path/Frameworks", "-rpath", "@executable_path/Frameworks")); } final ImmutableList<Arg> linkerArgs = linkerArgsBuilder.build(); return NativeLinkableInput.of(linkerArgs, frameworkPaths.build(), Collections.emptySet()); } @Override public NativeLinkableInput getNativeLinkableInput(CxxPlatform cxxPlatform, Linker.LinkableDepType type) throws NoSuchBuildTargetException { Pair<Flavor, Linker.LinkableDepType> key = new Pair<>(cxxPlatform.getFlavor(), type); NativeLinkableInput input = nativeLinkableCache.get(key); if (input == null) { input = getNativeLinkableInputUncached(cxxPlatform, type); nativeLinkableCache.put(key, input); } return input; } @Override public NativeLinkable.Linkage getPreferredLinkage(CxxPlatform cxxPlatform) { return this.preferredLinkage; } @Override public ImmutableMap<String, SourcePath> getSharedLibraries(CxxPlatform cxxPlatform) throws NoSuchBuildTargetException { return ImmutableMap.of(); } }