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

com.simpligility.maven.plugins.android.AndroidNdk Maven / Gradle / Ivy

The newest version!
/*
 * 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.simpligility.maven.plugins.android;

import org.apache.commons.lang3.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 - [email protected]
 * @author Manfred Moser - [email protected]
 */
public class AndroidNdk
{

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

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

    /**
     * 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" };

    /**
     * Arm64 toolchain implementations.
     */
    public static final String[] ARM64_TOOLCHAIN = {  "aarch64-linux-android-4.9" };

    /**
     * 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" };

    /**
     * x86 toolchain implementations.
     */
    public static final String[] X86_64_TOOLCHAIN = { "x86_64-4.9" };

    /**
     * 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" };

    /**
     * Mips toolchain implementations.
     */
    public static final String[] MIPS64_TOOLCHAIN = { "mips64el-linux-android-4.9" };

    /**
     * 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 osDirectories = new ArrayList();
        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( "aarch64" ) )
        {
            fileName = "aarch64-linux-android-strip" + extension;
        }
        else if ( toolchain.startsWith( "x86_64" ) )
        {
            fileName = "x86_64-linux-android-strip" + extension;
        }
        else if ( toolchain.startsWith( "x86" ) )
        {
            fileName = "i686-linux-android-strip" + extension;
        }
        else if ( toolchain.startsWith( "mips64" ) )
        {
            fileName = "mips64el-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( "armeabi" ) )
        {
            resolvedNdkToolchain = resolveNdkToolchain( ARM_TOOLCHAIN );
        }
        else if ( ndkArchitecture.startsWith( "arm64" ) )
        {
            resolvedNdkToolchain = resolveNdkToolchain( ARM64_TOOLCHAIN );
        }
        else if ( ndkArchitecture.startsWith( "x86_64" ) )
        {
            resolvedNdkToolchain = resolveNdkToolchain( X86_64_TOOLCHAIN );
        }
        else if ( ndkArchitecture.startsWith( "x86" ) )
        {
            resolvedNdkToolchain = resolveNdkToolchain( X86_TOOLCHAIN );
        }
        else if ( ndkArchitecture.startsWith( "mips64" ) )
        {
            resolvedNdkToolchain = resolveNdkToolchain( MIPS64_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 String, 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 gdbServerLocations = new ArrayList();
        if ( ndkArchitecture.startsWith( "armeabi" ) )
        {
            gdbServerLocations.add( "android-arm" );
            gdbServerLocations.add( "android-armeabi" );
            gdbServerLocations.addAll( Arrays.asList( ARM_TOOLCHAIN ) );
        }
        else if ( ndkArchitecture.startsWith( "arm64" ) )
        {
            gdbServerLocations.add( "android-arm64" );
            gdbServerLocations.addAll( Arrays.asList( ARM64_TOOLCHAIN ) );
        }
        else if ( ndkArchitecture.startsWith( "x86_64" ) )
        {
            gdbServerLocations.add( "android-x86_64" );
            gdbServerLocations.addAll( Arrays.asList( X86_64_TOOLCHAIN ) );
        }
        else if ( ndkArchitecture.startsWith( "x86" ) )
        {
            gdbServerLocations.add( "android-x86" );
            gdbServerLocations.addAll( Arrays.asList( X86_TOOLCHAIN ) );
        }
        else if ( ndkArchitecture.startsWith( "mips64" ) )
        {
            gdbServerLocations.add( "android-mips64" );
            gdbServerLocations.addAll( Arrays.asList( MIPS64_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" );
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy