// 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)
// Scott Hernandez (ScottHernandez@hotmail.com)
using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.Xml;
using NAnt.Core.Attributes;
using NAnt.Core.Util;
using NAnt.Core.Types;
namespace NAnt.Core.Tasks {
///
/// Runs NAnt on a supplied build file, or a set of build files.
///
///
///
/// By default, all the properties of the current project will be available
/// in the new project. Alternatively, you can set
/// to to not copy any properties to the new
/// project.
///
///
/// You can also set properties in the new project from the old project by
/// using nested property tags. These properties are always passed to the
/// new project regardless of the setting of .
/// This allows you to parameterize your subprojects.
///
///
/// References to data types can also be passed to the new project, but by
/// default they are not. If you set the to
/// , all references will be copied.
///
///
///
///
/// Build a project located in a different directory if the debug
/// property is not .
///
///
///
/// ]]>
///
///
///
///
/// Build a project while adding a set of properties to that project.
///
///
///
///
///
///
///
///
///
/// ]]>
///
///
///
///
/// Build all projects named default.build located anywhere under
/// the project base directory.
///
///
///
///
///
///
///
///
///
/// ]]>
///
///
[TaskName("nant")]
public class NAntTask : Task {
#region Private Instance Fields
private FileInfo _buildFile;
private FileSet _buildFiles = new FileSet();
private string _target;
private bool _inheritAll = true;
private bool _inheritRefs = false;
private ArrayList _overrideProperties = new ArrayList();
#endregion Private Instance Fields
#region Public Instance Properties
///
/// The build file to build.
///
[TaskAttribute("buildfile")]
public FileInfo BuildFile {
get { return _buildFile; }
set { _buildFile = value; }
}
///
/// The target to execute. To specify more than one target seperate
/// targets with a space. Targets are executed in order if possible.
/// The default is to use target specified in the project's default
/// attribute.
///
[TaskAttribute("target")]
public string DefaultTarget {
get { return _target; }
set { _target = StringUtils.ConvertEmptyToNull(value); }
}
///
/// Used to specify a set of build files to process.
///
[BuildElement("buildfiles")]
public virtual FileSet BuildFiles {
get { return _buildFiles; }
set { _buildFiles = value; }
}
///
/// Specifies whether current property values should be inherited by
/// the executed project. The default is .
///
[TaskAttribute("inheritall")]
[BooleanValidator()]
public bool InheritAll {
get { return _inheritAll; }
set { _inheritAll = value; }
}
///
/// Specifies whether all references will be copied to the new project.
/// The default is .
///
[TaskAttribute("inheritrefs")]
[BooleanValidator()]
public bool InheritRefs {
get { return _inheritRefs; }
set { _inheritRefs = value; }
}
///
/// Specifies a collection of properties that should be created in the
/// executed project. Note, existing properties with identical names
/// that are not read-only will be overwritten.
///
[BuildElementCollection("properties", "property", ElementType=typeof(PropertyTask))]
public ArrayList OverrideProperties {
get { return _overrideProperties; }
}
#endregion Public Instance Properties
#region Override implementation of Task
///
/// Validates the element.
///
/// The XML node of the task to use for initialization.
protected override void InitializeTask(XmlNode taskNode) {
if (BuildFile != null && BuildFiles != null && BuildFiles.Includes.Count > 0) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1141")), Location);
}
}
protected override void ExecuteTask() {
// run the build file specified in an attribute
if (BuildFile != null) {
RunBuild(BuildFile);
} else {
if (BuildFiles.FileNames.Count == 0) {
Log(Level.Warning, "No matching build files found to run.");
return;
}
// run all build files specified in the fileset
foreach (string buildFile in BuildFiles.FileNames) {
RunBuild(new FileInfo(buildFile));
}
}
}
private void RunBuild(FileInfo buildFile) {
Log(Level.Info, "{0} {1}", buildFile.FullName, DefaultTarget);
// create new project with same threshold as current project and
// increased indentation level, and initialize it using the same
// configuration node
Project project = new Project(buildFile.FullName, Project);
// have the new project inherit properties from the current project
if (InheritAll) {
StringCollection excludes = new StringCollection();
excludes.Add(Project.NAntPropertyFileName);
excludes.Add(Project.NAntPropertyLocation);
excludes.Add(Project.NAntPropertyOnSuccess);
excludes.Add(Project.NAntPropertyOnFailure);
excludes.Add(Project.NAntPropertyProjectBaseDir);
excludes.Add(Project.NAntPropertyProjectBuildFile);
excludes.Add(Project.NAntPropertyProjectDefault);
excludes.Add(Project.NAntPropertyProjectName);
excludes.Add(Project.NAntPropertyVersion);
project.Properties.Inherit(Properties, excludes);
}
// add/overwrite properties
foreach (PropertyTask property in OverrideProperties) {
// expand properties in context of current project for non-dynamic
// properties
if (!property.Dynamic) {
property.Value = Project.ExpandProperties(property.Value, Location);
}
property.Project = project;
property.Execute();
}
if (InheritRefs) {
// pass datatypes thru to the child project
project.DataTypeReferences.Inherit(Project.DataTypeReferences);
}
// handle multiple targets
if (DefaultTarget != null) {
foreach (string t in DefaultTarget.Split(' ')) {
string target = t.Trim();
if (target.Length > 0) {
project.BuildTargets.Add(target);
}
}
}
// run the given build
if (!project.Run()) {
throw new BuildException("Nested build failed. Refer to build log for exact reason.");
}
}
#endregion Override implementation of Task
}
}