protected override void ExecuteTask()
{
// create compiler info for user-specified language
CompilerInfo compilerInfo = CreateCompilerInfo(Language);
// ensure base directory is set, even if fileset was not initialized
// from XML
if (References.BaseDirectory == null) {
References.BaseDirectory = new DirectoryInfo(Project.BaseDirectory);
}
ICodeCompiler compiler = compilerInfo.Compiler;
CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = false;
options.GenerateInMemory = true;
options.MainClass = MainClass;
// implicitly reference the NAnt.Core assembly
options.ReferencedAssemblies.Add (typeof (Project).Assembly.Location);
// Log the assembly being added to the CompilerParameters
Log(Level.Verbose, "Adding assembly {0}", typeof (Project).Assembly.GetName().Name);
// add (and load) assemblies specified by user
foreach (string assemblyFile in References.FileNames) {
try {
// load the assembly into current AppDomain to ensure it is
// available when executing the emitted assembly
Assembly asm = Assembly.LoadFrom(assemblyFile);
// Log the assembly being added to the CompilerParameters
Log(Level.Verbose, "Adding assembly {0}", asm.GetName().Name);
// add the location of the loaded assembly
if (!StringUtils.IsNullOrEmpty(asm.Location)) {
options.ReferencedAssemblies.Add(asm.Location);
}
} catch (Exception ex) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA2028"), assemblyFile), Location, ex);
}
}
StringCollection imports = new StringCollection();
foreach (NamespaceImport import in Imports) {
if (import.IfDefined && !import.UnlessDefined) {
imports.Add(import.Namespace);
}
}
// generate the code
CodeCompileUnit compileUnit = compilerInfo.GenerateCode(_rootClassName,
Code.Xml.InnerText, imports, Prefix);
StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
compilerInfo.CodeGen.GenerateCodeFromCompileUnit(compileUnit, sw, null);
string code = sw.ToString();
Log(Level.Debug, ResourceUtils.GetString("String_GeneratedCodeLooksLike") + "\n{0}", code);
CompilerResults results = compiler.CompileAssemblyFromDom(options, compileUnit);
Assembly compiled = null;
if (results.Errors.Count > 0) {
string errors = ResourceUtils.GetString("NA2029") + Environment.NewLine;
foreach (CompilerError err in results.Errors) {
errors += err.ToString() + Environment.NewLine;
}
errors += code;
throw new BuildException(errors, Location);
} else {
compiled = results.CompiledAssembly;
}
// scan the new assembly for tasks, types and functions
// Its unlikely that tasks will be defined in buildfiles though.
bool extensionAssembly = TypeFactory.ScanAssembly(compiled, this);
string mainClass = _rootClassName;
if (!StringUtils.IsNullOrEmpty(MainClass)) {
mainClass += "+" + MainClass;
}
Type mainType = compiled.GetType(mainClass);
if (mainType == null) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA2030"), mainClass), Location);
}
MethodInfo entry = mainType.GetMethod("ScriptMain");
// check for task or function definitions.
if (entry == null) {
if (!extensionAssembly) {
throw new BuildException(ResourceUtils.GetString("NA2031"), Location);
} else {
return; // no entry point so nothing to do here beyond loading task and function defs
}
}
if (!entry.IsStatic) {
throw new BuildException(ResourceUtils.GetString("NA2032"), Location);
}
ParameterInfo[] entryParams = entry.GetParameters();
if (entryParams.Length != 1) {
throw new BuildException(ResourceUtils.GetString("NA2033"), Location);
}
if (entryParams[0].ParameterType.FullName != typeof(Project).FullName) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA2034"), entryParams[0].ParameterType.FullName,
typeof(Project).FullName), Location);
}
try {
// invoke Main method
entry.Invoke(null, new object[] {Project});
} catch (Exception ex) {
// this exception is not likely to tell us much, BUT the
// InnerException normally contains the runtime exception
// thrown by the executed script code.
throw new BuildException(ResourceUtils.GetString("NA2035"), Location,
ex.InnerException);
}
}