com.jayway.maven.plugins.android.AndroidNdk.java Source code

Java tutorial

Introduction

Here is the source code for com.jayway.maven.plugins.android.AndroidNdk.java

Source

/*
 * 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.jayway.maven.plugins.android;

import com.jayway.maven.plugins.android.configuration.NDKArchitectureToolchainMappings;
import com.jayway.maven.plugins.android.phase05compile.NdkBuildMojo;
import org.apache.commons.lang.SystemUtils;
import org.apache.maven.plugin.MojoExecutionException;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Represents an Android NDK.
 *
 * @author Johan Lindquist <johanlindquist@gmail.com>
 * @author Manfred Moser <manfred@simpligility.com>
 */
public class AndroidNdk {

    public static final String PROPER_NDK_HOME_DIRECTORY_MESSAGE = "Please provide a proper Android NDK directory path"
            + " as configuration parameter <ndk><path>...</path></ndk> in the plugin <configuration/>. As an "
            + "alternative, you may add the parameter to commandline: -Dandroid.ndk.path=... or set environment "
            + "variable " + NdkBuildMojo.ENV_ANDROID_NDK_HOME + ".";

    public static final String[] NDK_ARCHITECTURES = { "armeabi", "armeabi-v7a", "mips", "x86" };

    /**
     * Arm toolchain implementations.
     */
    public static final String[] ARM_TOOLCHAIN = { "arm-linux-androideabi-4.9", "arm-linux-androideabi-4.8",
            "arm-linux-androideabi-4.7", "arm-linux-androideabi-4.6", "arm-linux-androideabi-4.4.3" };

    /**
     * x86 toolchain implementations.
     */
    public static final String[] X86_TOOLCHAIN = { "x86-4.9", "x86-4.8", "x86-4.7", "x86-4.6", "x86-4.4.3" };

    /**
     * Mips toolchain implementations.
     */
    public static final String[] MIPS_TOOLCHAIN = { "mipsel-linux-android-4.9", "mipsel-linux-android-4.8",
            "mipsel-linux-android-4.7", "mipsel-linux-android-4.6", "mipsel-linux-android-4.4.3" };

    /**
     * Possible locations for the gdbserver file.
     */
    private static final String[] GDB_SERVER_LOCATIONS = { "toolchains/%s/prebuilt/gdbserver",
            "prebuilt/%s/gdbserver/gdbserver" };

    private final File ndkPath;

    public AndroidNdk(File ndkPath) {
        assertPathIsDirectory(ndkPath);
        this.ndkPath = ndkPath;
    }

    private void assertPathIsDirectory(final File path) {
        if (path == null) {
            throw new InvalidNdkException(PROPER_NDK_HOME_DIRECTORY_MESSAGE);
        }
        if (!path.isDirectory()) {
            throw new InvalidNdkException(
                    "Path \"" + path + "\" is not a directory. " + PROPER_NDK_HOME_DIRECTORY_MESSAGE);
        }
    }

    private File findStripper(String toolchain) {
        List<String> osDirectories = new ArrayList<String>();
        String extension = "";

        if (SystemUtils.IS_OS_LINUX) {
            osDirectories.add("linux-x86");
            osDirectories.add("linux-x86_64");
        } else if (SystemUtils.IS_OS_WINDOWS) {
            osDirectories.add("windows");
            osDirectories.add("windows-x86_64");
            extension = ".exe";
        } else if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_MAC_OSX) {
            osDirectories.add("darwin-x86");
            osDirectories.add("darwin-x86_64");
        }

        String fileName = "";
        if (toolchain.startsWith("arm")) {
            fileName = "arm-linux-androideabi-strip" + extension;
        } else if (toolchain.startsWith("x86")) {
            fileName = "i686-linux-android-strip" + extension;
        } else if (toolchain.startsWith("mips")) {
            fileName = "mipsel-linux-android-strip" + extension;
        }

