// NAnt - A .NET build tool
// Copyright (C) 2001-2002 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// Shawn Van Ness (nantluver@arithex.com)
// Gerry Shaw (gerry_shaw@yahoo.com)
// Ian MacLean (ian@maclean.ms)
// Eric V. Smith (ericsmith@windsor.com)
//
// TODO: review interface for future compatibility/customizations issues
using System;
using System.IO;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using NAnt.Core.Types;
using NAnt.VisualCpp.Types;
using NAnt.VisualCpp.Util;
namespace NAnt.VisualCpp.Tasks {
///
/// Run lib.exe, Microsoft's Library Manager.
///
///
/// Create a library.
///
///
///
///
///
///
/// ]]>
///
///
[TaskName("lib")]
public class LibTask : ExternalProgramBase {
#region Private Instance Fields
private string _responseFileName;
private FileInfo _outputFile;
private FileInfo _moduleDefinitionFile;
private FileSet _sources = new FileSet();
private SymbolCollection _symbols = new SymbolCollection();
private LibraryCollection _ignoreLibraries = new LibraryCollection();
private FileSet _libdirs = new FileSet();
private string _options;
#endregion Private Instance Fields
#region Public Instance Properties
///
/// Options to pass to the compiler.
///
[TaskAttribute("options")]
public string Options {
get { return _options; }
set { _options = value; }
}
///
/// The output file.
///
[TaskAttribute("output", Required=true)]
public FileInfo OutputFile {
get { return _outputFile; }
set { _outputFile = value; }
}
///
/// The module definition file.
///
[TaskAttribute("moduledefinition")]
public FileInfo ModuleDefinitionFile {
get { return _moduleDefinitionFile; }
set { _moduleDefinitionFile = value; }
}
///
/// The list of files to combine into the output file.
///
[BuildElement("sources")]
public FileSet Sources {
get { return _sources; }
set { _sources = value; }
}
///
/// Symbols to add to the symbol table.
///
[BuildElementCollection("symbols", "symbol")]
public SymbolCollection Symbols {
get { return _symbols; }
set { _symbols = value; }
}
///
/// Names of default libraries to ignore.
///
[BuildElementCollection("ignorelibraries", "library")]
public LibraryCollection IgnoreLibraries {
get { return _ignoreLibraries; }
set { _ignoreLibraries = value; }
}
///
/// The list of additional library directories to search.
///
[BuildElement("libdirs")]
public FileSet LibDirs {
get { return _libdirs; }
set { _libdirs = value; }
}
#endregion Public Instance Properties
#region Override implementation of ExternalProgramBase
///
/// Gets the filename of the external program to start.
///
/// The filename of the external program.
public override string ProgramFileName {
get { return Name; }
}
///
/// Gets the command-line arguments for the external program.
///
///
/// The command-line arguments for the external program.
///
public override string ProgramArguments {
get { return "@" + "\"" + _responseFileName + "\""; }
}
#endregion Override implementation of ExternalProgramBase
#region Override implementation of Task
///
/// Creates the library.
///
protected override void ExecuteTask() {
// ensure base directory is set, even if fileset was not initialized
// from XML
if (Sources.BaseDirectory == null) {
Sources.BaseDirectory = new DirectoryInfo(Project.BaseDirectory);
}
if (LibDirs.BaseDirectory == null) {
LibDirs.BaseDirectory = new DirectoryInfo(Project.BaseDirectory);
}
if (!NeedsCompiling()) {
return;
}
Log(Level.Info, "Combining {0} files to '{1}'.",
Sources.FileNames.Count, OutputFile.FullName);
// Create temp response file to hold compiler options
_responseFileName = Path.GetTempFileName();
StreamWriter writer = new StreamWriter(_responseFileName);
try {
// specify the output file
writer.WriteLine("/OUT:\"{0}\"", OutputFile.FullName);
// write user provided options
if (Options != null) {
writer.WriteLine(Options);
}
// write each of the filenames
foreach (string filename in Sources.FileNames) {
writer.WriteLine(ArgumentUtils.QuoteArgumentValue(filename,
BackslashProcessingMethod.None));
}
// write symbols
foreach (Symbol symbol in Symbols) {
if (symbol.IfDefined && !symbol.UnlessDefined) {
writer.WriteLine("/INCLUDE:{0}", ArgumentUtils.QuoteArgumentValue(
symbol.SymbolName, BackslashProcessingMethod.Duplicate));
}
}
// names of default libraries to ignore
foreach (Library ignoreLibrary in IgnoreLibraries) {
if (ignoreLibrary.IfDefined && !ignoreLibrary.UnlessDefined) {
writer.WriteLine("/NODEFAULTLIB:{0}", ArgumentUtils.QuoteArgumentValue(
ignoreLibrary.LibraryName, BackslashProcessingMethod.Duplicate));
}
}
// write each of the libdirs
foreach (string libdir in LibDirs.DirectoryNames) {
writer.WriteLine("/LIBPATH:{0}", ArgumentUtils.QuoteArgumentValue(
libdir, BackslashProcessingMethod.None));
}
if (ModuleDefinitionFile != null) {
writer.WriteLine("/DEF:\"{0}\"", ModuleDefinitionFile.FullName);
}
// suppresses display of the sign-on banner
writer.WriteLine("/nologo");
writer.Close();
if (Verbose) {
// display response file contents
Log(Level.Info, "Contents of {0}.", _responseFileName);
StreamReader reader = File.OpenText(_responseFileName);
Log(Level.Info, reader.ReadToEnd());
reader.Close();
}
// call base class to do the actual work
base.ExecuteTask();
} finally {
// make sure we delete response file even if an exception is thrown
writer.Close(); // make sure stream is closed or file cannot be deleted
File.Delete(_responseFileName);
_responseFileName = null;
}
}
#endregion Override implementation of Task
#region Protected Instance Methods
///
/// Determines if the sources need to be linked.
///
protected virtual bool NeedsCompiling() {
// check if output file exists - if not, rebuild
if (!OutputFile.Exists) {
Log(Level.Verbose, "Output file '{0}' does not exist, rebuilding library.",
OutputFile.FullName);
return true;
}
// check if .OBJ files were updated
string fileName = FileSet.FindMoreRecentLastWriteTime(
Sources.FileNames, OutputFile.LastWriteTime);
if (fileName != null) {
Log(Level.Verbose, "'{0}' has been updated, relinking.", fileName);
return true;
}
return false;
}
#endregion Protected Instance Methods
}
}
#if unused
Microsoft (R) Library Manager Version 7.00.9466
Copyright (C) Microsoft Corporation. All rights reserved.
usage: LIB [options] [files]
options:
/DEF[:filename]
/EXPORT:symbol
/EXTRACT:membername
/INCLUDE:symbol
/LIBPATH:dir
/LIST[:filename]
/MACHINE:{AM33|ARM|IA64|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|
PPC|PPCFP|SH3|SH3DSP|SH4|SH5|THUMB|TRICORE|X86}
/NAME:filename
/NODEFAULTLIB[:library]
/NOLOGO
/OUT:filename
/REMOVE:membername
/SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|
EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|
WINDOWSCE}[,#[.##]]
/VERBOSE
#endif