// 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