/*
*
* Copyright 2001-2004 The Ant-Contrib project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.sf.antcontrib.cpptasks.types;
import java.io.File;
import net.sf.antcontrib.cpptasks.CUtil;
import net.sf.antcontrib.cpptasks.FileVisitor;
import net.sf.antcontrib.cpptasks.compiler.Linker;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.PatternSet;
/**
* A set of library names. Libraries can also be added to a link by specifying
* them in a fileset.
*
* For most Unix-like compilers, libset will result in a series of -l and -L
* linker arguments. For Windows compilers, the library names will be used to
* locate the appropriate library files which will be added to the linkers
* input file list as if they had been specified in a fileset.
*
* @author Mark A Russell mark_russell@csg_systems.com
*
* @author Adam Murdoch
* @author Curt Arnold
*/
public class LibrarySet extends ProjectComponent {
private String dataset;
private boolean explicitCaseSensitive;
private String ifCond;
private String[] libnames;
private final FileSet set = new FileSet();
private String unlessCond;
private LibraryTypeEnum libraryType;
public LibrarySet() {
libnames = new String[0];
}
public void execute() throws org.apache.tools.ant.BuildException {
throw new org.apache.tools.ant.BuildException(
"Not an actual task, but looks like one for documentation purposes");
}
/**
* Gets the dataset. Used on OS390 if the libs are in a dataset.
*
* @return Returns a String
*/
public String getDataset() {
return dataset;
}
public File getDir(Project project) {
return set.getDir(project);
}
protected FileSet getFileSet() {
return set;
}
public String[] getLibs() {
String[] retval = (String[]) libnames.clone();
return retval;
}
/**
* Gets preferred library type
*
* @return library type, may be null.
*/
public LibraryTypeEnum getType() {
return libraryType;
}
/**
* Returns true if the define's if and unless conditions (if any) are
* satisfied.
*/
public boolean isActive(org.apache.tools.ant.Project p) {
if (p == null) {
throw new NullPointerException("p");
}
if (ifCond != null) {
String ifValue = p.getProperty(ifCond);
if (ifValue != null) {
if (ifValue.equals("no") || ifValue.equals("false")) {
throw new BuildException(
"property "
+ ifCond
+ " used as if condition has value "
+ ifValue
+ " which suggests a misunderstanding of if attributes");
}
} else {
return false;
}
}
if (unlessCond != null) {
String unlessValue = p.getProperty(unlessCond);
if (unlessValue != null) {
if (unlessValue.equals("no") || unlessValue.equals("false")) {
throw new BuildException(
"property "
+ unlessCond
+ " used as unless condition has value "
+ unlessValue
+ " which suggests a misunderstanding of unless attributes");
}
return false;
}
}
if (libnames.length == 0) {
p.log("libnames not specified or empty.", Project.MSG_WARN);
return false;
}
return true;
}
/**
* Sets case sensitivity of the file system. If not set, will default to
* the linker's case sensitivity.
*
* @param isCaseSensitive
* "true"|"on"|"yes" if file system is case sensitive,
* "false"|"off"|"no" when not.
*/
public void setCaseSensitive(boolean isCaseSensitive) {
explicitCaseSensitive = true;
set.setCaseSensitive(isCaseSensitive);
}
/**
* Sets the dataset. Used on OS390 if the libs are in a dataset.
*
* @param dataset
* The dataset to set
*/
public void setDataset(String dataset) {
this.dataset = dataset;
}
/**
* Library directory.
*
* @param dir
* library directory
*
*/
public void setDir(File dir) throws BuildException {
set.setDir(dir);
}
/**
* Sets the property name for the 'if' condition.
*
* The library set will be ignored unless the property is defined.
*
* The value of the property is insignificant, but values that would imply
* misinterpretation ("false", "no") will throw an exception when
* evaluated.
*
* @param propName
* property name
*/
public void setIf(String propName) {
ifCond = propName;
}
/**
* Comma-separated list of library names without leading prefixes, such as
* "lib", or extensions, such as ".so" or ".a".
*
*/
public void setLibs(CUtil.StringArrayBuilder libs) throws BuildException {
libnames = libs.getValue();
// If this is not active.. then it's ok if the lib names are invalid.
// so we can do a:
if (!isActive(getProject()))
return;
for (int i = 0; i < libnames.length; i++) {
int lastDot = libnames[i].lastIndexOf('.');
if (lastDot >= 0) {
String extension = libnames[i].substring(lastDot);
if (extension.equalsIgnoreCase(".lib")
|| extension.equalsIgnoreCase(".so")
|| extension.equalsIgnoreCase(".a")) {
getProject().log(
"Suspicious library name ending with \""
+ extension + "\": " + libnames[i], Project.MSG_DEBUG );
}
}
if (libnames[i].length() >= 3
&& libnames[i].substring(0, 3).equalsIgnoreCase("lib")) {
getProject().log(
"Suspicious library name starting with \"lib\": "
+ libnames[i], Project.MSG_DEBUG);
}
}
}
public void setProject(Project project) {
set.setProject(project);
super.setProject(project);
}
/**
* Set the property name for the 'unless' condition.
*
* If named property is set, the library set will be ignored.
*
* The value of the property is insignificant, but values that would imply
* misinterpretation ("false", "no") of the behavior will throw an
* exception when evaluated.
*
* @param propName
* name of property
*/
public void setUnless(String propName) {
unlessCond = propName;
}
/**
* Sets the preferred library type. Supported values "shared", "static", and
* "framework". "framework" is equivalent to "shared" on non-Darwin platforms.
*/
public void setType(LibraryTypeEnum type) {
this.libraryType = type;
}
public void visitLibraries(Project project, Linker linker, File[] libpath,
FileVisitor visitor) throws BuildException {
FileSet localSet = (FileSet) set.clone();
//
// unless explicitly set
// will default to the linker case sensitivity
//
if (!explicitCaseSensitive) {
boolean linkerCaseSensitive = linker.isCaseSensitive();
localSet.setCaseSensitive(linkerCaseSensitive);
}
//
// if there was a libs attribute then
// add the corresponding patterns to the FileSet
//
if (libnames != null && libnames.length > 0) {
String[] patterns = linker.getLibraryPatterns(libnames, libraryType);
//
// if no patterns, then linker does not support libraries
//
if (patterns.length > 0) {
for (int i = 0; i < patterns.length; i++) {
PatternSet.NameEntry entry = localSet.createInclude();
entry.setName(patterns[i]);
}
//
// if there was no specified directory then
// run through the libpath backwards
//
if (localSet.getDir(project) == null) {
//
// scan libpath in reverse order
// to give earlier entries priority
//
for (int j = libpath.length - 1; j >= 0; j--) {
FileSet clone = (FileSet) localSet.clone();
clone.setDir(libpath[j]);
DirectoryScanner scanner = clone.getDirectoryScanner(project);
File basedir = scanner.getBasedir();
String[] files = scanner.getIncludedFiles();
for (int k = 0; k < files.length; k++) {
visitor.visit(basedir, files[k]);
}
}
} else {
DirectoryScanner scanner = localSet.getDirectoryScanner(project);
File basedir = scanner.getBasedir();
String[] files = scanner.getIncludedFiles();
for (int k = 0; k < files.length; k++) {
visitor.visit(basedir, files[k]);
}
}
}
}
}
}