diff options
Diffstat (limited to 'src/main/java/org/apache/maven/plugin/nar/NarCompileMojo.java')
-rw-r--r-- | src/main/java/org/apache/maven/plugin/nar/NarCompileMojo.java | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/src/main/java/org/apache/maven/plugin/nar/NarCompileMojo.java b/src/main/java/org/apache/maven/plugin/nar/NarCompileMojo.java new file mode 100644 index 0000000..10db16e --- /dev/null +++ b/src/main/java/org/apache/maven/plugin/nar/NarCompileMojo.java @@ -0,0 +1,296 @@ +// Copyright FreeHEP, 2005-2007. +package org.freehep.maven.nar; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.LinkerDef; +import net.sf.antcontrib.cpptasks.OutputTypeEnum; +import net.sf.antcontrib.cpptasks.RuntimeType; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LinkerArgument; +import net.sf.antcontrib.cpptasks.types.SystemLibrarySet; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.StringUtils; + +/** + * Compiles native source files. + * + * @goal nar-compile + * @phase compile + * @requiresDependencyResolution compile + * @author <a href="Mark.Donszelmann@slac.stanford.edu">Mark Donszelmann</a> + * @version $Id: plugin/src/main/java/org/freehep/maven/nar/NarCompileMojo.java 0ee9148b7c6a 2007/09/20 18:42:29 duns $ + */ +public class NarCompileMojo extends AbstractCompileMojo { + + public void execute() throws MojoExecutionException, MojoFailureException { + if (shouldSkip()) + return; + + // make sure destination is there + getTargetDirectory().mkdirs(); + + // check for source files + int noOfSources = 0; + noOfSources += getSourcesFor(getCpp()).size(); + noOfSources += getSourcesFor(getC()).size(); + noOfSources += getSourcesFor(getFortran()).size(); + if (noOfSources > 0) { + for (Iterator i = getLibraries().iterator(); i.hasNext();) { + createLibrary(getAntProject(), (Library) i.next()); + } + } + + try { + // FIXME, should the include paths be defined at a higher level ? + getCpp().copyIncludeFiles(getMavenProject(), + new File(getTargetDirectory(), "include")); + } catch (IOException e) { + throw new MojoExecutionException( + "NAR: could not copy include files", e); + } + } + + private List getSourcesFor(Compiler compiler) throws MojoFailureException { + try { + File srcDir = compiler.getSourceDirectory(); + return srcDir.exists() ? FileUtils.getFiles(srcDir, StringUtils + .join(compiler.getIncludes().iterator(), ","), null) + : Collections.EMPTY_LIST; + } catch (IOException e) { + return Collections.EMPTY_LIST; + } + } + + private void createLibrary(Project antProject, Library library) + throws MojoExecutionException, MojoFailureException { + // configure task + CCTask task = new CCTask(); + task.setProject(antProject); + + // set max cores + task.setMaxCores(getMaxCores(getAOL())); + + // outtype + OutputTypeEnum outTypeEnum = new OutputTypeEnum(); + String type = library.getType(); + outTypeEnum.setValue(type); + task.setOuttype(outTypeEnum); + + // stdc++ + task.setLinkCPP(library.linkCPP()); + + // fortran + task.setLinkFortran(library.linkFortran()); + + // outDir + File outDir = new File(getTargetDirectory(), type + .equals(Library.EXECUTABLE) ? "bin" : "lib"); + outDir = new File(outDir, getAOL().toString()); + if (!type.equals(Library.EXECUTABLE)) + outDir = new File(outDir, type); + outDir.mkdirs(); + + // outFile + File outFile; + if (type.equals(Library.EXECUTABLE)) { + // executable has no version number + outFile = new File(outDir, getMavenProject().getArtifactId()); + } else { + outFile = new File(outDir, getOutput(getAOL())); + } + 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 + RuntimeType runtimeType = new RuntimeType(); + runtimeType.setValue(getRuntime(getAOL())); + task.setRuntime(runtimeType); + + // add C++ compiler + task.addConfiguredCompiler(getCpp().getCompiler(type, getOutput(getAOL()))); + + // add C compiler + task.addConfiguredCompiler(getC().getCompiler(type, getOutput(getAOL()))); + + // add Fortran compiler + task.addConfiguredCompiler(getFortran().getCompiler(type, getOutput(getAOL()))); + + // add javah include path + File jniDirectory = getJavah().getJniDirectory(); + if (jniDirectory.exists()) + task.createIncludePath().setPath(jniDirectory.getPath()); + + // add java include paths + getJava().addIncludePaths(task, type); + + // add dependency include paths + for (Iterator i = getNarManager().getNarDependencies("compile") + .iterator(); i.hasNext();) { + // FIXME, handle multiple includes from one NAR + NarArtifact narDependency = (NarArtifact) i.next(); + String binding = narDependency.getNarInfo().getBinding(getAOL(), + Library.STATIC); + getLog().debug( + "Looking for " + narDependency + " found binding " + + binding); + if (!binding.equals(Library.JNI)) { + File include = new File(getNarManager().getNarFile( + narDependency).getParentFile(), "nar/include"); + getLog().debug("Looking for for directory: " + include); + if (include.exists()) { + task.createIncludePath().setPath(include.getPath()); + } + } + } + + // add linker + 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)) { + + List depLibOrder = getDependencyLibOrder(); + List depLibs = getNarManager().getNarDependencies("compile"); + + // reorder the libraries that come from the nar dependencies + // to comply with the order specified by the user + if ((depLibOrder != null) && !depLibOrder.isEmpty()) { + + List tmp = new LinkedList(); + + for (Iterator i = depLibOrder.iterator(); i.hasNext();) { + + String depToOrderName = (String)i.next(); + + for (Iterator j = depLibs.iterator(); j.hasNext();) { + + NarArtifact dep = (NarArtifact)j.next(); + String depName = dep.getGroupId() + ":" + dep.getArtifactId(); + + if (depName.equals(depToOrderName)) { + + tmp.add(dep); + j.remove(); + } + } + } + + tmp.addAll(depLibs); + depLibs = tmp; + } + + for (Iterator i = depLibs.iterator(); i.hasNext();) { + + NarArtifact dependency = (NarArtifact) i.next(); + + // FIXME no handling of "local" + + // FIXME, no way to override this at this stage + String binding = dependency.getNarInfo().getBinding(getAOL(), + Library.STATIC); + 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)) { + File dir = new File(getNarManager().getNarFile(dependency) + .getParentFile(), "nar/lib/" + aol.toString() + "/" + binding); + getLog().debug("Looking for Library Directory: " + dir); + if (dir.exists()) { + LibrarySet libSet = new LibrarySet(); + libSet.setProject(antProject); + + // FIXME, no way to override + 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 + String options = dependency.getNarInfo().getOptions(getAOL()); + if ((options != null) && !options.equals("")) { + getLog().debug("Using OPTIONS = " + options); + LinkerArgument arg = new LinkerArgument(); + arg.setValue(options); + linkerDefinition.addConfiguredLinkerArg(arg); + } + + String sysLibs = dependency.getNarInfo().getSysLibs( + getAOL()); + if ((sysLibs != null) && !sysLibs.equals("")) { + getLog().debug("Using SYSLIBS = " + sysLibs); + 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 (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") && + NarUtil.getEnv("MSVCVer", "MSVCVer", "6.0").startsWith("8.")) { + String libType = library.getType(); + if (libType.equals(Library.JNI) || libType.equals(Library.SHARED)) { + String dll = outFile.getPath()+".dll"; + String manifest = dll+".manifest"; + int result = NarUtil.runCommand("mt.exe", new String[] {"/manifest", manifest, "/outputresource:"+dll+";#2"}, null, getLog()); + if (result != 0) + throw new MojoFailureException("MT.EXE failed with exit code: " + result); + } + } + } +} |