        for (String osDirectory : osDirectories) {
            String stripperLocation = String.format("toolchains/%s/prebuilt/%s/bin/%s", toolchain, osDirectory,
                    fileName);
            final File stripper = new File(ndkPath, stripperLocation);
            if (stripper.exists()) {
                return stripper;
            }
        }
        return null;
    }

    public File getStripper(String toolchain) throws MojoExecutionException {
        final File stripper = findStripper(toolchain);
        if (stripper == null) {
            throw new MojoExecutionException("Could not resolve stripper for current OS: " + SystemUtils.OS_NAME);
        }

        // Some basic validation
        if (!stripper.exists()) {
            throw new MojoExecutionException("Strip binary " + stripper.getAbsolutePath()
                    + " does not exist, please double check the toolchain and OS used");
        }

        // We should be good to go
        return stripper;
    }

    private String resolveNdkToolchain(String[] toolchains) {
        for (String toolchain : toolchains) {
            File f = findStripper(toolchain);
            if (f != null && f.exists()) {
                return toolchain;
            }
        }
        return null;
    }

    /**
     * Tries to resolve the toolchain based on the path of the file.
     *
     * @param file Native library
     * @return String
     * @throws MojoExecutionException When no toolchain is found
     */
    public String getToolchain(File file) throws MojoExecutionException {
        String resolvedNdkToolchain = null;

        // try to resolve the toolchain now
        String ndkArchitecture = file.getParentFile().getName();
        if (ndkArchitecture.startsWith("arm")) {
            resolvedNdkToolchain = resolveNdkToolchain(ARM_TOOLCHAIN);
        } else if (ndkArchitecture.startsWith("x86")) {
            resolvedNdkToolchain = resolveNdkToolchain(X86_TOOLCHAIN);
        } else if (ndkArchitecture.startsWith("mips")) {
            resolvedNdkToolchain = resolveNdkToolchain(MIPS_TOOLCHAIN);
        }

        // if no toolchain can be found
        if (resolvedNdkToolchain == null) {
            throw new MojoExecutionException(
                    "Can not resolve automatically a toolchain to use. Please specify one.");
        }
        return resolvedNdkToolchain;
    }

    /**
     * Returns the complete path for the ndk-build tool, based on this NDK.
     *
     * @return the complete path as a <code>String</code>, including the tool's filename.
     */
    public String getNdkBuildPath() {
        if (SystemUtils.IS_OS_WINDOWS) {
            return new File(ndkPath, "/ndk-build.cmd").getAbsolutePath();
        } else {
            return new File(ndkPath, "/ndk-build").getAbsolutePath();
        }
    }

    public File getGdbServer(String ndkArchitecture) throws MojoExecutionException {
        // create a list of possible gdb server parent folder locations
        List<String> gdbServerLocations = new ArrayList<String>();
        if (ndkArchitecture.startsWith("arm")) {
            gdbServerLocations.add("android-arm");
            gdbServerLocations.addAll(Arrays.asList(ARM_TOOLCHAIN));
        } else if (ndkArchitecture.startsWith("x86")) {
            gdbServerLocations.add("android-x86");
            gdbServerLocations.addAll(Arrays.asList(X86_TOOLCHAIN));
        } else if (ndkArchitecture.startsWith("mips")) {
            gdbServerLocations.add("android-mips");
            gdbServerLocations.addAll(Arrays.asList(MIPS_TOOLCHAIN));
        }

        // check for the gdb server
        for (String location : GDB_SERVER_LOCATIONS) {
            for (String gdbServerLocation : gdbServerLocations) {
                File gdbServerFile = new File(ndkPath, String.format(location, gdbServerLocation));
                if (gdbServerFile.exists()) {
                    return gdbServerFile;
                }
            }
        }

        //  if we got here, throw an error
        throw new MojoExecutionException("gdbserver binary for architecture " + ndkArchitecture
                + " does not exist, please double check the toolchain and OS used");
    }

    /** Retrieves, based on the architecture and possibly toolchain mappings, the toolchain for the architecture.
     * <br/>
     * <strong>Note:</strong> This method will return the <strong>default</strong> toolchain as defined by the NDK if
     * not specified in the <code>NDKArchitectureToolchainMappings</code>.
     *
     * @param ndkArchitecture Architecture to resolve toolchain for
     * @param ndkArchitectureToolchainMappings User mappings of architecture to toolchain
     *
     * @return Toolchain to be used for the architecture
     *
     * @throws MojoExecutionException If a toolchain can not be resolved
     */
    public String getToolchainFromArchitecture(final String ndkArchitecture,
            final NDKArchitectureToolchainMappings ndkArchitectureToolchainMappings) throws MojoExecutionException {
        if (ndkArchitecture.startsWith("arm")) {
            if (ndkArchitectureToolchainMappings != null) {
                return ndkArchitectureToolchainMappings.getArmeabi();
            }
            return AndroidNdk.ARM_TOOLCHAIN[0];
        } else if (ndkArchitecture.startsWith("x86")) {
            if (ndkArchitectureToolchainMappings != null) {
                return ndkArchitectureToolchainMappings.getX86();
            }
            return AndroidNdk.X86_TOOLCHAIN[0];
        } else if (ndkArchitecture.startsWith("mips")) {
            if (ndkArchitectureToolchainMappings != null) {
                return ndkArchitectureToolchainMappings.getMips();
            }
            return AndroidNdk.MIPS_TOOLCHAIN[0];
        }

        //  if we got here, throw an error
        throw new MojoExecutionException(
                "Toolchain for architecture " + ndkArchitecture + " does not exist, please double check the setup");
    }
}