2005-06-05 Peter Bartok <pbartok@novell.com>
[mono.git] / mcs / nant / src / Tasks / CompilerBase.cs
1 // NAnt - A .NET build tool\r
2 // Copyright (C) 2001 Gerry Shaw\r
3 //\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
8 //\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
13 //\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
17 //\r
18 // Gerry Shaw (gerry_shaw@yahoo.com)\r
19 // Mike Krueger (mike@icsharpcode.net)\r
20 \r
21 namespace SourceForge.NAnt {\r
22 \r
23     using System;\r
24     using System.Collections.Specialized;\r
25     using System.Diagnostics;\r
26     using System.IO;\r
27 \r
28     public abstract class CompilerBase : ExternalProgramBase {\r
29 \r
30         string _responseFileName;\r
31 \r
32         // Microsoft common compiler options\r
33         [TaskAttribute("output", Required=true)]\r
34         string _output = null;\r
35 \r
36         [TaskAttribute("target", Required=true)]\r
37         string _target = null;\r
38 \r
39         [TaskAttribute("debug")]\r
40         [BooleanValidator()]\r
41         string _debug = Boolean.FalseString;\r
42 \r
43         [TaskAttribute("define")]\r
44         string _define = null;\r
45 \r
46         [TaskAttribute("win32icon")]\r
47         string _win32icon = null;\r
48 \r
49         [TaskFileSet("references")]\r
50         FileSet _references = new FileSet(false);\r
51 \r
52         [TaskFileSet("resources")]\r
53         FileSet _resources = new FileSet(false);\r
54 \r
55         [TaskFileSet("modules")]\r
56         FileSet _modules = new FileSet(false);\r
57 \r
58         [TaskFileSet("sources")]\r
59         FileSet _sources = new FileSet(true); // include all by default\r
60 \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
70 \r
71         public override string ProgramFileName  { get { return Name; } }\r
72         public override string ProgramArguments { get { return "@" + _responseFileName; } }\r
73 \r
74         protected virtual void WriteOptions(TextWriter writer) {\r
75         }\r
76 \r
77         protected virtual void WriteOption(TextWriter writer, string name) {\r
78             writer.WriteLine("/{0}", name);\r
79         }\r
80 \r
81         protected virtual void WriteOption(TextWriter writer, string name, string arg) {\r
82             writer.WriteLine("/{0}:{1}", name, arg);\r
83         }\r
84 \r
85         protected string GetOutputPath() {\r
86             return Path.GetFullPath(Path.Combine(BaseDirectory, Project.ExpandText(Output)));\r
87         }\r
88 \r
89         protected virtual bool NeedsCompiling() {\r
90             // return true as soon as we know we need to compile\r
91 \r
92             FileInfo outputFileInfo = new FileInfo(GetOutputPath());\r
93             if (!outputFileInfo.Exists) {\r
94                 return true;\r
95             }\r
96 \r
97             if (FileSet.MoreRecentLastWriteTime(Sources.FileNames, outputFileInfo.LastWriteTime)) {\r
98                 return true;\r
99             }\r
100             if (FileSet.MoreRecentLastWriteTime(References.FileNames, outputFileInfo.LastWriteTime)) {\r
101                 return true;\r
102             }\r
103             if (FileSet.MoreRecentLastWriteTime(Modules.FileNames, outputFileInfo.LastWriteTime)) {\r
104                 return true;\r
105             }\r
106 \r
107             // if we made it here then we don't have to recompile\r
108             return false;\r
109         }\r
110 \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
116 \r
117                 try {\r
118                     if (References.BaseDirectory == null) {\r
119                         References.BaseDirectory = BaseDirectory;\r
120                     }\r
121                     if (Modules.BaseDirectory == null) {\r
122                         Modules.BaseDirectory = BaseDirectory;\r
123                     }\r
124                     if (Sources.BaseDirectory == null) {\r
125                         Sources.BaseDirectory = BaseDirectory;\r
126                     }\r
127 \r
128                     Log.WriteLine(LogPrefix + "Compiling {0} files to {1}", Sources.FileNames.Count, GetOutputPath());\r
129 \r
130                     // specific compiler options\r
131                     WriteOptions(writer);\r
132 \r
133                     // Microsoft common compiler options\r
134                     WriteOption(writer, "nologo");\r
135                     WriteOption(writer, "target", OutputTarget);\r
136                     WriteOption(writer, "out", GetOutputPath());\r
137                     if (Debug) {\r
138                         WriteOption(writer, "debug");\r
139                         WriteOption(writer, "define", "DEBUG");\r
140                         WriteOption(writer, "define", "TRACE");\r
141                     }\r
142                     if (Define != null) {\r
143                         WriteOption(writer, "define", Define);\r
144                     }\r
145                     if (Win32Icon != null) {\r
146                         WriteOption(writer, "win32icon", Win32Icon);\r
147                     }\r
148                     foreach (string fileName in References.FileNames) {\r
149                         WriteOption(writer, "reference", fileName);\r
150                     }\r
151                     foreach (string fileName in Modules.FileNames) {\r
152                         WriteOption(writer, "addmodule", fileName);\r
153                     }\r
154                     foreach (string fileName in Resources.FileNames) {\r
155                         WriteOption(writer, "resource", fileName);\r
156                     }\r
157                     foreach (string fileName in Sources.FileNames) {\r
158                         writer.WriteLine(fileName);\r
159                     }\r
160                     // Make sure to close the response file otherwise contents\r
161                     // will not be written to disc and EXecuteTask() will fail.\r
162                     writer.Close();\r
163 \r
164                     if (Verbose) {\r
165                         // display response file contents\r
166                         Log.WriteLine(LogPrefix + "Contents of " + _responseFileName);\r
167                         /*\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
173                         }\r
174                         reader.Close();\r
175                         */\r
176 \r
177                         StreamReader reader = File.OpenText(_responseFileName);\r
178                         Log.WriteLine(reader.ReadToEnd());\r
179                         reader.Close();\r
180 \r
181                     }\r
182 \r
183                     // call base class to do the work\r
184                     base.ExecuteTask();\r
185 \r
186                 } finally {\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
191                 }\r
192             }\r
193         }\r
194     }\r
195 }\r