aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Prebuild/src/Core/Targets/VSGenericTarget.cs
diff options
context:
space:
mode:
authorlbsa712009-02-19 12:48:38 +0000
committerlbsa712009-02-19 12:48:38 +0000
commitdd9640cda82bca8125289f292238ea6b447cc6e9 (patch)
tree5f558fa38e4c03b05eb5b91cc9db7ff2363c0b48 /Prebuild/src/Core/Targets/VSGenericTarget.cs
parentreverted last revision, until we decide how to handle capturing IM's (diff)
downloadopensim-SC-dd9640cda82bca8125289f292238ea6b447cc6e9.zip
opensim-SC-dd9640cda82bca8125289f292238ea6b447cc6e9.tar.gz
opensim-SC-dd9640cda82bca8125289f292238ea6b447cc6e9.tar.bz2
opensim-SC-dd9640cda82bca8125289f292238ea6b447cc6e9.tar.xz
=== PREBUILD UPSTREAMS UPDATE : POTENTIAL BREAKAGE ===
* Applied upstreams changes to allow for auditing and debugging in our various environments. * This should, in theory, bring back 'multiple ref dirs'. * Temporarily Removed xmlns because prebuild-1.7 schema does not allow for multiple solutions per prebuild node (This will be a moot issue once the Prebuild node is moved out of prebuild.xml) * Autotools target: Various minor fixes * MonoDevelop Target : No changes. * Nant Target: Various minor fixes, support for net-3.5 and mono-2.0/3.5 targets * Sharpdevelop targets: No changes. * VS Targets: Refactored into using VSGenericTarget, and supports 2.0-3.5 * XCode Target: No changes. --- Regressions and outstanding issues --- * The Solution is assigned a random Guid - will lead to unnecessary reloads and loss of user settings. --- New features of Prebuild 2.0.4 --- * (Better) support for Web, WinForms and Database Projects and build actions * Conditional Framework Version compilation support (1.1, 2.0-3.5) * ArrayList -> List<>, ICollection -> IList (this means Prebuild can generate 1.1 solutions, but can't itself be built under 1.1 - how very meta) * Added <?include file="sub_prebuild.xml" ?> preprocessor directive.
Diffstat (limited to 'Prebuild/src/Core/Targets/VSGenericTarget.cs')
-rw-r--r--Prebuild/src/Core/Targets/VSGenericTarget.cs881
1 files changed, 881 insertions, 0 deletions
diff --git a/Prebuild/src/Core/Targets/VSGenericTarget.cs b/Prebuild/src/Core/Targets/VSGenericTarget.cs
new file mode 100644
index 0000000..401331d
--- /dev/null
+++ b/Prebuild/src/Core/Targets/VSGenericTarget.cs
@@ -0,0 +1,881 @@
1#region BSD License
2/*
3Copyright (c) 2008 Matthew Holmes (matthew@wildfiregames.com), John Anderson (sontek@gmail.com)
4
5Redistribution and use in source and binary forms, with or without modification, are permitted
6provided that the following conditions are met:
7
8* Redistributions of source code must retain the above copyright notice, this list of conditions
9 and the following disclaimer.
10* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
11 and the following disclaimer in the documentation and/or other materials provided with the
12 distribution.
13* The name of the author may not be used to endorse or promote products derived from this software
14 without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
17BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23*/
24#endregion
25
26using System;
27using System.Collections;
28using System.Collections.Generic;
29using System.Collections.Specialized;
30using System.IO;
31using System.Text;
32
33using Prebuild.Core.Attributes;
34using Prebuild.Core.Interfaces;
35using Prebuild.Core.Nodes;
36using Prebuild.Core.Utilities;
37using System.CodeDom.Compiler;
38
39namespace Prebuild.Core.Targets
40{
41
42 /// <summary>
43 ///
44 /// </summary>
45 public abstract class VSGenericTarget : ITarget
46 {
47 #region Fields
48
49 readonly Hashtable tools = new Hashtable();
50 Kernel kernel;
51 #endregion
52
53 #region Properties
54 /// <summary>
55 /// Gets or sets the solution version.
56 /// </summary>
57 /// <value>The solution version.</value>
58 public abstract string SolutionVersion { get; }
59 /// <summary>
60 /// Gets or sets the product version.
61 /// </summary>
62 /// <value>The product version.</value>
63 public abstract string ProductVersion { get; }
64 /// <summary>
65 /// Gets or sets the schema version.
66 /// </summary>
67 /// <value>The schema version.</value>
68 public abstract string SchemaVersion { get; }
69 /// <summary>
70 /// Gets or sets the name of the version.
71 /// </summary>
72 /// <value>The name of the version.</value>
73 public abstract string VersionName { get; }
74 /// <summary>
75 /// Gets or sets the version.
76 /// </summary>
77 /// <value>The version.</value>
78 public abstract VSVersion Version { get; }
79 /// <summary>
80 /// Gets the name.
81 /// </summary>
82 /// <value>The name.</value>
83 public abstract string Name { get; }
84
85 protected abstract string GetToolsVersionXml(FrameworkVersion version);
86 public abstract string SolutionTag { get; }
87
88 #endregion
89
90 #region Constructors
91
92 /// <summary>
93 /// Initializes a new instance of the <see cref="VSGenericTarget"/> class.
94 /// </summary>
95 protected VSGenericTarget()
96 {
97 this.tools["C#"] = new ToolInfo("C#", "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", "csproj", "CSHARP", "$(MSBuildBinPath)\\Microsoft.CSHARP.Targets");
98 this.tools["Database"] = new ToolInfo("Database", "{4F174C21-8C12-11D0-8340-0000F80270F8}", "dbp", "UNKNOWN");
99 this.tools["Boo"] = new ToolInfo("Boo", "{45CEA7DC-C2ED-48A6-ACE0-E16144C02365}", "booproj", "Boo", "$(BooBinPath)\\Boo.Microsoft.Build.targets");
100 this.tools["VisualBasic"] = new ToolInfo("VisualBasic", "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}", "vbproj", "VisualBasic", "$(MSBuildBinPath)\\Microsoft.VisualBasic.Targets");
101 this.tools["Folder"] = new ToolInfo("Folder", "{2150E333-8FDC-42A3-9474-1A3956D46DE8}", null, null);
102 }
103
104 #endregion
105
106 #region Private Methods
107
108 private string MakeRefPath(ProjectNode project)
109 {
110 string ret = "";
111 foreach (ReferencePathNode node in project.ReferencePaths)
112 {
113 try
114 {
115 string fullPath = Helper.ResolvePath(node.Path);
116 if (ret.Length < 1)
117 {
118 ret = fullPath;
119 }
120 else
121 {
122 ret += ";" + fullPath;
123 }
124 }
125 catch (ArgumentException)
126 {
127 this.kernel.Log.Write(LogType.Warning, "Could not resolve reference path: {0}", node.Path);
128 }
129 }
130
131 return ret;
132 }
133
134 private static ProjectNode FindProjectInSolution(string name, SolutionNode solution)
135 {
136 SolutionNode node = solution;
137
138 while (node.Parent is SolutionNode)
139 node = node.Parent as SolutionNode;
140
141 return FindProjectInSolutionRecursively(name, node);
142 }
143
144 private static ProjectNode FindProjectInSolutionRecursively(string name, SolutionNode solution)
145 {
146 if (solution.ProjectsTable.ContainsKey(name))
147 return (ProjectNode)solution.ProjectsTable[name];
148
149 foreach (SolutionNode child in solution.Solutions)
150 {
151 ProjectNode node = FindProjectInSolutionRecursively(name, child);
152 if (node != null)
153 return node;
154 }
155
156 return null;
157 }
158
159 private void WriteProject(SolutionNode solution, ProjectNode project)
160 {
161 if (!tools.ContainsKey(project.Language))
162 {
163 throw new UnknownLanguageException("Unknown .NET language: " + project.Language);
164 }
165
166 ToolInfo toolInfo = (ToolInfo)tools[project.Language];
167 string projectFile = Helper.MakeFilePath(project.FullPath, project.Name, toolInfo.FileExtension);
168 StreamWriter ps = new StreamWriter(projectFile);
169
170 kernel.CurrentWorkingDirectory.Push();
171 Helper.SetCurrentDir(Path.GetDirectoryName(projectFile));
172
173 #region Project File
174 using (ps)
175 {
176 ps.WriteLine("<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\" {0}>", GetToolsVersionXml(project.FrameworkVersion));
177 ps.WriteLine(" <PropertyGroup>");
178 ps.WriteLine(" <ProjectType>Local</ProjectType>");
179 ps.WriteLine(" <ProductVersion>{0}</ProductVersion>", this.ProductVersion);
180 ps.WriteLine(" <SchemaVersion>{0}</SchemaVersion>", this.SchemaVersion);
181 ps.WriteLine(" <ProjectGuid>{{{0}}}</ProjectGuid>", project.Guid.ToString().ToUpper());
182
183 // Visual Studio has a hard coded guid for the project type
184 if (project.Type == ProjectType.Web)
185 ps.WriteLine(" <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>");
186 ps.WriteLine(" <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>");
187 ps.WriteLine(" <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>");
188 ps.WriteLine(" <ApplicationIcon>{0}</ApplicationIcon>", project.AppIcon);
189 ps.WriteLine(" <AssemblyKeyContainerName>");
190 ps.WriteLine(" </AssemblyKeyContainerName>");
191 ps.WriteLine(" <AssemblyName>{0}</AssemblyName>", project.AssemblyName);
192 foreach (ConfigurationNode conf in project.Configurations)
193 {
194 if (conf.Options.KeyFile != "")
195 {
196 ps.WriteLine(" <AssemblyOriginatorKeyFile>{0}</AssemblyOriginatorKeyFile>", conf.Options.KeyFile);
197 ps.WriteLine(" <SignAssembly>true</SignAssembly>");
198 break;
199 }
200 }
201 ps.WriteLine(" <DefaultClientScript>JScript</DefaultClientScript>");
202 ps.WriteLine(" <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>");
203 ps.WriteLine(" <DefaultTargetSchema>IE50</DefaultTargetSchema>");
204 ps.WriteLine(" <DelaySign>false</DelaySign>");
205 ps.WriteLine(" <TargetFrameworkVersion>{0}</TargetFrameworkVersion>", project.FrameworkVersion.ToString().Replace("_", "."));
206
207 ps.WriteLine(" <OutputType>{0}</OutputType>", project.Type == ProjectType.Web ? ProjectType.Library.ToString() : project.Type.ToString());
208 ps.WriteLine(" <AppDesignerFolder>{0}</AppDesignerFolder>", project.DesignerFolder);
209 ps.WriteLine(" <RootNamespace>{0}</RootNamespace>", project.RootNamespace);
210 ps.WriteLine(" <StartupObject>{0}</StartupObject>", project.StartupObject);
211 if (string.IsNullOrEmpty(project.DebugStartParameters))
212 {
213 ps.WriteLine(" <StartArguments>{0}</StartArguments>", project.DebugStartParameters);
214 }
215 ps.WriteLine(" <FileUpgradeFlags>");
216 ps.WriteLine(" </FileUpgradeFlags>");
217
218 ps.WriteLine(" </PropertyGroup>");
219
220 foreach (ConfigurationNode conf in project.Configurations)
221 {
222 ps.Write(" <PropertyGroup ");
223 ps.WriteLine("Condition=\" '$(Configuration)|$(Platform)' == '{0}|AnyCPU' \">", conf.Name);
224 ps.WriteLine(" <AllowUnsafeBlocks>{0}</AllowUnsafeBlocks>", conf.Options["AllowUnsafe"]);
225 ps.WriteLine(" <BaseAddress>{0}</BaseAddress>", conf.Options["BaseAddress"]);
226 ps.WriteLine(" <CheckForOverflowUnderflow>{0}</CheckForOverflowUnderflow>", conf.Options["CheckUnderflowOverflow"]);
227 ps.WriteLine(" <ConfigurationOverrideFile>");
228 ps.WriteLine(" </ConfigurationOverrideFile>");
229 ps.WriteLine(" <DefineConstants>{0}</DefineConstants>", conf.Options["CompilerDefines"]);
230 ps.WriteLine(" <DocumentationFile>{0}</DocumentationFile>", Helper.NormalizePath(conf.Options["XmlDocFile"].ToString()));
231 ps.WriteLine(" <DebugSymbols>{0}</DebugSymbols>", conf.Options["DebugInformation"]);
232 ps.WriteLine(" <FileAlignment>{0}</FileAlignment>", conf.Options["FileAlignment"]);
233 ps.WriteLine(" <Optimize>{0}</Optimize>", conf.Options["OptimizeCode"]);
234 if (project.Type != ProjectType.Web)
235 ps.WriteLine(" <OutputPath>{0}</OutputPath>",
236 Helper.EndPath(Helper.NormalizePath(conf.Options["OutputPath"].ToString())));
237 else
238 ps.WriteLine(" <OutputPath>{0}</OutputPath>",
239 Helper.EndPath(Helper.NormalizePath("bin\\")));
240
241 ps.WriteLine(" <RegisterForComInterop>{0}</RegisterForComInterop>", conf.Options["RegisterComInterop"]);
242 ps.WriteLine(" <RemoveIntegerChecks>{0}</RemoveIntegerChecks>", conf.Options["RemoveIntegerChecks"]);
243 ps.WriteLine(" <TreatWarningsAsErrors>{0}</TreatWarningsAsErrors>", conf.Options["WarningsAsErrors"]);
244 ps.WriteLine(" <WarningLevel>{0}</WarningLevel>", conf.Options["WarningLevel"]);
245 ps.WriteLine(" <NoStdLib>{0}</NoStdLib>", conf.Options["NoStdLib"]);
246 ps.WriteLine(" <NoWarn>{0}</NoWarn>", conf.Options["SuppressWarnings"]);
247 ps.WriteLine(" </PropertyGroup>");
248 }
249
250 //ps.WriteLine(" </Settings>");
251
252 List<ProjectNode> projectReferences = new List<ProjectNode>();
253 List<ReferenceNode> otherReferences = new List<ReferenceNode>();
254
255 foreach (ReferenceNode refr in project.References)
256 {
257 ProjectNode projectNode = FindProjectInSolution(refr.Name, solution);
258
259 if (projectNode == null)
260 otherReferences.Add(refr);
261 else
262 projectReferences.Add(projectNode);
263 }
264 // Assembly References
265 ps.WriteLine(" <ItemGroup>");
266
267 foreach (ReferenceNode refr in otherReferences)
268 {
269 ps.Write(" <Reference");
270 ps.Write(" Include=\"");
271 ps.Write(refr.Name);
272 ps.WriteLine("\" >");
273 ps.Write(" <Name>");
274 ps.Write(refr.Name);
275 ps.WriteLine("</Name>");
276 // TODO: Allow reference to *.exe files
277 ps.WriteLine(" <Private>{0}</Private>", refr.LocalCopy);
278 ps.WriteLine(" </Reference>");
279 }
280 ps.WriteLine(" </ItemGroup>");
281
282 //Project References
283 ps.WriteLine(" <ItemGroup>");
284 foreach (ProjectNode projectReference in projectReferences)
285 {
286 ToolInfo tool = (ToolInfo)tools[projectReference.Language];
287 if (tools == null)
288 throw new UnknownLanguageException();
289
290 string path =
291 Helper.MakePathRelativeTo(project.FullPath,
292 Helper.MakeFilePath(projectReference.FullPath, projectReference.Name, tool.FileExtension));
293 ps.WriteLine(" <ProjectReference Include=\"{0}\">", path);
294
295 // TODO: Allow reference to visual basic projects
296 ps.WriteLine(" <Name>{0}</Name>", projectReference.Name);
297 ps.WriteLine(" <Project>{0}</Project>", projectReference.Guid.ToString("B").ToUpper());
298 ps.WriteLine(" <Package>{0}</Package>", tool.Guid.ToUpper());
299 ps.WriteLine(" </ProjectReference>");
300 }
301 ps.WriteLine(" </ItemGroup>");
302
303 // ps.WriteLine(" </Build>");
304 ps.WriteLine(" <ItemGroup>");
305
306 // ps.WriteLine(" <Include>");
307 List<string> list = new List<string>();
308
309 foreach (string path in project.Files)
310 {
311 string lower = path.ToLower();
312 if (lower.EndsWith(".resx"))
313 {
314 string codebehind = String.Format("{0}.Designer{1}", path.Substring(0, path.LastIndexOf('.')), toolInfo.LanguageExtension);
315 if (!list.Contains(codebehind))
316 list.Add(codebehind);
317 }
318 }
319
320 foreach (string file in project.Files)
321 {
322 // if (file == "Properties\\Bind.Designer.cs")
323 // {
324 // Console.WriteLine("Wait a minute!");
325 // Console.WriteLine(project.Files.GetSubType(file).ToString());
326 // }
327
328 SubType subType = project.Files.GetSubType(file);
329
330 if (subType != SubType.Code && subType != SubType.Settings && subType != SubType.Designer
331 && subType != SubType.CodeBehind)
332 {
333 ps.WriteLine(" <EmbeddedResource Include=\"{0}\">", file.Substring(0, file.LastIndexOf('.')) + ".resx");
334 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(file));
335 ps.WriteLine(" <SubType>Designer</SubType>");
336 ps.WriteLine(" </EmbeddedResource>");
337 //
338 }
339
340 if (subType == SubType.Designer)
341 {
342 ps.WriteLine(" <EmbeddedResource Include=\"{0}\">", file);
343 ps.WriteLine(" <SubType>" + subType + "</SubType>");
344 ps.WriteLine(" <Generator>ResXFileCodeGenerator</Generator>");
345
346 string autogen_name = file.Substring(0, file.LastIndexOf('.')) + ".Designer.cs";
347 string dependent_name = file.Substring(0, file.LastIndexOf('.')) + ".cs";
348
349 ps.WriteLine(" <LastGenOutput>{0}</LastGenOutput>", autogen_name);
350
351 // Check for a parent .cs file with the same name as this designer file
352 if (File.Exists(dependent_name))
353 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(dependent_name));
354
355 ps.WriteLine(" </EmbeddedResource>");
356 if (File.Exists(autogen_name))
357 {
358 ps.WriteLine(" <Compile Include=\"{0}\">", autogen_name);
359 ps.WriteLine(" <AutoGen>True</AutoGen>");
360 ps.WriteLine(" <DesignTime>True</DesignTime>");
361
362 // If a parent .cs file exists, link this autogen file to it. Otherwise link
363 // to the designer file
364 if (File.Exists(dependent_name))
365 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(dependent_name));
366 else
367 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(file));
368
369 ps.WriteLine(" </Compile>");
370 }
371 list.Add(autogen_name);
372 }
373 if (subType == SubType.Settings)
374 {
375 ps.Write(" <{0} ", project.Files.GetBuildAction(file));
376 ps.WriteLine("Include=\"{0}\">", file);
377 string fileName = Path.GetFileName(file);
378 if (project.Files.GetBuildAction(file) == BuildAction.None)
379 {
380 ps.WriteLine(" <Generator>SettingsSingleFileGenerator</Generator>");
381 ps.WriteLine(" <LastGenOutput>{0}</LastGenOutput>", fileName.Substring(0, fileName.LastIndexOf('.')) + ".Designer.cs");
382 }
383 else
384 {
385 ps.WriteLine(" <SubType>Code</SubType>");
386 ps.WriteLine(" <AutoGen>True</AutoGen>");
387 ps.WriteLine(" <DesignTimeSharedInput>True</DesignTimeSharedInput>");
388 string fileNameShort = fileName.Substring(0, fileName.LastIndexOf('.'));
389 string fileNameShorter = fileNameShort.Substring(0, fileNameShort.LastIndexOf('.'));
390 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(fileNameShorter + ".settings"));
391 }
392 ps.WriteLine(" </{0}>", project.Files.GetBuildAction(file));
393 }
394 else if (subType != SubType.Designer)
395 {
396 string path = Helper.NormalizePath(file);
397 string path_lower = path.ToLower();
398
399 if (!list.Contains(file))
400 {
401 ps.Write(" <{0} ", project.Files.GetBuildAction(path));
402
403 int startPos = 0;
404 if (project.Files.GetPreservePath(file))
405 {
406 while ((@"./\").IndexOf(file.Substring(startPos, 1)) != -1)
407 startPos++;
408
409 }
410 else
411 {
412 startPos = file.LastIndexOf(Path.GetFileName(path));
413 }
414
415 ps.WriteLine("Include=\"{0}\">", path);
416
417 int last_period_index = file.LastIndexOf('.');
418 string short_file_name = file.Substring(0, last_period_index);
419 string extension = Path.GetExtension(path);
420 string designer_format = string.Format(".designer{0}", extension);
421
422 if (path_lower.EndsWith(designer_format))
423 {
424 int designer_index = path_lower.IndexOf(designer_format);
425 string file_name = path.Substring(0, designer_index);
426
427 if (File.Exists(file_name))
428 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(file_name));
429 else if (File.Exists(file_name + ".resx"))
430 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(file_name + ".resx"));
431 }
432 else if (subType == SubType.CodeBehind)
433 {
434 ps.WriteLine(" <DependentUpon>{0}</DependentUpon>", Path.GetFileName(short_file_name));
435 }
436 if (project.Files.GetIsLink(file))
437 {
438 string alias = project.Files.GetLinkPath(file);
439 alias += file.Substring(startPos);
440 alias = Helper.NormalizePath(alias);
441 ps.WriteLine(" <Link>{0}</Link>", alias);
442 }
443 else if (project.Files.GetBuildAction(file) != BuildAction.None)
444 {
445 if (project.Files.GetBuildAction(file) != BuildAction.EmbeddedResource)
446 {
447 ps.WriteLine(" <SubType>{0}</SubType>", subType);
448 }
449 }
450
451 if (project.Files.GetCopyToOutput(file) != CopyToOutput.Never)
452 {
453 ps.WriteLine(" <CopyToOutputDirectory>{0}</CopyToOutputDirectory>", project.Files.GetCopyToOutput(file));
454 }
455
456 ps.WriteLine(" </{0}>", project.Files.GetBuildAction(file));
457 }
458 }
459 }
460
461 ps.WriteLine(" </ItemGroup>");
462 ps.WriteLine(" <Import Project=\"" + toolInfo.ImportProject + "\" />");
463 ps.WriteLine(" <PropertyGroup>");
464 ps.WriteLine(" <PreBuildEvent>");
465 ps.WriteLine(" </PreBuildEvent>");
466 ps.WriteLine(" <PostBuildEvent>");
467 ps.WriteLine(" </PostBuildEvent>");
468 ps.WriteLine(" </PropertyGroup>");
469 ps.WriteLine("</Project>");
470 }
471 #endregion
472
473 #region User File
474
475 ps = new StreamWriter(projectFile + ".user");
476 using (ps)
477 {
478 ps.WriteLine("<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">");
479 //ps.WriteLine( "<VisualStudioProject>" );
480 //ps.WriteLine(" <{0}>", toolInfo.XMLTag);
481 //ps.WriteLine(" <Build>");
482 ps.WriteLine(" <PropertyGroup>");
483 //ps.WriteLine(" <Settings ReferencePath=\"{0}\">", MakeRefPath(project));
484 ps.WriteLine(" <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>");
485 ps.WriteLine(" <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>");
486 ps.WriteLine(" <ReferencePath>{0}</ReferencePath>", MakeRefPath(project));
487 ps.WriteLine(" <LastOpenVersion>{0}</LastOpenVersion>", this.ProductVersion);
488 ps.WriteLine(" <ProjectView>ProjectFiles</ProjectView>");
489 ps.WriteLine(" <ProjectTrust>0</ProjectTrust>");
490 ps.WriteLine(" </PropertyGroup>");
491 foreach (ConfigurationNode conf in project.Configurations)
492 {
493 ps.Write(" <PropertyGroup");
494 ps.Write(" Condition = \" '$(Configuration)|$(Platform)' == '{0}|AnyCPU' \"", conf.Name);
495 ps.WriteLine(" />");
496 }
497 ps.WriteLine("</Project>");
498 }
499 #endregion
500
501 kernel.CurrentWorkingDirectory.Pop();
502 }
503
504 private void WriteSolution(SolutionNode solution, bool writeSolutionToDisk)
505 {
506 kernel.Log.Write("Creating {0} solution and project files", this.VersionName);
507
508 foreach (SolutionNode child in solution.Solutions)
509 {
510 kernel.Log.Write("...Creating folder: {0}", child.Name);
511 WriteSolution(child, false);
512 }
513
514 foreach (ProjectNode project in solution.Projects)
515 {
516 kernel.Log.Write("...Creating project: {0}", project.Name);
517 WriteProject(solution, project);
518 }
519
520 foreach (DatabaseProjectNode project in solution.DatabaseProjects)
521 {
522 kernel.Log.Write("...Creating database project: {0}", project.Name);
523 WriteDatabaseProject(solution, project);
524 }
525
526 if (writeSolutionToDisk) // only write main solution
527 {
528 kernel.Log.Write("");
529 string solutionFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "sln");
530
531 using (StreamWriter ss = new StreamWriter(solutionFile))
532 {
533 kernel.CurrentWorkingDirectory.Push();
534 Helper.SetCurrentDir(Path.GetDirectoryName(solutionFile));
535
536 ss.WriteLine("Microsoft Visual Studio Solution File, Format Version {0}", this.SolutionVersion);
537 ss.WriteLine(SolutionTag);
538
539 WriteProjectDeclarations(ss, solution, solution);
540
541 ss.WriteLine("Global");
542
543 ss.WriteLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
544 foreach (ConfigurationNode conf in solution.Configurations)
545 {
546 ss.WriteLine("\t\t{0}|Any CPU = {0}|Any CPU", conf.Name);
547 }
548 ss.WriteLine("\tEndGlobalSection");
549
550 ss.WriteLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
551 WriteConfigurationLines(solution.Configurations, solution, ss);
552 ss.WriteLine("\tEndGlobalSection");
553
554 if (solution.Solutions.Count > 0)
555 {
556 ss.WriteLine("\tGlobalSection(NestedProjects) = preSolution");
557 foreach (SolutionNode embeddedSolution in solution.Solutions)
558 {
559 WriteNestedProjectMap(ss, embeddedSolution);
560 }
561 ss.WriteLine("\tEndGlobalSection");
562 }
563
564 ss.WriteLine("EndGlobal");
565 }
566
567 kernel.CurrentWorkingDirectory.Pop();
568 }
569 }
570
571 private void WriteProjectDeclarations(StreamWriter writer, SolutionNode actualSolution, SolutionNode embeddedSolution)
572 {
573 foreach (SolutionNode childSolution in embeddedSolution.Solutions)
574 {
575 WriteEmbeddedSolution(writer, childSolution);
576 WriteProjectDeclarations(writer, actualSolution, childSolution);
577 }
578
579 foreach (ProjectNode project in embeddedSolution.Projects)
580 {
581 WriteProject(actualSolution, writer, project);
582 }
583
584 foreach (DatabaseProjectNode dbProject in embeddedSolution.DatabaseProjects)
585 {
586 WriteProject(actualSolution, writer, dbProject);
587 }
588
589 if (actualSolution.Guid == embeddedSolution.Guid)
590 {
591 WriteSolutionFiles(actualSolution, writer);
592 }
593 }
594
595 private static void WriteNestedProjectMap(StreamWriter writer, SolutionNode embeddedSolution)
596 {
597 foreach (ProjectNode project in embeddedSolution.Projects)
598 {
599 WriteNestedProject(writer, embeddedSolution, project.Guid);
600 }
601
602 foreach (DatabaseProjectNode dbProject in embeddedSolution.DatabaseProjects)
603 {
604 WriteNestedProject(writer, embeddedSolution, dbProject.Guid);
605 }
606
607 foreach (SolutionNode child in embeddedSolution.Solutions)
608 {
609 WriteNestedProject(writer, embeddedSolution, child.Guid);
610 WriteNestedProjectMap(writer, child);
611 }
612 }
613
614 private static void WriteNestedProject(StreamWriter writer, SolutionNode solution, Guid projectGuid)
615 {
616 WriteNestedFolder(writer, solution.Guid, projectGuid);
617 }
618
619 private static void WriteNestedFolder(StreamWriter writer, Guid parentGuid, Guid childGuid)
620 {
621 writer.WriteLine("\t\t{0} = {1}",
622 childGuid.ToString("B").ToUpper(),
623 parentGuid.ToString("B").ToUpper());
624 }
625
626 private static void WriteConfigurationLines(ICollection configurations, SolutionNode solution, StreamWriter ss)
627 {
628 foreach (ProjectNode project in solution.Projects)
629 {
630 foreach (ConfigurationNode conf in configurations)
631 {
632 ss.WriteLine("\t\t{0}.{1}|Any CPU.ActiveCfg = {1}|Any CPU",
633 project.Guid.ToString("B").ToUpper(),
634 conf.Name);
635
636 ss.WriteLine("\t\t{0}.{1}|Any CPU.Build.0 = {1}|Any CPU",
637 project.Guid.ToString("B").ToUpper(),
638 conf.Name);
639 }
640 }
641
642 foreach (SolutionNode child in solution.Solutions)
643 {
644 WriteConfigurationLines(configurations, child, ss);
645 }
646 }
647
648 private void WriteSolutionFiles(SolutionNode solution, StreamWriter ss)
649 {
650 WriteProject(ss, "Folder", solution.Guid, "Solution Files", "Solution Files", solution.Files);
651 }
652
653 private void WriteEmbeddedSolution(StreamWriter writer, SolutionNode embeddedSolution)
654 {
655 WriteProject(writer, "Folder", embeddedSolution.Guid, embeddedSolution.Name, embeddedSolution.Name, embeddedSolution.Files);
656 }
657
658 private void WriteProject(SolutionNode solution, StreamWriter ss, ProjectNode project)
659 {
660 WriteProject(ss, solution, project.Language, project.Guid, project.Name, project.FullPath);
661 }
662
663 private void WriteProject(SolutionNode solution, StreamWriter ss, DatabaseProjectNode dbProject)
664 {
665 if (solution.Files != null && solution.Files.Count > 0)
666 WriteProject(ss, solution, "Database", dbProject.Guid, dbProject.Name, dbProject.FullPath);
667 }
668
669 private static bool ExtensionSpecified(string refName)
670 {
671 return refName.EndsWith(".dll") || refName.EndsWith(".exe");
672 }
673
674 private static string GetProjectExtension(ProjectNode project)
675 {
676 string extension = ".dll";
677 if (project.Type == ProjectType.Exe)
678 {
679 extension = ".exe";
680 }
681 return extension;
682 }
683
684 const string ProjectDeclarationBeginFormat = "Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"";
685 const string ProjectDeclarationEndFormat = "EndProject";
686
687 private void WriteProject(StreamWriter ss, SolutionNode solution, string language, Guid guid, string name, string projectFullPath)
688 {
689 if (!tools.ContainsKey(language))
690 throw new UnknownLanguageException("Unknown .NET language: " + language);
691
692 ToolInfo toolInfo = (ToolInfo)tools[language];
693
694 string path = Helper.MakePathRelativeTo(solution.FullPath, projectFullPath);
695
696 path = Helper.MakeFilePath(path, name, toolInfo.FileExtension);
697
698 WriteProject(ss, language, guid, name, path);
699 }
700
701 private void WriteProject(StreamWriter writer, string language, Guid projectGuid, string name, string location)
702 {
703 WriteProject(writer, language, projectGuid, name, location, null);
704 }
705
706 private void WriteProject(StreamWriter writer, string language, Guid projectGuid, string name, string location, FilesNode files)
707 {
708 if (!tools.ContainsKey(language))
709 throw new UnknownLanguageException("Unknown .NET language: " + language);
710
711 ToolInfo toolInfo = (ToolInfo)tools[language];
712
713 writer.WriteLine(ProjectDeclarationBeginFormat,
714 toolInfo.Guid,
715 name,
716 location,
717 projectGuid.ToString("B").ToUpper());
718
719 if (files != null)
720 {
721 writer.WriteLine("\tProjectSection(SolutionItems) = preProject");
722
723 foreach (string file in files)
724 writer.WriteLine("\t\t{0} = {0}", file);
725
726 writer.WriteLine("\tEndProjectSection");
727 }
728
729 writer.WriteLine(ProjectDeclarationEndFormat);
730 }
731
732 private void WriteDatabaseProject(SolutionNode solution, DatabaseProjectNode project)
733 {
734 string projectFile = Helper.MakeFilePath(project.FullPath, project.Name, "dbp");
735 IndentedTextWriter ps = new IndentedTextWriter(new StreamWriter(projectFile), " ");
736
737 kernel.CurrentWorkingDirectory.Push();
738
739 Helper.SetCurrentDir(Path.GetDirectoryName(projectFile));
740
741 using (ps)
742 {
743 ps.WriteLine("# Microsoft Developer Studio Project File - Database Project");
744 ps.WriteLine("Begin DataProject = \"{0}\"", project.Name);
745 ps.Indent++;
746 ps.WriteLine("MSDTVersion = \"80\"");
747 // TODO: Use the project.Files property
748 if (ContainsSqlFiles(Path.GetDirectoryName(projectFile)))
749 WriteDatabaseFoldersAndFiles(ps, Path.GetDirectoryName(projectFile));
750
751 ps.WriteLine("Begin DBRefFolder = \"Database References\"");
752 ps.Indent++;
753 foreach (DatabaseReferenceNode reference in project.References)
754 {
755 ps.WriteLine("Begin DBRefNode = \"{0}\"", reference.Name);
756 ps.Indent++;
757 ps.WriteLine("ConnectStr = \"{0}\"", reference.ConnectionString);
758 ps.WriteLine("Provider = \"{0}\"", reference.ProviderId.ToString("B").ToUpper());
759 //ps.WriteLine("Colorizer = 5");
760 ps.Indent--;
761 ps.WriteLine("End");
762 }
763 ps.Indent--;
764 ps.WriteLine("End");
765 ps.Indent--;
766 ps.WriteLine("End");
767
768 ps.Flush();
769 }
770
771 kernel.CurrentWorkingDirectory.Pop();
772 }
773
774 private bool ContainsSqlFiles(string folder)
775 {
776 foreach (string file in Directory.GetFiles(folder, "*.sql"))
777 {
778 return true; // if the folder contains 1 .sql file, that's good enough
779 }
780
781 foreach (string child in Directory.GetDirectories(folder))
782 {
783 if (ContainsSqlFiles(child))
784 return true; // if 1 child folder contains a .sql file, still good enough
785 }
786
787 return false;
788 }
789
790 private void WriteDatabaseFoldersAndFiles(IndentedTextWriter writer, string folder)
791 {
792 foreach (string child in Directory.GetDirectories(folder))
793 {
794 if (ContainsSqlFiles(child))
795 {
796 writer.WriteLine("Begin Folder = \"{0}\"", Path.GetFileName(child));
797 writer.Indent++;
798 WriteDatabaseFoldersAndFiles(writer, child);
799 writer.Indent--;
800 writer.WriteLine("End");
801 }
802 }
803 foreach (string file in Directory.GetFiles(folder, "*.sql"))
804 {
805 writer.WriteLine("Script = \"{0}\"", Path.GetFileName(file));
806 }
807 }
808
809 private void CleanProject(ProjectNode project)
810 {
811 kernel.Log.Write("...Cleaning project: {0}", project.Name);
812
813 ToolInfo toolInfo = (ToolInfo)tools[project.Language];
814 string projectFile = Helper.MakeFilePath(project.FullPath, project.Name, toolInfo.FileExtension);
815 string userFile = projectFile + ".user";
816
817 Helper.DeleteIfExists(projectFile);
818 Helper.DeleteIfExists(userFile);
819 }
820
821 private void CleanSolution(SolutionNode solution)
822 {
823 kernel.Log.Write("Cleaning {0} solution and project files", this.VersionName, solution.Name);
824
825 string slnFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "sln");
826 string suoFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "suo");
827
828 Helper.DeleteIfExists(slnFile);
829 Helper.DeleteIfExists(suoFile);
830
831 foreach (ProjectNode project in solution.Projects)
832 {
833 CleanProject(project);
834 }
835
836 kernel.Log.Write("");
837 }
838
839 #endregion
840
841 #region ITarget Members
842
843 /// <summary>
844 /// Writes the specified kern.
845 /// </summary>
846 /// <param name="kern">The kern.</param>
847 public virtual void Write(Kernel kern)
848 {
849 if (kern == null)
850 {
851 throw new ArgumentNullException("kern");
852 }
853 kernel = kern;
854 foreach (SolutionNode sol in kernel.Solutions)
855 {
856 WriteSolution(sol, true);
857 }
858 kernel = null;
859 }
860
861 /// <summary>
862 /// Cleans the specified kern.
863 /// </summary>
864 /// <param name="kern">The kern.</param>
865 public virtual void Clean(Kernel kern)
866 {
867 if (kern == null)
868 {
869 throw new ArgumentNullException("kern");
870 }
871 kernel = kern;
872 foreach (SolutionNode sol in kernel.Solutions)
873 {
874 CleanSolution(sol);
875 }
876 kernel = null;
877 }
878
879 #endregion
880 }
881}