// 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
//
// Gerry Shaw (gerry_shaw@yahoo.com)
// Mike Krueger (mike@icsharpcode.net)
// Gert Driesen (gert.driesen@ardatis.com)
// Ian MacLean (ian_maclean@another.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 C# 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 "Default Namespace" of the C# project, and the
/// value of the attribute
/// should be set to "".
///
///
///
/// Compile a "HelloWorld" application, including embedded resources.
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
/// ]]>
///
///
[TaskName("csc")]
[ProgramLocation(LocationType.FrameworkDir)]
public class CscTask : CompilerBase {
#region Private Instance Fields
private DebugOutput _debugOutput = DebugOutput.None;
private FileInfo _docFile;
private int _fileAlign;
private bool _nostdlib;
private bool _noconfig;
private bool _checked;
private bool _unsafe;
private bool _optimize;
private string _warningLevel;
private string _codepage;
private string _baseAddress;
private string _platform;
private string _langVersion;
// framework configuration settings
private bool _supportsDocGeneration = true;
private bool _supportsPlatform;
private bool _supportsLangVersion;
#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 can be specified as a decimal, hexadecimal, or octal
/// 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.
///
///
///
/// Corresponds with the /doc: flag.
///
///
[TaskAttribute("doc")]
public FileInfo DocFile {
get { return _docFile; }
set { _docFile = value; }
}
///
/// Specifies the size of sections in the output file. Valid values are
/// 512, 1024, 2048, 4096, and 8192.
///
///
/// The size of sections in the output file.
///
[TaskAttribute("filealign")]
[Int32Validator(512, 8192)]
public int FileAlign {
get { return _fileAlign; }
set { _fileAlign = value; }
}
///
/// Instructs the compiler not to import mscorlib.dll. The default is
/// .
///
///
///
/// Corresponds with the /nostdlib[+|-] flag.
///
///
[FrameworkConfigurable("nostdlib")]
[TaskAttribute("nostdlib")]
[BooleanValidator()]
public bool NoStdLib {
get { return _nostdlib; }
set { _nostdlib = value; }
}
///
/// Instructs the compiler not to use implicit references to assemblies.
/// The default is .
///
///
///
/// Corresponds with the /noconfig flag.
///
///
[FrameworkConfigurable("noconfig")]
[TaskAttribute("noconfig")]
[BooleanValidator()]
public bool NoConfig {
get { return _noconfig; }
set { _noconfig = value; }
}
///
/// Specifies whether an integer arithmetic statement that is not in
/// the scope of the checked or unchecked keywords and
/// that results in a value outside the range of the data type should
/// cause a run-time exception. The default is .
///
///
///
/// Corresponds with the /checked[+|-] flag.
///
///
[TaskAttribute("checked")]
[BooleanValidator()]
public bool Checked {
get { return _checked; }
set { _checked = value; }
}
///
/// Instructs the compiler to allow code that uses the unsafe
/// keyword. The default is .
///
///
///
/// Corresponds with the /unsafe[+|-] flag.
///
///
[TaskAttribute("unsafe")]
[BooleanValidator()]
public bool Unsafe {
get { return _unsafe; }
set { _unsafe = value; }
}
///
/// Causes the compiler to only accept syntax that is included in a
/// given specification.
///
///
///
/// Corresponds with the /langversion flag.
///
///
[TaskAttribute("langversion")]
public string LangVersion {
get { return _langVersion; }
set { _langVersion = StringUtils.ConvertEmptyToNull(value); }
}
///
/// Specifies whether the compiler should perform optimizations to the
/// make output files smaller, faster, and more effecient. The default
/// is .
///
///
/// if the compiler should perform optimizations;
/// otherwise, .
///
///
///
/// Corresponds with the /optimize[+|-] flag.
///
///
[TaskAttribute("optimize")]
[BooleanValidator()]
public bool Optimize {
get { return _optimize; }
set { _optimize = 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 the warning level for the compiler to display. Valid values
/// are 0-4. The default is 4.
///
///
/// The warning level for the compiler to display.
///
///
///
/// Corresponds with the /warn flag.
///
///
[TaskAttribute("warninglevel")]
[Int32Validator(0, 4)]
public string WarningLevel {
get { return _warningLevel; }
set { _warningLevel = StringUtils.ConvertEmptyToNull(value); }
}
///
/// Specifies the code page to use for all source code files in the
/// compilation.
///
///
///
/// Corresponds with the /codepage flag.
///
///
[TaskAttribute("codepage")]
public string Codepage {
get { return _codepage; }
set { _codepage = 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 limiting the platform on which the compiled code can run.
/// The default is .
///
[FrameworkConfigurable("supportsplatform")]
public bool SupportsPlatform {
get { return _supportsPlatform; }
set { _supportsPlatform = value; }
}
///
/// Specifies whether the compiler for the active target framework
/// supports accepting only a specific language syntax.
/// The default is .
///
[FrameworkConfigurable("supportslangversion")]
public bool SupportsLangVersion {
get { return _supportsLangVersion; }
set { _supportsLangVersion = value; }
}
#endregion Public Instance Properties
#region Override implementation of CompilerBase
///
/// Writes the compiler options to the specified .
///
/// to which the compiler options should be written.
protected override void WriteOptions(TextWriter writer) {
// causes the compiler to specify the full path of the file in which
// an error was found
WriteOption(writer, "fullpaths");
// 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);
}
}
// langversion
if (LangVersion != null) {
if (SupportsLangVersion) {
WriteOption(writer, "langversion", LangVersion);
} else {
Log(Level.Warning, ResourceUtils.GetString("String_CompilerDoesNotSupportLangVersion"),
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");
WriteOption(writer, "define", "TRACE");
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);
}
if (FileAlign > 0) {
WriteOption(writer, "filealign", FileAlign.ToString(CultureInfo.InvariantCulture));
}
if (NoStdLib) {
WriteOption(writer, "nostdlib");
}
if (Checked) {
WriteOption(writer, "checked");
}
if (Unsafe) {
WriteOption(writer, "unsafe");
}
if (Optimize) {
WriteOption(writer, "optimize");
}
if (WarningLevel != null) {
WriteOption(writer, "warn", WarningLevel);
}
if (Codepage != null) {
WriteOption(writer, "codepage", Codepage);
}
if (NoConfig && !Arguments.Contains("/noconfig")) {
Arguments.Add(new Argument("/noconfig"));
}
}
///
/// 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 C# compiler, the file extension is always cs.
///
public override string Extension {
get { return "cs"; }
}
///
/// 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
}
}