com.facebook.buck.cxx.CxxHeaders.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.cxx.CxxHeaders.java

Source

/*
 * 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.RuleKeyAppendable;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;

import java.nio.file.Path;
import java.util.Optional;

/**
 * Encapsulates headers from a single root location.
 */
public abstract class CxxHeaders implements RuleKeyAppendable {

    public abstract CxxPreprocessables.IncludeType getIncludeType();

    /**
     * @return the root of the includes.
     */
    public abstract SourcePath getRoot();

    /**
     * @return the path to the optional header map to use for this header pack.
     */
    public abstract Optional<SourcePath> getHeaderMap();

    /**
     * @return the path to add to the preprocessor search path to find the includes.  This defaults
     *     to the root, but can be overridden to use an alternate path.
     */
    public abstract SourcePath getIncludeRoot();

    /**
     * Add this header pack to the given {@link com.facebook.buck.cxx.HeaderPathNormalizer.Builder}.
     */
    public abstract void addToHeaderPathNormalizer(HeaderPathNormalizer.Builder builder);

    /**
     * @return all deps required by this header pack.
     */
    public abstract Iterable<BuildRule> getDeps(SourcePathRuleFinder ruleFinder);

    private static Path resolveSourcePathAndShorten(SourcePathResolver resolver, SourcePath path,
            Optional<PathShortener> pathShortener) {
        Path resolvedPath = resolver.getAbsolutePath(path);
        return pathShortener.isPresent() ? pathShortener.get().shorten(resolvedPath) : resolvedPath;
    }

    /**
     * @return the arguments to add to the preprocessor command line to include the given header packs
     *     in preprocessor search path.
     */
    public static Iterable<String> getArgs(Iterable<CxxHeaders> cxxHeaderses, SourcePathResolver resolver,
            Optional<PathShortener> pathMinimizer, Preprocessor preprocessor) {
        ImmutableList.Builder<String> args = ImmutableList.builder();

        // Collect the header maps and roots into buckets organized by include type, so that we can:
        // 1) Apply the header maps first (so that they work properly).
        // 2) De-duplicate redundant include paths.
        Multimap<CxxPreprocessables.IncludeType, String> headerMaps = LinkedHashMultimap.create();
        Multimap<CxxPreprocessables.IncludeType, String> roots = LinkedHashMultimap.create();
        for (CxxHeaders cxxHeaders : cxxHeaderses) {
            Optional<SourcePath> headerMap = cxxHeaders.getHeaderMap();
            if (headerMap.isPresent()) {
                headerMaps.put(cxxHeaders.getIncludeType(),
                        resolveSourcePathAndShorten(resolver, headerMap.get(), pathMinimizer).toString());
            }
            roots.put(cxxHeaders.getIncludeType(),
                    resolveSourcePathAndShorten(resolver, cxxHeaders.getIncludeRoot(), pathMinimizer).toString());
        }

        // Define the include type ordering.  We always add local ("-I") include paths first so that
        // headers match there before system ("-isystem") ones.
        ImmutableSet<CxxPreprocessables.IncludeType> includeTypes = ImmutableSet
                .of(CxxPreprocessables.IncludeType.LOCAL, CxxPreprocessables.IncludeType.SYSTEM);

        // Apply the header maps first, so that headers that matching there avoid falling back to
        // stat'ing files in the normal include roots.
        Preconditions.checkState(includeTypes.containsAll(headerMaps.keySet()));
        for (CxxPreprocessables.IncludeType includeType : includeTypes) {
            args.addAll(includeType.includeArgs(preprocessor, headerMaps.get(includeType)));
        }

        // Apply the regular includes last.
        Preconditions.checkState(includeTypes.containsAll(roots.keySet()));
        for (CxxPreprocessables.IncludeType includeType : includeTypes) {
            args.addAll(includeType.includeArgs(preprocessor, roots.get(includeType)));
        }

        return args.build();
    }

}