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