// Copyright FreeHEP, 2005-2007.
package org.freehep.maven.nar;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.LinkedList;
import net.sf.antcontrib.cpptasks.CUtil;
import net.sf.antcontrib.cpptasks.LinkerDef;
import net.sf.antcontrib.cpptasks.LinkerEnum;
import net.sf.antcontrib.cpptasks.types.LibrarySet;
import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum;
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.Project;
import org.codehaus.plexus.util.FileUtils;
/**
* Linker tag
*
* @author <a href="Mark.Donszelmann@slac.stanford.edu">Mark Donszelmann</a>
* @version $Id: Linker.java 13295 2007-09-06 18:55:15Z duns $
*/
public class Linker {
/**
* The Linker Some choices are: "msvc", "g++", "CC", "icpc", ... Default is
* Architecture-OS-Linker specific: FIXME: table missing
*
* @parameter expression=""
*/
private String name;
/**
* Enables or disables incremental linking.
*
* @parameter expression="" default-value="false"
* @required
*/
private boolean incremental = false;
/**
* Enables or disables the production of a map file.
*
* @parameter expression="" default-value="false"
* @required
*/
private boolean map = false;
/**
* Options for the linker Defaults to Architecture-OS-Linker specific
* values. FIXME table missing
*
* @parameter expression=""
*/
private List options;
/**
* Options for the linker as a whitespace separated list.
* Defaults to Architecture-OS-Linker specific values.
* Will work in combination with <options>.
*
* @parameter expression=""
*/
private String optionSet;
/**
* Clears default options
*
* @parameter expression="" default-value="false"
* @required
*/
private boolean clearDefaultOptions;
/**
* Adds libraries to the linker.
*
* @parameter expression=""
*/
private List/* <Lib> */libs;
/**
* Adds libraries to the linker. Will work in combination with <libs>.
* The format is comma separated, colon-delimited values (name:type:dir),
* like "myLib:shared:/home/me/libs/, otherLib:static:/some/path".
*
* @parameter expression=""
*/
private String libSet;
/**
* Adds system libraries to the linker.
*
* @parameter expression=""
*/
private List/* <SysLib> */sysLibs;
/**
* Adds system libraries to the linker. Will work in combination with <sysLibs>.
* The format is comma separated, colon-delimited values (name:type),
* like "dl:shared, pthread:shared".
*
* @parameter expression=""
*/
private String sysLibSet;
/**
* <p>
* Specifies the link ordering of libraries that come from nar dependencies. The format is
* a comma separated list of dependency names, given as groupId:artifactId.
* </p>
*
* <p>
* Example: <narDependencyLibOrder>someGroup:myProduct, other.group:productB<narDependencyLibOrder>
* </p>
*
* @parameter expression=""
*/
private String narDependencyLibOrder;
public Linker() {
// default constructor for use as TAG
}
/**
* For use with specific named linker.
*
* @param name
*/
public Linker(String name) {
this.name = name;
}
public String getName(Properties defaults, String prefix)
throws MojoFailureException {
if ((name == null) && (defaults != null) && (prefix != null)) {
name = defaults.getProperty(prefix + "linker");
}
if (name == null) {
throw new MojoFailureException(
"NAR: Please specify a <Name> as part of <Linker>");
}
return name;
}
public LinkerDef getLinker(AbstractCompileMojo mojo, Project antProject,
String os, String prefix, String type) throws MojoFailureException,
MojoExecutionException {
if (name == null) {
throw new MojoFailureException(
"NAR: Please specify a <Name> as part of <Linker>");
}
LinkerDef linker = new LinkerDef();
linker.setProject(antProject);
LinkerEnum linkerEnum = new LinkerEnum();
linkerEnum.setValue(name);
linker.setName(linkerEnum);
// incremental, map
linker.setIncremental(incremental);
linker.setMap(map);
// Add definitions (Window only)
if (os.equals(OS.WINDOWS)
&& (type.equals(Library.SHARED) || type.equals(Library.JNI))) {
Set defs = new HashSet();
try {
File cSrcDir = mojo.getC().getSourceDirectory();
if (cSrcDir.exists())
defs.addAll(FileUtils.getFiles(cSrcDir, "**/*.def", null));
} catch (IOException e) {
}
try {
File cppSrcDir = mojo.getCpp().getSourceDirectory();
if (cppSrcDir.exists())
defs
.addAll(FileUtils.getFiles(cppSrcDir, "**/*.def",
null));
} catch (IOException e) {
}
try {
File fortranSrcDir = mojo.getFortran().getSourceDirectory();
if (fortranSrcDir.exists())
defs.addAll(FileUtils.getFiles(fortranSrcDir, "**/*.def",
null));
} catch (IOException e) {
}
for (Iterator i = defs.iterator(); i.hasNext();) {
LinkerArgument arg = new LinkerArgument();
arg.setValue("/def:" + (File) i.next());
linker.addConfiguredLinkerArg(arg);
}
}
// Add options to linker
if (options != null) {
for (Iterator i = options.iterator(); i.hasNext();) {
LinkerArgument arg = new LinkerArgument();
arg.setValue((String) i.next());
linker.addConfiguredLinkerArg(arg);
}
}
if (optionSet != null) {
String[] opts = optionSet.split("\\s");
for (int i = 0; i < opts.length; i++) {
LinkerArgument arg = new LinkerArgument();
arg.setValue(opts[i]);
linker.addConfiguredLinkerArg(arg);
}
}
if (!clearDefaultOptions) {
String options = NarUtil.getDefaults().getProperty(
prefix + "options");
if (options != null) {
String[] option = options.split(" ");
for (int i = 0; i < option.length; i++) {
LinkerArgument arg = new LinkerArgument();
arg.setValue(option[i]);
linker.addConfiguredLinkerArg(arg);
}
}
}
// record the preference for nar dependency library link order
if (narDependencyLibOrder != null) {
List libOrder = new LinkedList();
String[] libs = narDependencyLibOrder.split(",");
for (int i = 0; i < libs.length; i++) {
libOrder.add(libs[i].trim());
}
mojo.setDependencyLibOrder(libOrder);
}
// Add Libraries to linker
if ((libs != null) || (libSet != null)) {
if (libs != null) {
for (Iterator i = libs.iterator(); i.hasNext();) {
Lib lib = (Lib) i.next();
lib.addLibSet(mojo, linker, antProject);
}
}
if (libSet != null) {
addLibraries(libSet, linker, antProject, false);
}
}
else {
String libsList = NarUtil.getDefaults()
.getProperty(prefix + "libs");
addLibraries(libsList, linker, antProject, false);
}
// Add System Libraries to linker
if ((sysLibs != null) || (sysLibSet != null)) {
if (sysLibs != null) {
for (Iterator i = sysLibs.iterator(); i.hasNext();) {
SysLib sysLib = (SysLib) i.next();
linker.addSyslibset(sysLib.getSysLibSet(antProject));
}
}
if (sysLibSet != null) {
addLibraries(sysLibSet, linker, antProject, true);
}
}
else {
String sysLibsList = NarUtil.getDefaults().getProperty(
prefix + "sysLibs");
addLibraries(sysLibsList, linker, antProject, true);
}
return linker;
}
private void addLibraries(String libraryList, LinkerDef linker, Project antProject, boolean isSystem) {
if (libraryList == null) {
return;
}
String[] lib = libraryList.split(",");
for (int i = 0; i < lib.length; i++) {
String[] libInfo = lib[i].trim().split(":", 3);
LibrarySet librarySet = new LibrarySet();
if (isSystem) {
librarySet = new SystemLibrarySet();
}
librarySet.setProject(antProject);
librarySet.setLibs(new CUtil.StringArrayBuilder(libInfo[0]));
if (libInfo.length > 1) {
LibraryTypeEnum libType = new LibraryTypeEnum();
libType.setValue(libInfo[1]);
librarySet.setType(libType);
if (!isSystem && (libInfo.length > 2)) {
librarySet.setDir(new File(libInfo[2]));
}
}
if (!isSystem) {
linker.addLibset(librarySet);
}
else {
linker.addSyslibset((SystemLibrarySet)librarySet);
}
}
}
}