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

com.jayway.maven.plugins.android.phase05compile.NdkBuildMojo Maven / Gradle / Ivy

/*
 * 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.phase05compile;

import java.io.*;
import java.util.*;

import com.jayway.maven.plugins.android.*;
import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.*;

import static org.apache.commons.lang.StringUtils.isBlank;

/**
 * @author Johan Lindquist 
 * @goal ndk-build
 * @phase compile
 * @requiresProject true
 */
public class NdkBuildMojo extends AbstractAndroidMojo {
    /**
     * 

The Android NDK to use.

*

Looks like this:

*
     * <ndk>
     *     <path>/opt/android-ndk-r4</path>
     * </ndk>
     * 
*

The <path> parameter is optional. The default is the setting of the ANDROID_NDK_HOME environment * variable. The parameter can be used to override this setting with a different environment variable like this:

*
     * <ndk>
     *     <path>${env.ANDROID_NDK_HOME}</path>
     * </ndk>
     * 
*

or just with a hardcoded absolute path. The parameters can also be configured from command-line with parameter * -Dandroid.ndk.path.

* * @parameter */ private Ndk ndk; /** *

Parameter designed to pick up -Dandroid.ndk.path in case there is no pom with an * <ndk> configuration tag.

*

Corresponds to {@link Ndk#path}.

* * @parameter expression="${android.ndk.path}" * @readonly */ private File ndkPath; /** * Specifies the classifier with which the artifact should be stored in the repository * * @parameter expression="${android.ndk.build.native-classifier}" */ protected String ndkClassifier; /** * Specifies additional command line parameters to pass to ndk-build * * @parameter expression="${android.ndk.build.command-line}" */ protected String ndkBuildAdditionalCommandline; /** * Flag indicating whether the NDK output directory (libs/<architecture>) should be cleared after build. This * will essentially 'move' all the native artifacts (.so) to the ${project.build.directory}/libs/<architecture>. * If an APK is built as part of the invocation, the libraries will be included from here. * * @parameter expression="${android.ndk.build.clear-native-artifacts}" default="false" */ protected boolean clearNativeArtifacts = false; /** * Flag indicating whether the resulting native library should be attached as an artifact to the build. This * means the resulting .so is installed into the repository as well as being included in the final APK. * * @parameter expression="${android.ndk.build.attach-native-artifact}" default="false" */ protected boolean attachNativeArtifacts; /** * The ANDROID_NDK_HOME environment variable name. */ public static final String ENV_ANDROID_NDK_HOME = "ANDROID_NDK_HOME"; /** * Build folder to place built native libraries into * * @parameter expression="${android.ndk.build.ndk-output-directory}" default-value="${project.build.directory}/ndk-libs" */ protected File ndkOutputDirectory; /**

Folder containing native libraries compiled and linked by the NDK.

* * @parameter expression="${android.nativeLibrariesDirectory}" default-value="${project.basedir}/libs" */ private File nativeLibrariesDirectory; /** * Defines the architecture for the NDK build * * @parameter expression="${android.ndk.build.architecture}" default="armeabi" */ protected String ndkArchitecture = "armeabi"; public void execute() throws MojoExecutionException, MojoFailureException { // This points File nativeLibDirectory = new File( nativeLibrariesDirectory , ndkArchitecture ); final boolean libsDirectoryExists = nativeLibDirectory.exists(); File directoryToRemove = nativeLibDirectory; if ( !libsDirectoryExists ) { getLog().info( "Creating native output directory " + nativeLibDirectory ); if ( nativeLibDirectory.getParentFile().exists() ) { nativeLibDirectory.mkdir(); } else { nativeLibDirectory.mkdirs(); directoryToRemove = nativeLibDirectory.getParentFile(); } } final CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor(); executor.setLogger( this.getLog() ); final List commands = new ArrayList(); commands.add( "-C" ); commands.add( project.getBasedir().getAbsolutePath() ); if ( ndkBuildAdditionalCommandline != null ) { String[] additionalCommands = ndkBuildAdditionalCommandline.split( " " ); for ( final String command : additionalCommands ) { commands.add( command ); } } final String ndkBuildPath = getAndroidNdk().getNdkBuildPath(); getLog().info( ndkBuildPath + " " + commands.toString() ); try { executor.executeCommand( ndkBuildPath, commands, project.getBasedir(), true ); } catch ( ExecutionException e ) { throw new MojoExecutionException( e.getMessage(), e ); } // Cleanup libs/armeabi directory if needed - this implies moving any native artifacts into target/libs if ( clearNativeArtifacts ) { final File destinationDirectory = new File( ndkOutputDirectory.getAbsolutePath(), "/" + ndkArchitecture ); try { if ( !libsDirectoryExists ) { FileUtils.moveDirectory( nativeLibDirectory, destinationDirectory ); } else { FileUtils.copyDirectory( nativeLibDirectory, destinationDirectory ); FileUtils.cleanDirectory( nativeLibDirectory ); } nativeLibDirectory = destinationDirectory; } catch ( IOException e ) { throw new MojoExecutionException( e.getMessage(), e ); } } if ( !libsDirectoryExists ) { getLog().info( "Cleaning up native library output directory after build" ); if ( !directoryToRemove.delete() ) { getLog().warn( "Could not remove directory, marking as delete on exit" ); directoryToRemove.deleteOnExit(); } } // Attempt to attach the native library if the project is defined as a "pure" native Android library // (packaging is 'so') or if the plugin has been configured to attach the native library to the build if ( "so".equals(project.getPackaging()) || attachNativeArtifacts ) { File[] files = nativeLibDirectory.listFiles( new FilenameFilter() { public boolean accept( final File dir, final String name ) { return name.endsWith( ".so" ); } } ); // slight limitation at this stage - we only handle a single .so artifact if ( files == null || files.length > 1 ) { getLog().warn( "Error while detecting native compile artifacts: " + ( files == null ? "None found" : "Found more than 1 artifact" ) ); if ( files != null ) { getLog().warn( "Currently, only a single, final native library is supported by the build" ); } } else { getLog().debug( "Adding native compile artifact: " + files[ 0 ] ); projectHelper.attachArtifact( this.project, "so", ( ndkClassifier != null ? ndkClassifier : ndkArchitecture ), files[ 0 ] ); } } } /** *

Returns the Android NDK to use.

*

*

Current implementation looks for <ndk><path> configuration in pom, then System * property android.ndk.path, then environment variable ANDROID_NDK_HOME. *

*

This is where we collect all logic for how to lookup where it is, and which one to choose. The lookup is * based on available parameters. This method should be the only one you should need to look at to understand how * the Android NDK is chosen, and from where on disk.

* * @return the Android NDK to use. * @throws org.apache.maven.plugin.MojoExecutionException * if no Android NDK path configuration is available at all. */ protected AndroidNdk getAndroidNdk() throws MojoExecutionException { File chosenNdkPath; if ( ndk != null ) { // An tag exists in the pom. if ( ndk.getPath() != null ) { // An tag is set in the pom. chosenNdkPath = ndk.getPath(); } else { // There is no tag in the pom. if ( ndkPath != null ) { // -Dandroid.ndk.path is set on command line, or via ... chosenNdkPath = ndkPath; } else { // No -Dandroid.ndk.path is set on command line, or via ... chosenNdkPath = new File( getAndroidNdkHomeOrThrow() ); } } } else { // There is no tag in the pom. if ( ndkPath != null ) { // -Dandroid.ndk.path is set on command line, or via ... chosenNdkPath = ndkPath; } else { // No -Dandroid.ndk.path is set on command line, or via ... chosenNdkPath = new File( getAndroidNdkHomeOrThrow() ); } } return new AndroidNdk( chosenNdkPath ); } private String getAndroidNdkHomeOrThrow() throws MojoExecutionException { final String androidHome = System.getenv( ENV_ANDROID_NDK_HOME ); if ( isBlank( androidHome ) ) { throw new MojoExecutionException( "No Android NDK path could be found. You may configure it in the pom using ... or ... or on command-line using -Dandroid.ndk.path=... or by setting environment variable " + ENV_ANDROID_NDK_HOME ); } return androidHome; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy