All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.build.gradle.model.ComponentNativeLibraryFactory Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.android.build.gradle.model;

import static com.android.build.gradle.model.AndroidComponentModelPlugin.COMPONENT_NAME;

import com.android.annotations.NonNull;
import com.android.build.gradle.internal.NdkHandler;
import com.android.build.gradle.internal.core.Abi;
import com.android.build.gradle.internal.dependency.NativeDependencyResolveResult;
import com.android.build.gradle.internal.dependency.NativeLibraryArtifact;
import com.android.build.gradle.internal.model.NativeLibraryFactory;
import com.android.build.gradle.internal.model.NativeLibraryImpl;
import com.android.build.gradle.internal.ndk.NativeCompilerArgsUtil;
import com.android.build.gradle.internal.scope.VariantScope;
import com.android.build.gradle.internal.variant.BaseVariantData;
import com.android.build.gradle.internal.variant.BaseVariantOutputData;
import com.android.build.gradle.managed.NdkAbiOptions;
import com.android.build.gradle.managed.NdkConfig;
import com.android.build.gradle.managed.NdkOptions;
import com.android.build.gradle.model.internal.AndroidBinaryInternal;
import com.android.builder.model.NativeLibrary;
import com.android.utils.StringHelper;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

import org.gradle.model.ModelMap;
import org.gradle.nativeplatform.NativeLibraryBinary;
import org.gradle.nativeplatform.NativeLibraryBinarySpec;
import org.gradle.nativeplatform.SharedLibraryBinary;
import org.gradle.nativeplatform.StaticLibraryBinary;
import org.gradle.platform.base.BinaryContainer;

import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * Implementation of NativeLibraryFactory from in the component model plugin.
 *
 * The library extract information directly from the binaries.
 */
public class ComponentNativeLibraryFactory implements NativeLibraryFactory {
    @NonNull
    ModelMap binaries;
    @NonNull
    NdkHandler ndkHandler;
    @NonNull
    ModelMap abiOptions;
    @NonNull
    Multimap nativeDependencies;
    @NonNull
    Multimap jniLibsDependencies;

    public ComponentNativeLibraryFactory(
            @NonNull ModelMap binaries,
            @NonNull NdkHandler ndkHandler,
            @NonNull ModelMap abiOptions,
            @NonNull Multimap nativeDependencies,
            @NonNull Multimap jniLibsDependencies) {
        this.binaries = binaries;
        this.ndkHandler = ndkHandler;
        this.abiOptions = abiOptions;
        this.nativeDependencies = nativeDependencies;
        this.jniLibsDependencies = jniLibsDependencies;
    }

    @NonNull
    @Override
    public Optional create(
            @NonNull VariantScope scope,
            @NonNull String toolchainName,
            @NonNull final Abi abi) {
        BaseVariantData variantData = scope.getVariantData();

        AndroidBinaryInternal androidBinary =
                binaries.get(COMPONENT_NAME + StringHelper.capitalize(variantData.getName()));

        if (androidBinary == null) {
            // Binaries are not created for test variants.
            return Optional.absent();
        }

        @SuppressWarnings("ConstantConditions")
        Optional nativeBinary =
                Iterables.tryFind(androidBinary.getNativeBinaries(),
                        new Predicate() {
                            @Override
                            public boolean apply(NativeLibraryBinarySpec binary) {
                                return binary.getTargetPlatform().getName().equals(abi.getName());
                            }
                        });

        if (!nativeBinary.isPresent()) {
            // We don't have native binaries, but the project may be dependent on other native
            // projects.  Create a NativeLibrary to supply the debuggable library directories.
            return Optional.of(new NativeLibraryImpl(
                    abi.getName(),
                    toolchainName,
                    abi.getName(),
                    Collections.emptyList(),  /*cIncludeDirs*/
                    Collections.emptyList(),  /*cppIncludeDirs*/
                    Collections.emptyList(),  /*cSystemIncludeDirs*/
                    Collections.emptyList(),  /*cppSystemIncludeDirs*/
                    Collections.emptyList(),  /*cDefines*/
                    Collections.emptyList(),  /*cppDefines*/
                    Collections.emptyList(),  /*cFlags*/
                    Collections.emptyList(),  /*cppFlags*/
                    findDebuggableLibraryDirectories(variantData, androidBinary, abi)));
        }

        NdkOptions targetOptions = abiOptions.get(abi.getName());
        Iterable cFlags = nativeBinary.get().getcCompiler().getArgs();
        Iterable cppFlags = nativeBinary.get().getCppCompiler().getArgs();
        if (targetOptions != null) {
            if (!targetOptions.getCFlags().isEmpty()) {
                cFlags = Iterables.concat(cFlags, targetOptions.getCFlags());
            }
            if (!targetOptions.getCppFlags().isEmpty()) {
                cppFlags = Iterables.concat(cppFlags, targetOptions.getCppFlags());
            }
        }

        List debuggableLibDir = findDebuggableLibraryDirectories(variantData, androidBinary, abi);

        NdkConfig ndkConfig = androidBinary.getMergedNdkConfig();
        // The DSL currently do not support all options available in the model such as the
        // include dirs and the defines.  Therefore, just pass an empty collection for now.
        return Optional.of(new NativeLibraryImpl(
                ndkConfig.getModuleName(),
                toolchainName,
                abi.getName(),
                Collections.emptyList(),  /*cIncludeDirs*/
                Collections.emptyList(),  /*cppIncludeDirs*/
                Collections.emptyList(),  /*cSystemIncludeDirs*/
                ndkHandler.getStlIncludes(ndkConfig.getStl(), ndkConfig.getStlVersion(), abi),
                Collections.emptyList(),  /*cDefines*/
                Collections.emptyList(),  /*cppDefines*/
                NativeCompilerArgsUtil.transform(cFlags),
                NativeCompilerArgsUtil.transform(cppFlags),
                debuggableLibDir));
    }

    /**
     * Find all directories containing library with debug symbol.
     * Include libraries from dependencies.
     */
    private List findDebuggableLibraryDirectories(
            @NonNull BaseVariantData variantData,
            @NonNull AndroidBinaryInternal binary,
            @NonNull Abi abi) {
        // Create LinkedHashSet to remove duplicated while maintaining order.
        Set debuggableLibDir = Sets.newLinkedHashSet();

        debuggableLibDir.add(variantData.getScope().getNdkDebuggableLibraryFolders(abi));
        addNativeDebuggableLib(debuggableLibDir, binary, abi, nativeDependencies);
        addJniLibsDebuggableLib(debuggableLibDir, binary, abi, jniLibsDependencies);

        return ImmutableList.copyOf(debuggableLibDir);
    }

    private static void addNativeDebuggableLib(
            @NonNull Collection debuggableLibDir,
            @NonNull AndroidBinaryInternal binary,
            @NonNull final Abi abi,
            @NonNull Multimap dependencyMap) {
        NativeLibraryBinarySpec nativeBinary =
                Iterables.find(
                        binary.getNativeBinaries(),
                        new Predicate() {
                            @Override
                            public boolean apply(NativeLibraryBinarySpec nativeBinary) {
                                return nativeBinary.getTargetPlatform().getName().equals(abi.getName());
                            }
                        },
                        null);
        if (nativeBinary != null) {
            addDebuggableLib(
                    debuggableLibDir,
                    binary,
                    abi,
                    dependencyMap.get(nativeBinary.getName()));
        }
    }


    private static void addJniLibsDebuggableLib(
            @NonNull Collection debuggableLibDir,
            @NonNull AndroidBinary binary,
            @NonNull Abi abi,
            @NonNull Multimap dependencyMap) {
        addDebuggableLib(debuggableLibDir, binary, abi, dependencyMap.get(binary.getName()));
    }


    private static void addDebuggableLib(
            @NonNull Collection debuggableLibDir,
            @NonNull AndroidBinary binary,
            @NonNull Abi abi,
            @NonNull Iterable dependencies) {
        for (NativeDependencyResolveResult dependency : dependencies) {
            for (NativeLibraryArtifact artifact : dependency.getNativeArtifacts()) {
                for (File lib : artifact.getLibraries()) {
                    debuggableLibDir.add(lib.getParentFile());
                }
            }
            for (final NativeLibraryBinary nativeBinary : dependency.getPrebuiltLibraries()) {
                if (nativeBinary.getTargetPlatform().getName().equals(abi.getName())) {
                    File output = nativeBinary instanceof SharedLibraryBinary
                            ? ((SharedLibraryBinary) nativeBinary).getSharedLibraryFile()
                            : ((StaticLibraryBinary) nativeBinary).getStaticLibraryFile();
                    if (output != null) {
                        debuggableLibDir.add(output.getParentFile());
                    }
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy