ProjectGenerator.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using GodotTools.Core;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using Microsoft.Build.Construction;
  6. namespace GodotTools.ProjectEditor
  7. {
  8. public static class ProjectGenerator
  9. {
  10. private const string CoreApiProjectName = "GodotSharp";
  11. private const string EditorApiProjectName = "GodotSharpEditor";
  12. private const string CoreApiProjectGuid = "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}";
  13. private const string EditorApiProjectGuid = "{8FBEC238-D944-4074-8548-B3B524305905}";
  14. public static string GenCoreApiProject(string dir, IEnumerable<string> compileItems)
  15. {
  16. string path = Path.Combine(dir, CoreApiProjectName + ".csproj");
  17. ProjectPropertyGroupElement mainGroup;
  18. var root = CreateLibraryProject(CoreApiProjectName, out mainGroup);
  19. mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
  20. mainGroup.SetProperty("RootNamespace", "Godot");
  21. mainGroup.SetProperty("ProjectGuid", CoreApiProjectGuid);
  22. mainGroup.SetProperty("BaseIntermediateOutputPath", "obj");
  23. GenAssemblyInfoFile(root, dir, CoreApiProjectName,
  24. new[] {"[assembly: InternalsVisibleTo(\"" + EditorApiProjectName + "\")]"},
  25. new[] {"System.Runtime.CompilerServices"});
  26. foreach (var item in compileItems)
  27. {
  28. root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
  29. }
  30. root.Save(path);
  31. return CoreApiProjectGuid;
  32. }
  33. public static string GenEditorApiProject(string dir, string coreApiProjPath, IEnumerable<string> compileItems)
  34. {
  35. string path = Path.Combine(dir, EditorApiProjectName + ".csproj");
  36. ProjectPropertyGroupElement mainGroup;
  37. var root = CreateLibraryProject(EditorApiProjectName, out mainGroup);
  38. mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
  39. mainGroup.SetProperty("RootNamespace", "Godot");
  40. mainGroup.SetProperty("ProjectGuid", EditorApiProjectGuid);
  41. mainGroup.SetProperty("BaseIntermediateOutputPath", "obj");
  42. GenAssemblyInfoFile(root, dir, EditorApiProjectName);
  43. foreach (var item in compileItems)
  44. {
  45. root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
  46. }
  47. var coreApiRef = root.AddItem("ProjectReference", coreApiProjPath.Replace("/", "\\"));
  48. coreApiRef.AddMetadata("Private", "False");
  49. root.Save(path);
  50. return EditorApiProjectGuid;
  51. }
  52. public static string GenGameProject(string dir, string name, IEnumerable<string> compileItems)
  53. {
  54. string path = Path.Combine(dir, name + ".csproj");
  55. ProjectPropertyGroupElement mainGroup;
  56. var root = CreateLibraryProject(name, out mainGroup);
  57. mainGroup.SetProperty("OutputPath", Path.Combine(".mono", "temp", "bin", "$(Configuration)"));
  58. mainGroup.SetProperty("BaseIntermediateOutputPath", Path.Combine(".mono", "temp", "obj"));
  59. mainGroup.SetProperty("IntermediateOutputPath", Path.Combine("$(BaseIntermediateOutputPath)", "$(Configuration)"));
  60. mainGroup.SetProperty("ApiConfiguration", "Debug").Condition = " '$(Configuration)' != 'Release' ";
  61. mainGroup.SetProperty("ApiConfiguration", "Release").Condition = " '$(Configuration)' == 'Release' ";
  62. var toolsGroup = root.AddPropertyGroup();
  63. toolsGroup.Condition = " '$(Configuration)|$(Platform)' == 'Tools|AnyCPU' ";
  64. toolsGroup.AddProperty("DebugSymbols", "true");
  65. toolsGroup.AddProperty("DebugType", "portable");
  66. toolsGroup.AddProperty("Optimize", "false");
  67. toolsGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;TOOLS;");
  68. toolsGroup.AddProperty("ErrorReport", "prompt");
  69. toolsGroup.AddProperty("WarningLevel", "4");
  70. toolsGroup.AddProperty("ConsolePause", "false");
  71. var coreApiRef = root.AddItem("Reference", CoreApiProjectName);
  72. coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", CoreApiProjectName + ".dll"));
  73. coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", CoreApiProjectName + ".dll"));
  74. coreApiRef.AddMetadata("Private", "False");
  75. var editorApiRef = root.AddItem("Reference", EditorApiProjectName);
  76. editorApiRef.Condition = " '$(Configuration)' == 'Tools' ";
  77. editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", EditorApiProjectName + ".dll"));
  78. editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", EditorApiProjectName + ".dll"));
  79. editorApiRef.AddMetadata("Private", "False");
  80. GenAssemblyInfoFile(root, dir, name);
  81. foreach (var item in compileItems)
  82. {
  83. root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
  84. }
  85. root.Save(path);
  86. return root.GetGuid().ToString().ToUpper();
  87. }
  88. public static void GenAssemblyInfoFile(ProjectRootElement root, string dir, string name, string[] assemblyLines = null, string[] usingDirectives = null)
  89. {
  90. string propertiesDir = Path.Combine(dir, "Properties");
  91. if (!Directory.Exists(propertiesDir))
  92. Directory.CreateDirectory(propertiesDir);
  93. string usingDirectivesText = string.Empty;
  94. if (usingDirectives != null)
  95. {
  96. foreach (var usingDirective in usingDirectives)
  97. usingDirectivesText += "\nusing " + usingDirective + ";";
  98. }
  99. string assemblyLinesText = string.Empty;
  100. if (assemblyLines != null)
  101. assemblyLinesText += string.Join("\n", assemblyLines) + "\n";
  102. string content = string.Format(AssemblyInfoTemplate, usingDirectivesText, name, assemblyLinesText);
  103. string assemblyInfoFile = Path.Combine(propertiesDir, "AssemblyInfo.cs");
  104. File.WriteAllText(assemblyInfoFile, content);
  105. root.AddItem("Compile", assemblyInfoFile.RelativeToPath(dir).Replace("/", "\\"));
  106. }
  107. public static ProjectRootElement CreateLibraryProject(string name, out ProjectPropertyGroupElement mainGroup)
  108. {
  109. if (string.IsNullOrEmpty(name))
  110. throw new ArgumentException($"{nameof(name)} cannot be empty", nameof(name));
  111. var root = ProjectRootElement.Create();
  112. root.DefaultTargets = "Build";
  113. mainGroup = root.AddPropertyGroup();
  114. mainGroup.AddProperty("Configuration", "Debug").Condition = " '$(Configuration)' == '' ";
  115. mainGroup.AddProperty("Platform", "AnyCPU").Condition = " '$(Platform)' == '' ";
  116. mainGroup.AddProperty("ProjectGuid", "{" + Guid.NewGuid().ToString().ToUpper() + "}");
  117. mainGroup.AddProperty("OutputType", "Library");
  118. mainGroup.AddProperty("OutputPath", Path.Combine("bin", "$(Configuration)"));
  119. mainGroup.AddProperty("RootNamespace", IdentifierUtils.SanitizeQualifiedIdentifier(name, allowEmptyIdentifiers: true));
  120. mainGroup.AddProperty("AssemblyName", name);
  121. mainGroup.AddProperty("TargetFrameworkVersion", "v4.5");
  122. var debugGroup = root.AddPropertyGroup();
  123. debugGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ";
  124. debugGroup.AddProperty("DebugSymbols", "true");
  125. debugGroup.AddProperty("DebugType", "portable");
  126. debugGroup.AddProperty("Optimize", "false");
  127. debugGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;");
  128. debugGroup.AddProperty("ErrorReport", "prompt");
  129. debugGroup.AddProperty("WarningLevel", "4");
  130. debugGroup.AddProperty("ConsolePause", "false");
  131. var releaseGroup = root.AddPropertyGroup();
  132. releaseGroup.Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ";
  133. releaseGroup.AddProperty("DebugType", "portable");
  134. releaseGroup.AddProperty("Optimize", "true");
  135. releaseGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;");
  136. releaseGroup.AddProperty("ErrorReport", "prompt");
  137. releaseGroup.AddProperty("WarningLevel", "4");
  138. releaseGroup.AddProperty("ConsolePause", "false");
  139. // References
  140. var referenceGroup = root.AddItemGroup();
  141. referenceGroup.AddItem("Reference", "System");
  142. root.AddImport(Path.Combine("$(MSBuildBinPath)", "Microsoft.CSharp.targets").Replace("/", "\\"));
  143. return root;
  144. }
  145. private static void AddItems(ProjectRootElement elem, string groupName, params string[] items)
  146. {
  147. var group = elem.AddItemGroup();
  148. foreach (var item in items)
  149. {
  150. group.AddItem(groupName, item);
  151. }
  152. }
  153. private const string AssemblyInfoTemplate =
  154. @"using System.Reflection;{0}
  155. // Information about this assembly is defined by the following attributes.
  156. // Change them to the values specific to your project.
  157. [assembly: AssemblyTitle(""{1}"")]
  158. [assembly: AssemblyDescription("""")]
  159. [assembly: AssemblyConfiguration("""")]
  160. [assembly: AssemblyCompany("""")]
  161. [assembly: AssemblyProduct("""")]
  162. [assembly: AssemblyCopyright("""")]
  163. [assembly: AssemblyTrademark("""")]
  164. [assembly: AssemblyCulture("""")]
  165. // The assembly version has the format ""{{Major}}.{{Minor}}.{{Build}}.{{Revision}}"".
  166. // The form ""{{Major}}.{{Minor}}.*"" will automatically update the build and revision,
  167. // and ""{{Major}}.{{Minor}}.{{Build}}.*"" will update just the revision.
  168. [assembly: AssemblyVersion(""1.0.*"")]
  169. // The following attributes are used to specify the signing key for the assembly,
  170. // if desired. See the Mono documentation for more information about signing.
  171. //[assembly: AssemblyDelaySign(false)]
  172. //[assembly: AssemblyKeyFile("""")]
  173. {2}";
  174. }
  175. }