// 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 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 // // Gerry Shaw (gerry_shaw@yahoo.com) // Gert Driesen (gert.driesen@ardatis.com) // Mike Krueger (mike@icsharpcode.net) // Aaron A. Anderson (aaron@skypoint.com | aaron.anderson@farmcreditbank.com) // Giuseppe Greco (giuseppe.greco@agamura.com) using System; using System.Globalization; using System.IO; using System.Text.RegularExpressions; using NAnt.Core; using NAnt.Core.Attributes; using NAnt.Core.Types; using NAnt.Core.Util; using NAnt.DotNet.Types; namespace NAnt.DotNet.Tasks { /// /// Compiles Visual Basic.NET programs. /// /// /// /// In order to have generate manifest resource names /// that match those generated by Microsoft Visual Studio.NET, the value of /// the attribute of the <> /// element should match the "Root namespace" of the VB.NET project, and the /// value of the attribute /// should be set to "". /// /// /// /// Example build file using this task. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ]]> /// /// [TaskName("vbc")] [ProgramLocation(LocationType.FrameworkDir)] public class VbcTask : CompilerBase { #region Private Instance Fields private string _baseAddress; private DebugOutput _debugOutput = DebugOutput.None; private FileInfo _docFile; private bool _nostdlib; private string _optionCompare; private bool _optionExplicit; private bool _optionStrict; private bool _optionOptimize; private bool _removeintchecks; private string _rootNamespace; private string _platform; private NamespaceImportCollection _imports = new NamespaceImportCollection(); // framework configuration settings private bool _supportsDocGeneration; private bool _supportsNoStdLib; private bool _supportsPlatform; #endregion Private Instance Fields #region Private Static Fields private static Regex _classNameRegex = new Regex(@"^((?/\*.*?(\*/|$))|[\s\.]+|Class\s+(?\w+)|(?\w+))*"); private static Regex _namespaceRegex = new Regex(@"^((?/\*.*?(\*/|$))|[\s\.]+|Namespace\s+(?(\w+(\.\w+)*)+)|(?\w+))*"); #endregion Private Static Fields #region Public Instance Properties /// /// The preferred base address at which to load a DLL. The default base /// address for a DLL is set by the .NET Framework common language /// runtime. /// /// /// The preferred base address at which to load a DLL. /// /// /// This address must be specified as a hexadecimal number. /// [TaskAttribute("baseaddress")] public string BaseAddress { get { return _baseAddress; } set { _baseAddress = StringUtils.ConvertEmptyToNull(value); } } /// /// Specifies the type of debugging information generated by the /// compiler. The default is . /// [TaskAttribute("debug")] public DebugOutput DebugOutput { get { return _debugOutput; } set { _debugOutput = value; } } /// /// No longer expose this to build authors. Use /// instead. /// public override bool Debug { get { return DebugOutput != DebugOutput.None; } set { DebugOutput = DebugOutput.Enable; } } /// /// The name of the XML documentation file to generate. Only supported /// when targeting .NET 2.0 (or higher). /// /// /// /// Corresponds with the /doc: flag. /// /// [TaskAttribute("doc")] public FileInfo DocFile { get { return _docFile; } set { _docFile = value; } } /// /// Specifies whether the /imports option gets passed to the /// compiler. /// /// /// The value of this attribute is a string that contains one or more /// namespaces separated by commas. /// /// /// See the Microsoft.NET Framework SDK documentation for details. /// /// Example of an imports attribute /// /// [TaskAttribute("imports")] [Obsolete("Use the element instead.", false)] public string ImportsString { set { if (!StringUtils.IsNullOrEmpty(value)) { string[] imports = value.Split(','); foreach (string import in imports) { Imports.Add(new NamespaceImport(import)); } } } } /// /// The namespaces to import. /// [BuildElement("imports")] public NamespaceImportCollection Imports { get { return _imports; } set { _imports = value; } } /// /// Instructs the compiler not to reference standard libraries /// (system.dll and VBC.RSP). The default is . /// Only supported when targeting .NET 2.0 (or higher). /// /// /// /// Corresponds with the /nostdlib flag. /// /// [FrameworkConfigurable("nostdlib")] [TaskAttribute("nostdlib")] [BooleanValidator()] public bool NoStdLib { get { return _nostdlib; } set { _nostdlib = value; } } /// /// Specifies whether /optioncompare option gets passed to the /// compiler. /// /// /// text, binary, or an empty string. If the value is /// or an empty string, the option will not be /// passed to the compiler. /// /// See the Microsoft.NET Framework SDK documentation for details. [TaskAttribute("optioncompare")] public string OptionCompare { get { return _optionCompare; } set { _optionCompare = StringUtils.ConvertEmptyToNull(value); } } /// /// Specifies whether the /optionexplicit option gets passed to /// the compiler. The default is . /// /// /// if the option should be passed to the compiler; /// otherwise, . /// /// See the Microsoft.NET Framework SDK documentation for details. [TaskAttribute("optionexplicit")] [BooleanValidator()] public bool OptionExplicit { get { return _optionExplicit; } set { _optionExplicit = value; } } /// /// Specifies whether the /optimize option gets passed to the /// compiler. The default is . /// /// /// if the option should be passed to the compiler; /// otherwise, . /// /// See the Microsoft.NET Framework SDK documentation for details. [TaskAttribute("optionoptimize")] [BooleanValidator()] public bool OptionOptimize { get { return _optionOptimize; } set { _optionOptimize = value; } } /// /// Specifies whether the /optionstrict option gets passed to /// the compiler. The default is . /// /// /// if the option should be passed to the compiler; /// otherwise, . /// /// See the Microsoft.NET Framework SDK documentation for details. [TaskAttribute("optionstrict")] [BooleanValidator()] public bool OptionStrict { get { return _optionStrict; } set { _optionStrict = value; } } /// /// Specifies which platform version of common language runtime (CLR) /// can run the output file. /// /// /// The platform version of common language runtime (CLR) that can run /// the output file. /// /// /// /// Corresponds with the /platform flag. /// /// [TaskAttribute("platform")] public string Platform { get { return _platform; } set { _platform = StringUtils.ConvertEmptyToNull(value); } } /// /// Specifies whether the /removeintchecks option gets passed to /// the compiler. The default is . /// /// /// if the option should be passed to the compiler; /// otherwise, . /// /// See the Microsoft.NET Framework SDK documentation for details. [TaskAttribute("removeintchecks")] [BooleanValidator()] public bool RemoveIntChecks { get { return _removeintchecks; } set { _removeintchecks = value; } } /// /// Specifies whether the /rootnamespace option gets passed to /// the compiler. /// /// /// The value of this attribute is a string that contains the root /// namespace of the project. /// /// See the Microsoft.NET Framework SDK documentation for details. [TaskAttribute("rootnamespace")] public string RootNamespace { get { return _rootNamespace; } set { _rootNamespace = StringUtils.ConvertEmptyToNull(value); } } /// /// Specifies whether the compiler for the active target framework /// supports generation of XML Documentation file. The default is /// . /// [FrameworkConfigurable("supportsdocgeneration")] public bool SupportsDocGeneration { get { return _supportsDocGeneration; } set { _supportsDocGeneration = value; } } /// /// Specifies whether the compiler for the active target framework /// supports NOT referencing standard libraries (system.dll and VBC.RSP). /// The default is . /// [FrameworkConfigurable("supportsnostdlib")] public bool SupportsNoStdLib { get { return _supportsNoStdLib; } set { _supportsNoStdLib = value; } } /// /// Specifies whether the compiler for the active target framework /// supports limiting the platform on which the compiled code can run. /// The default is . /// [FrameworkConfigurable("supportsplatform")] public bool SupportsPlatform { get { return _supportsPlatform; } set { _supportsPlatform = value; } } #endregion Public Instance Properties #region Override implementation of CompilerBase /// /// Finds the correct namespace/classname for a resource file from the /// given dependent source file, and ensure the /// is prefixed. /// /// The file from which the resource linkage of the resource file should be determined. /// The culture of the resource file for which the resource linkage should be determined. /// /// The namespace/classname of the source file matching the resource or /// if the dependent source file does not exist. /// protected override ResourceLinkage GetResourceLinkage(string dependentFile, CultureInfo resourceCulture) { // determine resource linkage from dependent file ResourceLinkage resourceLinkage = base.GetResourceLinkage(dependentFile, resourceCulture); // check if resource linkage could be determined at all if (resourceLinkage != null) { // for VB.NET, the root namespace always needs to be used if (!StringUtils.IsNullOrEmpty(RootNamespace)) { if (resourceLinkage.HasNamespaceName) { resourceLinkage.NamespaceName = RootNamespace + "." + resourceLinkage.NamespaceName; } else { resourceLinkage.NamespaceName = RootNamespace; } } } return resourceLinkage; } /// /// Writes conditional compilation constants to the specified /// . /// /// The to which the conditional compilation constants should be written. protected override void WriteConditionalCompilationConstants(TextWriter writer) { if (Define != null) { string[] constants = Define.Split(','); foreach (string constant in constants) { WriteOption(writer, "define", constant); } } } /// /// Writes the compiler options to the specified . /// /// to which the compiler options should be written. protected override void WriteOptions(TextWriter writer) { // the base address for the DLL if (BaseAddress != null) { WriteOption(writer, "baseaddress", BaseAddress); } // XML documentation if (DocFile != null) { if (SupportsDocGeneration) { WriteOption(writer, "doc", DocFile.FullName); } else { Log(Level.Warning, ResourceUtils.GetString("String_CompilerDoesNotSupportXmlDoc"), Project.TargetFramework.Description); } } if (NoStdLib) { if (SupportsNoStdLib) { WriteOption(writer, "nostdlib"); } else { Log(Level.Warning, ResourceUtils.GetString("String_CompilerDoesNotSupportNoStdLib"), Project.TargetFramework.Description); } } // platform if (Platform != null) { if (SupportsPlatform) { WriteOption(writer, "platform", Platform); } else { Log(Level.Warning, ResourceUtils.GetString("String_CompilerDoesNotSupportPlatform"), Project.TargetFramework.Description); } } // handle debug builds. switch (DebugOutput) { case DebugOutput.None: break; case DebugOutput.Enable: WriteOption(writer, "debug"); WriteOption(writer, "define", "DEBUG=True"); WriteOption(writer, "define", "TRACE=True"); break; case DebugOutput.Full: WriteOption(writer, "debug"); break; case DebugOutput.PdbOnly: WriteOption(writer, "debug", "pdbonly"); break; default: throw new BuildException(string.Format(CultureInfo.InvariantCulture, ResourceUtils.GetString("NA2011"), DebugOutput), Location); } string imports = Imports.ToString(); if (!StringUtils.IsNullOrEmpty(imports)) { WriteOption(writer, "imports", imports); } if (OptionCompare != null && OptionCompare.ToUpper(CultureInfo.InvariantCulture) != "FALSE") { WriteOption(writer, "optioncompare", OptionCompare); } if (OptionExplicit) { WriteOption(writer, "optionexplicit"); } if (OptionStrict) { WriteOption(writer, "optionstrict"); } if (RemoveIntChecks) { WriteOption(writer, "removeintchecks"); } if (OptionOptimize) { WriteOption(writer, "optimize"); } if (RootNamespace != null) { WriteOption(writer, "rootnamespace", RootNamespace); } if (Project.TargetFramework.Family == "netcf") { WriteOption(writer, "netcf"); WriteOption(writer, "sdkpath", Project.TargetFramework. FrameworkAssemblyDirectory.FullName); } } /// /// Determines whether compilation is needed. /// protected override bool NeedsCompiling() { if (DocFile != null && SupportsDocGeneration) { if (!DocFile.Exists) { Log(Level.Verbose, ResourceUtils.GetString("String_DocFileDoesNotExist"), DocFile.FullName); return true; } } return base.NeedsCompiling(); } /// /// Gets the file extension required by the current compiler. /// /// /// For the VB.NET compiler, the file extension is always vb. /// public override string Extension { get { return "vb"; } } /// /// Gets the class name regular expression for the language of the /// current compiler. /// /// /// Class name regular expression for the language of the current /// compiler. /// protected override Regex ClassNameRegex { get { return _classNameRegex; } } /// /// Gets the namespace regular expression for the language of the /// current compiler. /// /// /// Namespace regular expression for the language of the current /// compiler. /// protected override Regex NamespaceRegex { get { return _namespaceRegex; } } #endregion Override implementation of CompilerBase } }