private Set<Artifact> findNativeLibraryDependencies() throws MojoExecutionException { final NativeHelper nativeHelper = getNativeHelper(); final Set<Artifact> staticLibraryArtifacts = nativeHelper.getNativeDependenciesArtifacts(this, getUnpackedLibsDirectory(), false); final Set<Artifact> sharedLibraryArtifacts = nativeHelper.getNativeDependenciesArtifacts(this, getUnpackedLibsDirectory(), true); final Set<Artifact> mergedArtifacts = new LinkedHashSet<Artifact>(); filterNativeDependencies(mergedArtifacts, staticLibraryArtifacts); filterNativeDependencies(mergedArtifacts, sharedLibraryArtifacts); getLog() .debug( "findNativeLibraryDependencies found " + mergedArtifacts.size() + ": " + mergedArtifacts.toString()); return mergedArtifacts; }
private Set<Artifact> findNativeLibraryDependencies() throws MojoExecutionException { NativeHelper nativeHelper = new NativeHelper(project, projectRepos, repoSession, repoSystem, artifactFactory, getLog()); final Set<Artifact> staticLibraryArtifacts = nativeHelper.getNativeDependenciesArtifacts(unpackedApkLibsDirectory, false); final Set<Artifact> sharedLibraryArtifacts = nativeHelper.getNativeDependenciesArtifacts(unpackedApkLibsDirectory, true); final Set<Artifact> mergedArtifacts = new LinkedHashSet<Artifact>(); filterNativeDependencies(mergedArtifacts, staticLibraryArtifacts); filterNativeDependencies(mergedArtifacts, sharedLibraryArtifacts); if (getLog().isDebugEnabled()) { getLog() .debug( "findNativeLibraryDependencies found " + mergedArtifacts.size() + ": " + mergedArtifacts.toString()); } return mergedArtifacts; }
private void setupNativeLibraryEnvironment( MakefileHelper makefileHelper, CommandExecutor executor, Set<Artifact> resolveNativeLibraryArtifacts, String ndkArchitecture) { // Only add the LOCAL_STATIC_LIBRARIES if (NativeHelper.hasStaticNativeLibraryArtifact( resolveNativeLibraryArtifacts, unpackedApkLibsDirectory, ndkArchitecture)) { String staticlibs = makefileHelper.createLibraryList(resolveNativeLibraryArtifacts, ndkArchitecture, true); executor.addEnvironment("ANDROID_MAVEN_PLUGIN_LOCAL_STATIC_LIBRARIES", staticlibs); getLog().debug("Set ANDROID_MAVEN_PLUGIN_LOCAL_STATIC_LIBRARIES = " + staticlibs); } // Only add the LOCAL_SHARED_LIBRARIES if (NativeHelper.hasSharedNativeLibraryArtifact( resolveNativeLibraryArtifacts, unpackedApkLibsDirectory, ndkArchitecture)) { String sharedlibs = makefileHelper.createLibraryList(resolveNativeLibraryArtifacts, ndkArchitecture, false); executor.addEnvironment("ANDROID_MAVEN_PLUGIN_LOCAL_SHARED_LIBRARIES", sharedlibs); getLog().debug("Set ANDROID_MAVEN_PLUGIN_LOCAL_SHARED_LIBRARIES = " + sharedlibs); } }
/** * @throws MojoExecutionException * @throws MojoFailureException */ public void execute() throws MojoExecutionException, MojoFailureException { try { // Validate the NDK final File ndkBuildFile = new File(getAndroidNdk().getNdkBuildPath()); NativeHelper.validateNDKVersion(ndkBuildFile.getParentFile()); // Validate the makefile - if our packaging type is so (for example) and there are // dependencies on .a files (or shared files for that matter) the makefile should include // the include of our Android Maven plugin generated makefile. validateMakefile(project, makefile); String[] ndkArchitectures = getAndroidNdk() .getNdkArchitectures( ndkClassifier, ndkArchitecture, applicationMakefile, project.getBasedir()); for (String ndkArchitecture : ndkArchitectures) { Preparation preparation = new Preparation().invoke(ndkArchitecture); boolean libsDirectoryExists = preparation.isLibsDirectoryExists(); File directoryToRemove = preparation.getDirectoryToRemove(); // Start setting up the command line to be executed final CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor(); // Add an error listener to the build - this allows the build to conditionally fail // depending on a) the output of the build b) whether or not build errors (output on stderr) // should be // ignored and c) whether the pattern matches or not executor.setErrorListener(getNdkErrorListener()); final Set<Artifact> nativeLibraryArtifacts = findNativeLibraryDependencies(); // If there are any static libraries the code needs to link to, include those in the make // file final Set<Artifact> resolveNativeLibraryArtifacts = AetherHelper.resolveArtifacts( nativeLibraryArtifacts, repoSystem, repoSession, projectRepos); if (getLog().isDebugEnabled()) { getLog() .debug( "resolveArtifacts found " + resolveNativeLibraryArtifacts.size() + ": " + resolveNativeLibraryArtifacts.toString()); } final File makefileDir = new File(project.getBuild().getDirectory(), NDK_MAKFILE_DIRECTORY); makefileDir.mkdirs(); final File androidMavenMakefile = new File(makefileDir, "android_maven_plugin_makefile.mk"); // set the ndk build directory if (ndkBuildDirectory == null) { ndkBuildDirectory = project.getBasedir().getAbsolutePath(); } final MakefileHelper makefileHelper = new MakefileHelper( getLog(), repoSystem, repoSession, projectRepos, unpackedApkLibsDirectory); final MakefileHelper.MakefileHolder makefileHolder = makefileHelper.createMakefileFromArtifacts( new File(ndkBuildDirectory), resolveNativeLibraryArtifacts, ndkArchitecture, useHeaderArchives); IOUtil.copy(makefileHolder.getMakeFile(), new FileOutputStream(androidMavenMakefile)); // Add the path to the generated makefile - this is picked up by the build (by an include // from the user) executor.addEnvironment( "ANDROID_MAVEN_PLUGIN_MAKEFILE", androidMavenMakefile.getAbsolutePath()); setupNativeLibraryEnvironment( makefileHelper, executor, resolveNativeLibraryArtifacts, ndkArchitecture); // Adds the location of the Makefile capturer file - this file will after the build include // things like header files, flags etc. It is processed after the build to retrieve the // headers // and also capture flags etc ... final File makefileCaptureFile = File.createTempFile("android_maven_plugin_makefile_captures", ".tmp"); makefileCaptureFile.deleteOnExit(); executor.addEnvironment( MakefileHelper.MAKEFILE_CAPTURE_FILE, makefileCaptureFile.getAbsolutePath()); // Add any defined system properties if (systemProperties != null && !systemProperties.isEmpty()) { for (Map.Entry<String, String> entry : systemProperties.entrySet()) { executor.addEnvironment(entry.getKey(), entry.getValue()); } } executor.setLogger(this.getLog()); // Setup the command line for the make final List<String> commands = new ArrayList<String>(); // Setup the build directory (defaults to the current directory) but may be different // depending // on user configuration commands.add("-C"); commands.add(ndkBuildDirectory); // If the build should use a custom makefile or not - some validation is done to ensure // this exists and all if (makefile != null) { File makeFile = new File(project.getBasedir(), makefile); if (!makeFile.exists()) { getLog().error("Specified makefile " + makeFile + " does not exist"); throw new MojoExecutionException("Specified makefile " + makeFile + " does not exist"); } commands.add("-f"); commands.add(makefile); } configureApplicationMakefile(commands); configureMaxJobs(commands); configureNdkToolchain(commands); // Anything else on the command line the user wants to add - simply splice it up and // add it one by one to the command line if (ndkBuildAdditionalCommandline != null) { String[] additionalCommands = ndkBuildAdditionalCommandline.split(" "); for (final String command : additionalCommands) { commands.add(command); } } // If a build target is specified, tag that onto the command line as the // very last of the parameters if (target != null) { commands.add(target); } else /*if ( "a".equals( project.getPackaging() ) )*/ { commands.add(project.getArtifactId()); } final String ndkBuildPath = resolveNdkBuildExecutable(); getLog().info(ndkBuildPath + " " + commands.toString()); executor.executeCommand(ndkBuildPath, commands, project.getBasedir(), true); cleanUp( preparation.getNativeLibDirectory(), ndkArchitecture, libsDirectoryExists, directoryToRemove, makefileHolder, makefileCaptureFile); } } catch (MojoExecutionException e) { getLog().error("Error during build: " + e.getMessage(), e); throw e; } catch (Exception e) { getLog().error("Error while executing: " + e.getMessage()); throw new MojoExecutionException(e.getMessage(), e); } }
private void processNativeLibraries(final List<File> natives, String ndkArchitecture) throws MojoExecutionException { // Examine the native libraries directory for content. This will only be true if: // a) the directory exists // b) it contains at least 1 file final boolean hasValidNativeLibrariesDirectory = hasValidNativeLibrariesDirectory(); final boolean hasValidBuildNativeLibrariesDirectory = hasValidBuildNativeLibrariesDirectory(); final Set<Artifact> artifacts = getNativeLibraryArtifacts(); if (artifacts.isEmpty() && hasValidNativeLibrariesDirectory && !hasValidBuildNativeLibrariesDirectory) { getLog() .debug( "No native library dependencies detected, will point directly to " + nativeLibrariesDirectory); // Point directly to the directory in this case - no need to copy files around addNativeDirectory(natives, nativeLibrariesDirectory); // FIXME: This would pollute a libs folder which is under source control // FIXME: Would be better to not support this case? optionallyCopyGdbServer(nativeLibrariesDirectory, ndkArchitecture); } else { if (!artifacts.isEmpty() || hasValidNativeLibrariesDirectory) { // In this case, we may have both .so files in it's normal location // as well as .so dependencies final File destinationDirectory = makeNativeLibrariesOutputDirectory(); // Point directly to the directory addNativeDirectory(natives, destinationDirectory); // If we have a valid native libs, copy those files - these already come in the structure // required if (hasValidNativeLibrariesDirectory) { copyLocalNativeLibraries(nativeLibrariesDirectory, destinationDirectory); } if (!artifacts.isEmpty()) { for (Artifact resolvedArtifact : artifacts) { if (NativeHelper.artifactHasHardwareArchitecture( resolvedArtifact, ndkArchitecture, nativeLibrariesDependenciesHardwareArchitectureDefault)) { copyNativeLibraryArtifactFileToDirectory( resolvedArtifact, destinationDirectory, ndkArchitecture); } else if (APKLIB.equals(resolvedArtifact.getType()) || AAR.equals(resolvedArtifact.getType())) { addNativeDirectory(natives, getUnpackedLibNativesFolder(resolvedArtifact)); } } } // Finally, think about copying the gdbserver binary into the APK output as well optionallyCopyGdbServer(destinationDirectory, ndkArchitecture); } } }