1 // NAnt - A .NET build tool
\r
2 // Copyright (C) 2001 Gerry Shaw
\r
4 // This program is free software; you can redistribute it and/or modify
\r
5 // it under the terms of the GNU General Public License as published by
\r
6 // the Free Software Foundation; either version 2 of the License, or
\r
7 // (at your option) any later version.
\r
9 // This program is distributed in the hope that it will be useful,
\r
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 // GNU General Public License for more details.
\r
14 // You should have received a copy of the GNU General Public License
\r
15 // along with this program; if not, write to the Free Software
\r
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
18 // Gerry Shaw (gerry_shaw@yahoo.com)
\r
19 // Mike Krueger (mike@icsharpcode.net)
\r
21 namespace SourceForge.NAnt {
\r
24 using System.Collections.Specialized;
\r
25 using System.Diagnostics;
\r
28 public abstract class CompilerBase : ExternalProgramBase {
\r
30 string _responseFileName;
\r
32 // Microsoft common compiler options
\r
33 [TaskAttribute("output", Required=true)]
\r
34 string _output = null;
\r
36 [TaskAttribute("target", Required=true)]
\r
37 string _target = null;
\r
39 [TaskAttribute("debug")]
\r
40 [BooleanValidator()]
\r
41 string _debug = Boolean.FalseString;
\r
43 [TaskAttribute("define")]
\r
44 string _define = null;
\r
46 [TaskAttribute("win32icon")]
\r
47 string _win32icon = null;
\r
49 [TaskFileSet("references")]
\r
50 FileSet _references = new FileSet(false);
\r
52 [TaskFileSet("resources")]
\r
53 FileSet _resources = new FileSet(false);
\r
55 [TaskFileSet("modules")]
\r
56 FileSet _modules = new FileSet(false);
\r
58 [TaskFileSet("sources")]
\r
59 FileSet _sources = new FileSet(true); // include all by default
\r
61 public string Output { get { return _output; } }
\r
62 public string OutputTarget { get { return _target; } }
\r
63 public bool Debug { get { return Convert.ToBoolean(_debug); } }
\r
64 public string Define { get { return _define; } }
\r
65 public string Win32Icon { get { return _win32icon; } }
\r
66 public FileSet References { get { return _references; } }
\r
67 public FileSet Resources { get { return _resources; } }
\r
68 public FileSet Modules { get { return _modules; } }
\r
69 public FileSet Sources { get { return _sources; } }
\r
71 public override string ProgramFileName { get { return Name; } }
\r
72 public override string ProgramArguments { get { return "@" + _responseFileName; } }
\r
74 protected virtual void WriteOptions(TextWriter writer) {
\r
77 protected virtual void WriteOption(TextWriter writer, string name) {
\r
78 writer.WriteLine("/{0}", name);
\r
81 protected virtual void WriteOption(TextWriter writer, string name, string arg) {
\r
82 writer.WriteLine("/{0}:{1}", name, arg);
\r
85 protected string GetOutputPath() {
\r
86 return Path.GetFullPath(Path.Combine(BaseDirectory, Project.ExpandText(Output)));
\r
89 protected virtual bool NeedsCompiling() {
\r
90 // return true as soon as we know we need to compile
\r
92 FileInfo outputFileInfo = new FileInfo(GetOutputPath());
\r
93 if (!outputFileInfo.Exists) {
\r
97 if (FileSet.MoreRecentLastWriteTime(Sources.FileNames, outputFileInfo.LastWriteTime)) {
\r
100 if (FileSet.MoreRecentLastWriteTime(References.FileNames, outputFileInfo.LastWriteTime)) {
\r
103 if (FileSet.MoreRecentLastWriteTime(Modules.FileNames, outputFileInfo.LastWriteTime)) {
\r
107 // if we made it here then we don't have to recompile
\r
111 protected override void ExecuteTask() {
\r
112 if (NeedsCompiling()) {
\r
113 // create temp response file to hold compiler options
\r
114 _responseFileName = Path.GetTempFileName();
\r
115 StreamWriter writer = new StreamWriter(_responseFileName);
\r
118 if (References.BaseDirectory == null) {
\r
119 References.BaseDirectory = BaseDirectory;
\r
121 if (Modules.BaseDirectory == null) {
\r
122 Modules.BaseDirectory = BaseDirectory;
\r
124 if (Sources.BaseDirectory == null) {
\r
125 Sources.BaseDirectory = BaseDirectory;
\r
128 Log.WriteLine(LogPrefix + "Compiling {0} files to {1}", Sources.FileNames.Count, GetOutputPath());
\r
130 // specific compiler options
\r
131 WriteOptions(writer);
\r
133 // Microsoft common compiler options
\r
134 WriteOption(writer, "nologo");
\r
135 WriteOption(writer, "target", OutputTarget);
\r
136 WriteOption(writer, "out", GetOutputPath());
\r
138 WriteOption(writer, "debug");
\r
139 WriteOption(writer, "define", "DEBUG");
\r
140 WriteOption(writer, "define", "TRACE");
\r
142 if (Define != null) {
\r
143 WriteOption(writer, "define", Define);
\r
145 if (Win32Icon != null) {
\r
146 WriteOption(writer, "win32icon", Win32Icon);
\r
148 foreach (string fileName in References.FileNames) {
\r
149 WriteOption(writer, "reference", fileName);
\r
151 foreach (string fileName in Modules.FileNames) {
\r
152 WriteOption(writer, "addmodule", fileName);
\r
154 foreach (string fileName in Resources.FileNames) {
\r
155 WriteOption(writer, "resource", fileName);
\r
157 foreach (string fileName in Sources.FileNames) {
\r
158 writer.WriteLine(fileName);
\r
160 // Make sure to close the response file otherwise contents
\r
161 // will not be written to disc and EXecuteTask() will fail.
\r
165 // display response file contents
\r
166 Log.WriteLine(LogPrefix + "Contents of " + _responseFileName);
\r
168 StreamReader reader = File.OpenText(_responseFileName);
\r
169 string line = reader.ReadLine();
\r
170 while (line != null) {
\r
171 Log.WriteLine(LogPrefix + " " + line);
\r
172 line = reader.ReadLine();
\r
177 StreamReader reader = File.OpenText(_responseFileName);
\r
178 Log.WriteLine(reader.ReadToEnd());
\r
183 // call base class to do the work
\r
184 base.ExecuteTask();
\r
187 // make sure we delete response file even if an exception is thrown
\r
188 writer.Close(); // make sure stream is closed or file cannot be deleted
\r
189 File.Delete(_responseFileName);
\r
190 _responseFileName = null;
\r