com.facebook.buck.lua.AbstractNativeExecutableStarter.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.lua.AbstractNativeExecutableStarter.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.lua;

import com.facebook.buck.cxx.AbstractCxxLibrary;
import com.facebook.buck.cxx.CxxBuckConfig;
import com.facebook.buck.cxx.CxxLinkableEnhancer;
import com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.cxx.CxxPreprocessAndCompile;
import com.facebook.buck.cxx.CxxPreprocessables;
import com.facebook.buck.cxx.CxxPreprocessorDep;
import com.facebook.buck.cxx.CxxPreprocessorInput;
import com.facebook.buck.cxx.CxxSource;
import com.facebook.buck.cxx.CxxSourceRuleFactory;
import com.facebook.buck.cxx.HeaderVisibility;
import com.facebook.buck.cxx.Linker;
import com.facebook.buck.cxx.Linkers;
import com.facebook.buck.cxx.NativeLinkTarget;
import com.facebook.buck.cxx.NativeLinkTargetMode;
import com.facebook.buck.cxx.NativeLinkable;
import com.facebook.buck.cxx.NativeLinkableInput;
import com.facebook.buck.file.WriteFile;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.ImmutableFlavor;
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.BuildTargetSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.WriteStringTemplateRule;
import com.facebook.buck.rules.args.SourcePathArg;
import com.facebook.buck.rules.args.StringArg;
import com.facebook.buck.util.Escaper;
import com.facebook.buck.util.immutables.BuckStyleTuple;
import com.google.common.base.Charsets;
import com.google.common.base.Predicates;
import com.google.common.base.Suppliers;
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 com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.io.Resources;

import org.immutables.value.Value;

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

/**
 * {@link Starter} implementation which builds a starter as a native executable.
 */
@Value.Immutable
@BuckStyleTuple
abstract class AbstractNativeExecutableStarter implements Starter, NativeLinkTarget {

    private static final String NATIVE_STARTER_CXX_SOURCE = "com/facebook/buck/lua/native-starter.cpp.in";

    abstract BuildRuleParams getBaseParams();

    abstract BuildRuleResolver getRuleResolver();

    abstract SourcePathResolver getPathResolver();

    abstract SourcePathRuleFinder getRuleFinder();

    abstract LuaConfig getLuaConfig();

    abstract CxxBuckConfig getCxxBuckConfig();

    abstract CxxPlatform getCxxPlatform();

    abstract BuildTarget getTarget();

    abstract Path getOutput();

    abstract String getMainModule();

    abstract Optional<BuildTarget> getNativeStarterLibrary();

    abstract Optional<Path> getRelativeModulesDir();

    abstract Optional<Path> getRelativePythonModulesDir();

    abstract Optional<Path> getRelativeNativeLibsDir();

    private String getNativeStarterCxxSourceTemplate() {
        try {
            return Resources.toString(Resources.getResource(NATIVE_STARTER_CXX_SOURCE), Charsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private CxxSource getNativeStarterCxxSource() {
        BuildTarget target = BuildTarget.builder(getBaseParams().getBuildTarget())
                .addFlavors(ImmutableFlavor.of("native-starter-cxx-source")).build();
        if (!getRuleResolver().getRuleOptional(target).isPresent()) {

            BuildTarget templateTarget = BuildTarget.builder(getBaseParams().getBuildTarget())
                    .addFlavors(ImmutableFlavor.of("native-starter-cxx-source-template")).build();
            getRuleResolver().addToIndex(new WriteFile(
                    getBaseParams().copyWithChanges(templateTarget, Suppliers.ofInstance(ImmutableSortedSet.of()),
                            Suppliers.ofInstance(ImmutableSortedSet.of())),
                    getNativeStarterCxxSourceTemplate(),
                    BuildTargets.getGenPath(getBaseParams().getProjectFilesystem(), templateTarget,
                            "%s/native-starter.cpp.in"),
                    /* executable */ false));

            Path output = BuildTargets.getGenPath(getBaseParams().getProjectFilesystem(), target,
                    "%s/native-starter.cpp");
            getRuleResolver().addToIndex(WriteStringTemplateRule.from(getBaseParams(), getRuleFinder(), target,
                    output, new BuildTargetSourcePath(templateTarget),
                    ImmutableMap.of("MAIN_MODULE", Escaper.escapeAsPythonString(getMainModule()), "MODULES_DIR",
                            getRelativeModulesDir().isPresent()
                                    ? Escaper.escapeAsPythonString(getRelativeModulesDir().get().toString())
                                    : "NULL",
                            "PY_MODULES_DIR",
                            getRelativePythonModulesDir().isPresent()
                                    ? Escaper.escapeAsPythonString(getRelativePythonModulesDir().get().toString())
                                    : "NULL",
                            "EXT_SUFFIX",
                            Escaper.escapeAsPythonString(getCxxPlatform().getSharedLibraryExtension())),
                    /* executable */ false));
        }

        return CxxSource.of(CxxSource.Type.CXX, new BuildTargetSourcePath(target), ImmutableList.of());
    }

    private ImmutableList<CxxPreprocessorInput> getTransitiveCxxPreprocessorInput(CxxPlatform cxxPlatform,
            Iterable<? extends CxxPreprocessorDep> deps) throws NoSuchBuildTargetException {
        ImmutableList.Builder<CxxPreprocessorInput> inputs = ImmutableList.builder();
        inputs.addAll(CxxPreprocessables.getTransitiveCxxPreprocessorInput(cxxPlatform,
                FluentIterable.from(deps).filter(BuildRule.class)));
        for (CxxPreprocessorDep dep : Iterables.filter(deps, Predicates.not(BuildRule.class::isInstance))) {
            inputs.add(dep.getCxxPreprocessorInput(cxxPlatform, HeaderVisibility.PUBLIC));
        }
        return inputs.build();
    }

    public Iterable<? extends AbstractCxxLibrary> getNativeStarterDeps() {
        return ImmutableList.of(getNativeStarterLibrary().isPresent()
                ? getRuleResolver().getRuleWithType(getNativeStarterLibrary().get(), AbstractCxxLibrary.class)
                : getLuaConfig().getLuaCxxLibrary(getRuleResolver()));
    }

    private NativeLinkableInput getNativeLinkableInput() throws NoSuchBuildTargetException {
        Iterable<? extends AbstractCxxLibrary> nativeStarterDeps = getNativeStarterDeps();
        ImmutableMap<CxxPreprocessAndCompile, SourcePath> objects = CxxSourceRuleFactory
                .requirePreprocessAndCompileRules(getBaseParams(), getRuleResolver(), getPathResolver(),
                        getRuleFinder(), getCxxBuckConfig(), getCxxPlatform(),
                        ImmutableList.<CxxPreprocessorInput>builder()
                                .add(CxxPreprocessorInput.builder()
                                        .putAllPreprocessorFlags(CxxSource.Type.CXX,
                                                getNativeStarterLibrary().isPresent() ? ImmutableList.of()
                                                        : ImmutableList.of("-DBUILTIN_NATIVE_STARTER"))
                                        .build())
                                .addAll(getTransitiveCxxPreprocessorInput(getCxxPlatform(), nativeStarterDeps))
                                .build(),
                        ImmutableMultimap.of(), Optional.empty(), Optional.empty(),
                        ImmutableMap.of("native-starter.cpp", getNativeStarterCxxSource()),
                        CxxSourceRuleFactory.PicType.PDC, Optional.empty());
        return NativeLinkableInput.builder()
                .addAllArgs(getRelativeNativeLibsDir().isPresent() ? StringArg.from(Linkers.iXlinker("-rpath",
                        String.format("%s/%s", getCxxPlatform().getLd().resolve(getRuleResolver()).origin(),
                                getRelativeNativeLibsDir().get().toString())))
                        : ImmutableList.of())
                .addAllArgs(SourcePathArg.from(getPathResolver(), objects.values())).build();
    }

    @Override
    public SourcePath build() throws NoSuchBuildTargetException {
        BuildTarget linkTarget = getTarget();
        getRuleResolver().addToIndex(CxxLinkableEnhancer.createCxxLinkableBuildRule(getCxxBuckConfig(),
                getCxxPlatform(), getBaseParams(), getRuleResolver(), getPathResolver(), getRuleFinder(),
                linkTarget, Linker.LinkType.EXECUTABLE, Optional.empty(), getOutput(),
                Linker.LinkableDepType.SHARED, getNativeStarterDeps(), Optional.empty(), Optional.empty(),
                ImmutableSet.of(), getNativeLinkableInput()));
        return new BuildTargetSourcePath(linkTarget);
    }

    @Override
    public BuildTarget getBuildTarget() {
        return getBaseParams().getBuildTarget();
    }

    @Override
    public NativeLinkTargetMode getNativeLinkTargetMode(CxxPlatform cxxPlatform) {
        return NativeLinkTargetMode.executable();
    }

    @Override
    public Iterable<? extends NativeLinkable> getNativeLinkTargetDeps(CxxPlatform cxxPlatform) {
        return getNativeStarterDeps();
    }

    @Override
    public NativeLinkableInput getNativeLinkTargetInput(CxxPlatform cxxPlatform) throws NoSuchBuildTargetException {
        return getNativeLinkableInput();
    }

    @Override
    public Optional<Path> getNativeLinkTargetOutputPath(CxxPlatform cxxPlatform) {
        return Optional.of(getOutput());
    }

}