@Override
  public final void narExecute() throws MojoExecutionException, MojoFailureException {
    if (!useGnu() || gnuMakeSkip) {
      return;
    }

    final File srcDir = getGnuAOLSourceDirectory();
    if (srcDir.exists()) {
      String[] args = null;
      String[] env = null;

      if (this.gnuMakeArgs != null) {
        args = this.gnuMakeArgs.split(" ");
      }
      if (this.gnuMakeEnv != null) {
        env = this.gnuMakeEnv.split(",");
      }

      getLog().info("Running GNU make");
      int result = NarUtil.runCommand("make", args, srcDir, env, getLog());
      if (result != 0) {
        throw new MojoExecutionException("'make' errorcode: " + result);
      }

      if (!this.gnuMakeInstallSkip) {
        getLog().info("Running make install");
        if (args != null) {
          this.gnuMakeArgs = this.gnuMakeArgs + " install";
          args = this.gnuMakeArgs.split(" ");
        } else {
          args = new String[] {"install"};
        }
        result = NarUtil.runCommand("make", args, srcDir, null, getLog());
        if (result != 0) {
          throw new MojoExecutionException("'make install' errorcode: " + result);
        }
      }
    }
  }
  private SurefireBooter constructSurefireBooter()
      throws MojoExecutionException, MojoFailureException {
    SurefireBooter surefireBooter = new SurefireBooter();

    Artifact surefireArtifact =
        (Artifact) pluginArtifactMap.get("org.apache.maven.surefire:surefire-booter");
    if (surefireArtifact == null) {
      throw new MojoExecutionException(
          "Unable to locate surefire-booter in the list of plugin artifacts");
    }

    surefireArtifact
        .isSnapshot(); // TODO: this is ridiculous, but it fixes getBaseVersion to be -SNAPSHOT if
    // needed

    Artifact junitArtifact;
    Artifact testNgArtifact;
    try {
      addArtifact(surefireBooter, surefireArtifact);

      junitArtifact = (Artifact) projectArtifactMap.get(junitArtifactName);
      // SUREFIRE-378, junit can have an alternate artifact name
      if (junitArtifact == null && "junit:junit".equals(junitArtifactName)) {
        junitArtifact = (Artifact) projectArtifactMap.get("junit:junit-dep");
      }

      // TODO: this is pretty manual, but I'd rather not require the plugin > dependencies section
      // right now
      testNgArtifact = (Artifact) projectArtifactMap.get(testNGArtifactName);

      if (testNgArtifact != null) {
        VersionRange range = VersionRange.createFromVersionSpec("[4.7,)");
        if (!range.containsVersion(new DefaultArtifactVersion(testNgArtifact.getVersion()))) {
          throw new MojoFailureException(
              "TestNG support requires version 4.7 or above. You have declared version "
                  + testNgArtifact.getVersion());
        }

        convertTestNGParameters();

        if (this.testClassesDirectory != null) {
          properties.setProperty("testng.test.classpath", testClassesDirectory.getAbsolutePath());
        }

        addArtifact(surefireBooter, testNgArtifact);

        // The plugin uses a JDK based profile to select the right testng. We might be explicity
        // using a
        // different one since its based on the source level, not the JVM. Prune using the filter.
        addProvider(
            surefireBooter, "surefire-testng", surefireArtifact.getBaseVersion(), testNgArtifact);
      } else if (junitArtifact != null && junitArtifact.getBaseVersion().startsWith("4")) {
        addProvider(surefireBooter, "surefire-junit4", surefireArtifact.getBaseVersion(), null);
      } else {
        // add the JUnit provider as default - it doesn't require JUnit to be present,
        // since it supports POJO tests.
        addProvider(surefireBooter, "surefire-junit", surefireArtifact.getBaseVersion(), null);
      }
    } catch (ArtifactNotFoundException e) {
      throw new MojoExecutionException(
          "Unable to locate required surefire provider dependency: " + e.getMessage(), e);
    } catch (InvalidVersionSpecificationException e) {
      throw new MojoExecutionException(
          "Error determining the TestNG version requested: " + e.getMessage(), e);
    } catch (ArtifactResolutionException e) {
      throw new MojoExecutionException(
          "Error to resolving surefire provider dependency: " + e.getMessage(), e);
    }

    if (suiteXmlFiles != null && suiteXmlFiles.length > 0 && test == null) {
      if (testNgArtifact == null) {
        throw new MojoExecutionException(
            "suiteXmlFiles is configured, but there is no TestNG dependency");
      }

      // TODO: properties should be passed in here too
      surefireBooter.addTestSuite(
          "org.apache.maven.surefire.testng.TestNGXmlTestSuite",
          new Object[] {
            suiteXmlFiles,
            testSourceDirectory.getAbsolutePath(),
            testNgArtifact.getVersion(),
            testNgArtifact.getClassifier(),
            properties,
            reportsDirectory
          });
    } else {
      List includeList;
      List excludeList;

      if (test != null) {
        // Check to see if we are running a single test. The raw parameter will
        // come through if it has not been set.

        // FooTest -> **/FooTest.java

        includeList = new ArrayList();

        excludeList = new ArrayList();

        if (failIfNoTests == null) {
          failIfNoTests = Boolean.TRUE;
        }

        String[] testRegexes = StringUtils.split(test, ",");

        for (int i = 0; i < testRegexes.length; i++) {
          String testRegex = testRegexes[i];
          if (testRegex.endsWith(".java")) {
            testRegex = testRegex.substring(0, testRegex.length() - 5);
          }
          // Allow paths delimited by '.' or '/'
          testRegex = testRegex.replace('.', '/');
          includeList.add("**/" + testRegex + ".java");
        }
      } else {
        includeList = this.includes;

        excludeList = this.excludes;

        // defaults here, qdox doesn't like the end javadoc value
        // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some
        // reason
        if (includeList == null || includeList.size() == 0) {
          includeList =
              new ArrayList(
                  Arrays.asList(
                      new String[] {"**/Test*.java", "**/*Test.java", "**/*TestCase.java"}));
        }
        if (excludeList == null || excludeList.size() == 0) {
          excludeList = new ArrayList(Arrays.asList(new String[] {"**/*$*"}));
        }
      }

      if (testNgArtifact != null) {
        surefireBooter.addTestSuite(
            "org.apache.maven.surefire.testng.TestNGDirectoryTestSuite",
            new Object[] {
              testClassesDirectory,
              includeList,
              excludeList,
              testSourceDirectory.getAbsolutePath(),
              testNgArtifact.getVersion(),
              testNgArtifact.getClassifier(),
              properties,
              reportsDirectory
            });
      } else {
        String junitDirectoryTestSuite;
        if (junitArtifact != null
            && junitArtifact.getBaseVersion() != null
            && junitArtifact.getBaseVersion().startsWith("4")) {
          junitDirectoryTestSuite = "org.apache.maven.surefire.junit4.JUnit4DirectoryTestSuite";
        } else {
          junitDirectoryTestSuite = "org.apache.maven.surefire.junit.JUnitDirectoryTestSuite";
        }

        // fall back to JUnit, which also contains POJO support. Also it can run
        // classes compiled against JUnit since it has a dependency on JUnit itself.
        surefireBooter.addTestSuite(
            junitDirectoryTestSuite, new Object[] {testClassesDirectory, includeList, excludeList});
      }
    }

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    getLog().debug("Test Classpath :");

    // Check if we need to add configured classes/test classes directories here.
    // If they are configured, we should remove the default to avoid conflicts.
    if (!project.getBuild().getOutputDirectory().equals(classesDirectory.getAbsolutePath())) {
      classpathElements.remove(project.getBuild().getOutputDirectory());
      classpathElements.add(classesDirectory.getAbsolutePath());
    }
    if (!project
        .getBuild()
        .getTestOutputDirectory()
        .equals(testClassesDirectory.getAbsolutePath())) {
      classpathElements.remove(project.getBuild().getTestOutputDirectory());
      classpathElements.add(testClassesDirectory.getAbsolutePath());
    }

    for (Iterator i = classpathElements.iterator(); i.hasNext(); ) {
      String classpathElement = (String) i.next();

      getLog().debug("  " + classpathElement);

      surefireBooter.addClassPathUrl(classpathElement);
    }

    Toolchain tc = getToolchain();

    if (tc != null) {
      getLog().info("Toolchain in surefire-plugin: " + tc);
      if (ForkConfiguration.FORK_NEVER.equals(forkMode)) {
        forkMode = ForkConfiguration.FORK_ONCE;
      }
      if (jvm != null) {
        getLog().warn("Toolchains are ignored, 'executable' parameter is set to " + jvm);
      } else {
        jvm = tc.findTool("java"); // NOI18N
      }
    }

    if (additionalClasspathElements != null) {
      for (Iterator i = additionalClasspathElements.iterator(); i.hasNext(); ) {
        String classpathElement = (String) i.next();

        getLog().debug("  " + classpathElement);

        surefireBooter.addClassPathUrl(classpathElement);
      }
    }

    // ----------------------------------------------------------------------
    // Forking
    // ----------------------------------------------------------------------

    ForkConfiguration fork = new ForkConfiguration();

    // DUNS
    if (project.getPackaging().equals("nar") || (getNarArtifacts().size() > 0)) {
      forkMode = "pertest";
    }

    fork.setForkMode(forkMode);

    processSystemProperties(!fork.isForking());

    if (getLog().isDebugEnabled()) {
      showMap(systemProperties, "system property");
    }

    if (fork.isForking()) {
      useSystemClassLoader = useSystemClassLoader == null ? Boolean.TRUE : useSystemClassLoader;
      fork.setUseSystemClassLoader(useSystemClassLoader.booleanValue());
      fork.setUseManifestOnlyJar(useManifestOnlyJar);

      fork.setSystemProperties(systemProperties);

      if ("true".equals(debugForkedProcess)) {
        debugForkedProcess =
            "-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005";
      }

      fork.setDebugLine(debugForkedProcess);

      if (jvm == null || "".equals(jvm)) {
        // use the same JVM as the one used to run Maven (the "java.home" one)
        jvm = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
        getLog().debug("Using JVM: " + jvm);
      }

      fork.setJvmExecutable(jvm);

      if (workingDirectory != null) {
        fork.setWorkingDirectory(workingDirectory);
      } else {
        fork.setWorkingDirectory(basedir);
      }

      // BEGINDUNS
      if (argLine == null) {
        argLine = "";
      }

      StringBuffer javaLibraryPath = new StringBuffer();
      if (testJNIModule()) {
        // Add libraries to java.library.path for testing
        File jniLibraryPathEntry =
            getLayout()
                .getLibDirectory(
                    getTargetDirectory(),
                    getMavenProject().getArtifactId(),
                    getMavenProject().getVersion(),
                    getAOL().toString(),
                    Library.JNI);
        if (jniLibraryPathEntry.exists()) {
          getLog().debug("Adding library directory to java.library.path: " + jniLibraryPathEntry);
          if (javaLibraryPath.length() > 0) {
            javaLibraryPath.append(File.pathSeparator);
          }
          javaLibraryPath.append(jniLibraryPathEntry);
        }

        File sharedLibraryPathEntry =
            getLayout()
                .getLibDirectory(
                    getTargetDirectory(),
                    getMavenProject().getArtifactId(),
                    getMavenProject().getVersion(),
                    getAOL().toString(),
                    Library.SHARED);
        if (sharedLibraryPathEntry.exists()) {
          getLog()
              .debug("Adding library directory to java.library.path: " + sharedLibraryPathEntry);
          if (javaLibraryPath.length() > 0) {
            javaLibraryPath.append(File.pathSeparator);
          }
          javaLibraryPath.append(sharedLibraryPathEntry);
        }

        // add jar file to classpath, as one may want to read a
        // properties file for artifactId and version
        String narFile = "target/" + project.getArtifactId() + "-" + project.getVersion() + ".jar";
        getLog().debug("Adding to surefire test classpath: " + narFile);
        surefireBooter.addClassPathUrl(narFile);
      }

      List dependencies =
          getNarArtifacts(); // TODO: get seems heavy, not sure if we can push this up to before the
                             // fork to use it multiple times.
      for (Iterator i = dependencies.iterator(); i.hasNext(); ) {
        NarArtifact dependency = (NarArtifact) i.next();
        // FIXME this should be overridable
        // NarInfo info = dependency.getNarInfo();
        // String binding = info.getBinding(getAOL(), Library.STATIC);
        // NOTE: fixed to shared, jni
        String[] bindings = {Library.SHARED, Library.JNI};
        for (int j = 0; j < bindings.length; j++) {
          String binding = bindings[j];
          if (!binding.equals(Library.STATIC)) {
            File depLibPathEntry =
                getLayout()
                    .getLibDirectory(
                        getUnpackDirectory(),
                        dependency.getArtifactId(),
                        dependency.getVersion(),
                        getAOL().toString(),
                        binding);
            if (depLibPathEntry.exists()) {
              getLog()
                  .debug("Adding dependency directory to java.library.path: " + depLibPathEntry);
              if (javaLibraryPath.length() > 0) {
                javaLibraryPath.append(File.pathSeparator);
              }
              javaLibraryPath.append(depLibPathEntry);
            }
          }
        }
      }

      // add final javalibrary path
      if (javaLibraryPath.length() > 0) {
        // NOTE java.library.path only works for the jni lib itself, and
        // not for its dependent shareables.
        // NOTE: java.library.path does not work with arguments with
        // spaces as
        // SureFireBooter splits the line in parts and then quotes
        // it wrongly
        NarUtil.addLibraryPathToEnv(javaLibraryPath.toString(), environmentVariables, getOS());
      }

      // necessary to find WinSxS
      if (getOS().equals(OS.WINDOWS)) {
        environmentVariables.put(
            "SystemRoot", NarUtil.getEnv("SystemRoot", "SystemRoot", "C:\\Windows"));
      }
      // ENDDUNS

      fork.setArgLine(argLine);

      fork.setEnvironmentVariables(environmentVariables);

      if (getLog().isDebugEnabled()) {
        showMap(environmentVariables, "environment variable");

        fork.setDebug(true);
      }

      if (argLine != null) {
        List args = Arrays.asList(argLine.split(" "));
        if (args.contains("-da") || args.contains("-disableassertions")) {
          enableAssertions = false;
        }
      }
    }

    surefireBooter.setFailIfNoTests(failIfNoTests == null ? false : failIfNoTests.booleanValue());

    surefireBooter.setForkedProcessTimeoutInSeconds(forkedProcessTimeoutInSeconds);

    surefireBooter.setRedirectTestOutputToFile(redirectTestOutputToFile);

    surefireBooter.setForkConfiguration(fork);

    surefireBooter.setChildDelegation(childDelegation);

    surefireBooter.setEnableAssertions(enableAssertions);

    surefireBooter.setReportsDirectory(reportsDirectory);

    addReporters(surefireBooter, fork.isForking());

    return surefireBooter;
  }
  public final String getVersion(final AbstractNarMojo mojo)
      throws MojoFailureException, MojoExecutionException {
    if (this.name == null) {
      throw new MojoFailureException("Cannot deduce linker version if name is null");
    }

    String version = null;

    final TextStream out = new StringTextStream();
    final TextStream err = new StringTextStream();
    final TextStream dbg = new StringTextStream();

    if (this.name.equals("g++") || this.name.equals("gcc")) {
      NarUtil.runCommand("gcc", new String[] {"--version"}, null, null, out, err, dbg, this.log);
      final Pattern p = Pattern.compile("\\d+\\.\\d+\\.\\d+");
      final Matcher m = p.matcher(out.toString());
      if (m.find()) {
        version = m.group(0);
      }
    } else if (this.name.equals("msvc")) {
      version = mojo.getMsvc().getVersion();
    } else if (this.name.equals("icc") || this.name.equals("icpc")) {
      NarUtil.runCommand("icc", new String[] {"--version"}, null, null, out, err, dbg, this.log);
      final Pattern p = Pattern.compile("\\d+\\.\\d+");
      final Matcher m = p.matcher(out.toString());
      if (m.find()) {
        version = m.group(0);
      }
    } else if (this.name.equals("icl")) {
      NarUtil.runCommand("icl", new String[] {"/QV"}, null, null, out, err, dbg, this.log);
      final Pattern p = Pattern.compile("\\d+\\.\\d+");
      final Matcher m = p.matcher(err.toString());
      if (m.find()) {
        version = m.group(0);
      }
    } else if (this.name.equals("CC")) {
      NarUtil.runCommand("CC", new String[] {"-V"}, null, null, out, err, dbg, this.log);
      final Pattern p = Pattern.compile("\\d+\\.d+");
      final Matcher m = p.matcher(err.toString());
      if (m.find()) {
        version = m.group(0);
      }
    } else if (this.name.equals("xlC")) {
      NarUtil.runCommand(
          "/usr/vacpp/bin/xlC", new String[] {"-qversion"}, null, null, out, err, dbg, this.log);
      final Pattern p = Pattern.compile("\\d+\\.\\d+");
      final Matcher m = p.matcher(out.toString());
      if (m.find()) {
        version = m.group(0);
      }
    } else {
      throw new MojoFailureException("Cannot find version number for linker '" + this.name + "'");
    }

    if (version == null) {
      if (!err.toString().isEmpty())
        mojo.getLog().debug("linker returned error stream: " + err.toString());
      throw new MojoFailureException("Cannot deduce version number from: " + out.toString());
    }
    return version;
  }
  private void createLibrary(final Project antProject, final Library library)
      throws MojoExecutionException, MojoFailureException {
    getLog().debug("Creating Library " + library);
    // configure task
    final CCTask task = new CCTask();
    task.setCommandLogLevel(this.commandLogLevel);
    task.setProject(antProject);

    task.setDecorateLinkerOptions(this.decorateLinkerOptions);

    // subsystem
    final SubsystemEnum subSystem = new SubsystemEnum();
    subSystem.setValue(library.getSubSystem());
    task.setSubsystem(subSystem);

    // set max cores
    task.setMaxCores(getMaxCores(getAOL()));

    // outtype
    final OutputTypeEnum outTypeEnum = new OutputTypeEnum();
    final String type = library.getType();
    outTypeEnum.setValue(type);
    task.setOuttype(outTypeEnum);

    // stdc++
    task.setLinkCPP(library.linkCPP());

    // fortran
    task.setLinkFortran(library.linkFortran());
    task.setLinkFortranMain(library.linkFortranMain());

    // outDir
    File outDir;
    if (type.equals(Library.EXECUTABLE)) {
      outDir =
          getLayout()
              .getBinDirectory(
                  getTargetDirectory(),
                  getMavenProject().getArtifactId(),
                  getMavenProject().getVersion(),
                  getAOL().toString());
    } else {
      outDir =
          getLayout()
              .getLibDirectory(
                  getTargetDirectory(),
                  getMavenProject().getArtifactId(),
                  getMavenProject().getVersion(),
                  getAOL().toString(),
                  type);
    }
    outDir.mkdirs();

    // outFile
    // FIXME NAR-90 we could get the final name from layout
    final File outFile = new File(outDir, getOutput(getAOL(), type));
    getLog().debug("NAR - output: '" + outFile + "'");
    task.setOutfile(outFile);

    // object directory
    File objDir = new File(getTargetDirectory(), "obj");
    objDir = new File(objDir, getAOL().toString());
    objDir.mkdirs();
    task.setObjdir(objDir);

    // failOnError, libtool
    task.setFailonerror(failOnError(getAOL()));
    task.setLibtool(useLibtool(getAOL()));

    // runtime
    final RuntimeType runtimeType = new RuntimeType();
    runtimeType.setValue(getRuntime(getAOL()));
    task.setRuntime(runtimeType);

    // IDL, MC, RC compilations should probably be 'generate source' type
    // actions, seperate from main build.
    // Needs resolution of handling for generate sources.
    // Order is somewhat important here, IDL and MC generate outputs that are
    // (often) included in the RC compilation
    if (getIdl() != null) {
      final CompilerDef idl = getIdl().getCompiler(Compiler.MAIN, null);
      if (idl != null) {
        task.addConfiguredCompiler(idl);
      }
    }
    if (getMessage() != null) {
      final CompilerDef mc = getMessage().getCompiler(Compiler.MAIN, null);
      if (mc != null) {
        task.addConfiguredCompiler(mc);
      }
    }
    if (getResource() != null) {
      final CompilerDef res = getResource().getCompiler(Compiler.MAIN, null);
      if (res != null) {
        task.addConfiguredCompiler(res);
      }
    }

    // Darren Sargent Feb 11 2010: Use Compiler.MAIN for "type"...appears the
    // wrong "type" variable was being used
    // since getCompiler() expects "main" or "test", whereas the "type" variable
    // here is "executable", "shared" etc.
    // add C++ compiler
    if (getCpp() != null) {
      final CompilerDef cpp = getCpp().getCompiler(Compiler.MAIN, null);
      if (cpp != null) {
        task.addConfiguredCompiler(cpp);
      }
    }

    // add C compiler
    if (getC() != null) {
      final CompilerDef c = getC().getCompiler(Compiler.MAIN, null);
      if (c != null) {
        task.addConfiguredCompiler(c);
      }
    }

    // add Fortran compiler
    if (getFortran() != null) {
      final CompilerDef fortran = getFortran().getCompiler(Compiler.MAIN, null);
      if (fortran != null) {
        task.addConfiguredCompiler(fortran);
      }
    }
    // end Darren

    // add javah include path
    final File jniDirectory = getJavah().getJniDirectory();
    if (jniDirectory.exists()) {
      task.createIncludePath().setPath(jniDirectory.getPath());
    }

    // add java include paths
    getJava().addIncludePaths(task, type);

    final List<NarArtifact> dependencies = getNarArtifacts();
    // add dependency include paths
    for (final Object element : dependencies) {
      // FIXME, handle multiple includes from one NAR
      final NarArtifact narDependency = (NarArtifact) element;
      final String binding = narDependency.getNarInfo().getBinding(getAOL(), Library.STATIC);
      getLog().debug("Looking for " + narDependency + " found binding " + binding);
      if (!binding.equals(Library.JNI)) {
        final File unpackDirectory = getUnpackDirectory();
        final File include =
            getLayout()
                .getIncludeDirectory(
                    unpackDirectory, narDependency.getArtifactId(), narDependency.getBaseVersion());
        getLog().debug("Looking for include directory: " + include);
        if (include.exists()) {
          task.createIncludePath().setPath(include.getPath());
        } else {
          throw new MojoExecutionException("NAR: unable to locate include path: " + include);
        }
      }
    }

    // add linker
    final LinkerDef linkerDefinition =
        getLinker().getLinker(this, antProject, getOS(), getAOL().getKey() + ".linker.", type);
    task.addConfiguredLinker(linkerDefinition);

    // add dependency libraries
    // FIXME: what about PLUGIN and STATIC, depending on STATIC, should we
    // not add all libraries, see NARPLUGIN-96
    if (type.equals(Library.SHARED)
        || type.equals(Library.JNI)
        || type.equals(Library.EXECUTABLE)) {

      final List depLibOrder = getDependencyLibOrder();
      List depLibs = dependencies;

      // reorder the libraries that come from the nar dependencies
      // to comply with the order specified by the user
      if (depLibOrder != null && !depLibOrder.isEmpty()) {
        final List tmp = new LinkedList();

        for (final Iterator i = depLibOrder.iterator(); i.hasNext(); ) {
          final String depToOrderName = (String) i.next();

          for (final Iterator j = depLibs.iterator(); j.hasNext(); ) {
            final NarArtifact dep = (NarArtifact) j.next();
            final String depName = dep.getGroupId() + ":" + dep.getArtifactId();

            if (depName.equals(depToOrderName)) {
              tmp.add(dep);
              j.remove();
            }
          }
        }

        tmp.addAll(depLibs);
        depLibs = tmp;
      }

      for (final Iterator i = depLibs.iterator(); i.hasNext(); ) {
        final NarArtifact dependency = (NarArtifact) i.next();

        // FIXME no handling of "local"

        // FIXME, no way to override this at this stage
        final String binding = dependency.getNarInfo().getBinding(getAOL(), Library.NONE);
        getLog().debug("Using Binding: " + binding);
        AOL aol = getAOL();
        aol = dependency.getNarInfo().getAOL(getAOL());
        getLog().debug("Using Library AOL: " + aol.toString());

        if (!binding.equals(Library.JNI)
            && !binding.equals(Library.NONE)
            && !binding.equals(Library.EXECUTABLE)) {
          final File unpackDirectory = getUnpackDirectory();

          final File dir =
              getLayout()
                  .getLibDirectory(
                      unpackDirectory,
                      dependency.getArtifactId(),
                      dependency.getBaseVersion(),
                      aol.toString(),
                      binding);

          getLog().debug("Looking for Library Directory: " + dir);
          if (dir.exists()) {
            final LibrarySet libSet = new LibrarySet();
            libSet.setProject(antProject);

            // FIXME, no way to override
            final String libs = dependency.getNarInfo().getLibs(getAOL());
            if (libs != null && !libs.equals("")) {
              getLog().debug("Using LIBS = " + libs);
              libSet.setLibs(new CUtil.StringArrayBuilder(libs));
              libSet.setDir(dir);
              task.addLibset(libSet);
            }
          } else {
            getLog().debug("Library Directory " + dir + " does NOT exist.");
          }

          // FIXME, look again at this, for multiple dependencies we may need to
          // remove duplicates
          final String options = dependency.getNarInfo().getOptions(getAOL());
          if (options != null && !options.equals("")) {
            getLog().debug("Using OPTIONS = " + options);
            final LinkerArgument arg = new LinkerArgument();
            arg.setValue(options);
            linkerDefinition.addConfiguredLinkerArg(arg);
          }

          final String sysLibs = dependency.getNarInfo().getSysLibs(getAOL());
          if (sysLibs != null && !sysLibs.equals("")) {
            getLog().debug("Using SYSLIBS = " + sysLibs);
            final SystemLibrarySet sysLibSet = new SystemLibrarySet();
            sysLibSet.setProject(antProject);

            sysLibSet.setLibs(new CUtil.StringArrayBuilder(sysLibs));
            task.addSyslibset(sysLibSet);
          }
        }
      }
    }

    // Add JVM to linker
    getJava().addRuntime(task, getJavaHome(getAOL()), getOS(), getAOL().getKey() + ".java.");

    // execute
    try {
      task.execute();
    } catch (final BuildException e) {
      throw new MojoExecutionException("NAR: Compile failed", e);
    }

    // FIXME, this should be done in CPPTasks at some point
    if (getRuntime(getAOL()).equals("dynamic")
        && getOS().equals(OS.WINDOWS)
        && getLinker().getName(null, null).equals("msvc")
        && !getLinker().getVersion().startsWith("6.")) {
      final String libType = library.getType();
      if (libType.equals(Library.JNI) || libType.equals(Library.SHARED)) {
        final String dll = outFile.getPath() + ".dll";
        final String manifest = dll + ".manifest";
        final int result =
            NarUtil.runCommand(
                "mt.exe",
                new String[] {"/manifest", manifest, "/outputresource:" + dll + ";#2"},
                null,
                null,
                getLog());
        if (result != 0) {
          throw new MojoFailureException("MT.EXE failed with exit code: " + result);
        }
      } else if (libType.equals(Library.EXECUTABLE)) {
        final String exe = outFile.getPath() + ".exe";
        final String manifest = exe + ".manifest";
        final int result =
            NarUtil.runCommand(
                "mt.exe",
                new String[] {"/manifest", manifest, "/outputresource:" + exe + ";#1"},
                null,
                null,
                getLog());
        if (result != 0) {
          throw new MojoFailureException("MT.EXE failed with exit code: " + result);
        }
      }
    }
  }
  protected void unpackNarAndProcess(
      ArchiverManager archiverManager,
      File file,
      File narLocation,
      String os,
      String linkerName,
      AOL defaultAOL)
      throws MojoExecutionException, MojoFailureException {

    final String gpp = "g++";
    final String gcc = "gcc";

    narLocation.mkdirs();

    // unpack
    try {
      UnArchiver unArchiver;
      unArchiver = archiverManager.getUnArchiver(NarConstants.NAR_ROLE_HINT);
      unArchiver.setSourceFile(file);
      unArchiver.setDestDirectory(narLocation);
      unArchiver.extract();
    } catch (NoSuchArchiverException e) {
      throw new MojoExecutionException("Error unpacking file: " + file + " to: " + narLocation, e);
    } catch (ArchiverException e) {
      throw new MojoExecutionException("Error unpacking file: " + file + " to: " + narLocation, e);
    }

    // process
    if (!NarUtil.getOS(os).equals(OS.WINDOWS)) {
      NarUtil.makeExecutable(new File(narLocation, "bin/" + defaultAOL), log);
      // FIXME clumsy
      if (defaultAOL.hasLinker(gpp)) {
        NarUtil.makeExecutable(
            new File(narLocation, "bin/" + NarUtil.replace(gpp, gcc, defaultAOL.toString())), log);
      }
      // add link to versioned so files
      NarUtil.makeLink(new File(narLocation, "lib/" + defaultAOL), log);
    }
    if (linkerName.equals(gcc) || linkerName.equals(gpp)) {
      NarUtil.runRanlib(new File(narLocation, "lib/" + defaultAOL), log);
      // FIXME clumsy
      if (defaultAOL.hasLinker(gpp)) {
        NarUtil.runRanlib(
            new File(narLocation, "lib/" + NarUtil.replace(gpp, gcc, defaultAOL.toString())), log);
      }
    }
    // TODO: Find replacement action to install name tool
    // install name tool adjusts the internal lookup directory for the libraries,
    // this isn't really appropriate, removing signatures for one.
    // however don't have a replacement action currently... having commented this,
    // may break some usage, perhaps if don't find solution make configurable.
    //        if ( NarUtil.getOS( os ).equals( OS.MACOSX ) )
    //        {
    //            File[] dylibDirs = new File[2];
    //            dylibDirs[0] = new File( narLocation, "lib/" + defaultAOL + "/" + Library.SHARED
    // );
    //            dylibDirs[1] = new File( narLocation, "lib/" + defaultAOL + "/" + Library.JNI );
    //
    //            NarUtil.runInstallNameTool( dylibDirs, log );
    //        }
  }