com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl.java

Source

// Copyright 2015 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.bazel.rules.android.ndkcrosstools;

import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * An NdkStlImpl adds a specific Android NDK C++ STL implementation to a given CToolchain proto
 * builder.
 */
public abstract class StlImpl {

    private enum RuntimeType {
        DYNAMIC("so"), STATIC("a");

        private final String name, fileExtension;

        private RuntimeType(String fileExtension) {
            this.name = name().toLowerCase();
            this.fileExtension = fileExtension;
        }
    }

    private final Map<String, String> fileGroupNameToFileGlobs = new LinkedHashMap<>();

    protected final String name;
    protected final NdkPaths ndkPaths;

    /**
     * @param name the name for this STL, which should be safe to use as a label
     * @param ndkPaths the NdkPaths
     */
    protected StlImpl(String name, NdkPaths ndkPaths) {
        this.name = name;
        this.ndkPaths = ndkPaths;
    }

    public void addStlImpl(List<CToolchain.Builder> baseToolchains, String gccVersion) {

        for (CToolchain.Builder baseToolchain : baseToolchains) {
            addStlImpl(baseToolchain, gccVersion);
        }
    }

    /**
     * Adds an Android NDK C++ STL implementation to the given CToolchain builder.
     *
     * @param toolchain the toolchain to add the STL implementation to
     * @param gccVersion the gcc version for the STL impl. Applicable only to gnu-libstdc++
     */
    public abstract void addStlImpl(CToolchain.Builder toolchain, String gccVersion);

    protected void addBaseStlImpl(CToolchain.Builder toolchain, String gccVersion) {

        toolchain.setToolchainIdentifier(toolchain.getToolchainIdentifier() + "-" + name)
                .setSupportsEmbeddedRuntimes(true)
                .setDynamicRuntimesFilegroup(createRuntimeLibrariesFilegroup(name, gccVersion,
                        toolchain.getTargetCpu(), RuntimeType.DYNAMIC))
                .setStaticRuntimesFilegroup(createRuntimeLibrariesFilegroup(name, gccVersion,
                        toolchain.getTargetCpu(), RuntimeType.STATIC));
    }

    private String createRuntimeLibrariesFilegroup(String stl, String gccVersion, String targetCpu,
            RuntimeType type) {

        // gnu-libstlc++ has separate libraries for 4.8 and 4.9
        String fullStlName = stl;
        if (gccVersion != null) {
            fullStlName += "-" + gccVersion;
        }

        String filegroupNameTemplate = "%stl%-%targetCpu%-%type%-runtime-libraries";
        String filegroupName = filegroupNameTemplate.replace("%stl%", fullStlName).replace("%targetCpu%", targetCpu)
                .replace("%type%", type.name);

        // At the same time that the filegroup name is created, record a corresponding file glob
        // pattern that AndroidNdkRepositoryFunction can look up later for creating the build file
        // rules.

        // These translations are unfortunate, but toolchain identifiers aren't allowed to have '+' in
        // their name.
        if (stl.equals("gnu-libstdcpp")) {
            stl = "gnu-libstdc++";
        }
        if (stl.equals("libcpp")) {
            stl = "llvm-libc++";
        }

        String glob = NdkPaths.createStlRuntimeLibsGlob(stl, gccVersion, targetCpu, type.fileExtension);
        String previousValue = fileGroupNameToFileGlobs.put(filegroupName, glob);

        // Some STL filegroups will end up being duplicates, but a filegroup should never be registered
        // with a different glob, otherwise one toolchain would get the wrong glob.
        Verify.verify(previousValue == null || previousValue.equals(glob),
                "STL filegroup glob being replaced with a different glob:\nname: %s\n%s\n%s", filegroupName, glob,
                previousValue);

        return filegroupName;
    }

    protected static Iterable<String> createIncludeFlags(Iterable<String> includePaths) {
        ImmutableList.Builder<String> includeFlags = ImmutableList.builder();
        for (String includePath : includePaths) {
            includeFlags.add("-isystem");
            includeFlags.add(includePath);
        }
        return includeFlags.build();
    }

    /**
     * @return a map of the names of the generated STL runtime library filegroup names to their file
     * glob patterns
     */
    public Map<String, String> getFilegroupNamesAndFilegroupFileGlobPatterns() {
        return ImmutableMap.copyOf(fileGroupNameToFileGlobs);
    }

    /**
     * @return the name of this STL impl, which is safe to use as a label
     */
    public String getName() {
        return name;
    }
}