コード例 #1
0
  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);
    }
  }
コード例 #2
0
  private void cleanUp(
      File nativeLibDirectory,
      String ndkArchitecture,
      boolean libsDirectoryExists,
      File directoryToRemove,
      MakefileHelper.MakefileHolder makefileHolder,
      File makefileCaptureFile)
      throws IOException, MojoExecutionException {
    try {
      // Cleanup libs/armeabi directory if needed - this implies moving any native artifacts into
      // target/libs
      if (clearNativeArtifacts) {
        nativeLibDirectory =
            cleanUpNativeArtifacts(nativeLibDirectory, ndkArchitecture, libsDirectoryExists);
      }

      // Attempt to attach the native library if the project is defined as a "pure" native Android
      // library
      // (packaging is 'so' or 'a') or if the plugin has been configured to attach the native
      // library to the
      // build
      if ("so".equals(project.getPackaging())
          || "a".equals(project.getPackaging())
          || attachNativeArtifacts) {

        final File nativeArtifactFile;
        if (ndkFinalLibraryName == null) {
          nativeArtifactFile = findNativeLibrary(nativeLibDirectory);
        } else {
          nativeArtifactFile = nativeLibraryFromName(nativeLibDirectory);
        }

        final String artifactType = resolveArtifactType(nativeArtifactFile);
        if (nativeArtifactFile.getName().endsWith(".so") && !skipStripping) {
          getLog()
              .debug("Post processing (stripping) native compiled artifact: " + nativeArtifactFile);
          invokeNDKStripper(nativeArtifactFile);
        }

        getLog().debug("Adding native compiled artifact: " + nativeArtifactFile);

        File fileToAttach = nativeArtifactFile;
        if (!libsDirectoryExists) {
          getLog().debug("Moving native compiled artifact to target directory for preservation");
          // This indicates the output directory was created by the build (us) and that we should
          // really
          // move it to the target (needed to preserve the attached artifact once install is
          // invoked)
          final String destFileName =
              ndkArchitecture + File.separator + nativeArtifactFile.getName();
          final File destFile = new File(ndkOutputDirectory, destFileName);
          if (destFile.exists()) {
            destFile.delete();
          }
          getLog().debug(nativeArtifactFile + " -> " + destFile);
          FileUtils.moveFile(nativeArtifactFile, destFile);
          fileToAttach = destFile;
        }
        projectHelper.attachArtifact(this.project, artifactType, ndkArchitecture, fileToAttach);
      }

      // Process conditionally any of the headers to include into the header archive file
      processMakefileCapture(makefileCaptureFile, ndkArchitecture);

    } finally {
      // If we created any directories as part of the build, blow those away after we're done
      if (!libsDirectoryExists) {
        getLog().info("Cleaning up native library output directory after build");
        getLog().debug("Removing directory: " + directoryToRemove); // AJE - removes 'obj' directory
        FileUtils.deleteDirectory(directoryToRemove);
      }

      // If we created a makefile for the build we should be polite and remove any extracted include
      // directories after we're done
      if (makefileHolder != null) {
        getLog().info("Cleaning up extracted include directories used for build");
        MakefileHelper.cleanupAfterBuild(makefileHolder);
      }
    }
  }
コード例 #3
0
  /**
   * @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);
    }
  }