ProjectGenerator.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using GodotTools.Core;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Reflection;
  6. using Microsoft.Build.Construction;
  7. namespace GodotTools.ProjectEditor
  8. {
  9. public static class ProjectGenerator
  10. {
  11. private const string CoreApiProjectName = "GodotSharp";
  12. private const string EditorApiProjectName = "GodotSharpEditor";
  13. public const string CSharpProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}";
  14. public const string GodotProjectTypeGuid = "{8F3E2DF0-C35C-4265-82FC-BEA011F4A7ED}";
  15. public static readonly string GodotDefaultProjectTypeGuids = $"{GodotProjectTypeGuid};{CSharpProjectTypeGuid}";
  16. public static string GenGameProject(string dir, string name, IEnumerable<string> compileItems)
  17. {
  18. string path = Path.Combine(dir, name + ".csproj");
  19. ProjectPropertyGroupElement mainGroup;
  20. var root = CreateLibraryProject(name, "Debug", out mainGroup);
  21. mainGroup.SetProperty("ProjectTypeGuids", GodotDefaultProjectTypeGuids);
  22. mainGroup.SetProperty("OutputPath", Path.Combine(".mono", "temp", "bin", "$(Configuration)"));
  23. mainGroup.SetProperty("BaseIntermediateOutputPath", Path.Combine(".mono", "temp", "obj"));
  24. mainGroup.SetProperty("IntermediateOutputPath", Path.Combine("$(BaseIntermediateOutputPath)", "$(Configuration)"));
  25. mainGroup.SetProperty("ApiConfiguration", "Debug").Condition = " '$(Configuration)' != 'ExportRelease' ";
  26. mainGroup.SetProperty("ApiConfiguration", "Release").Condition = " '$(Configuration)' == 'ExportRelease' ";
  27. var debugGroup = root.AddPropertyGroup();
  28. debugGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ";
  29. debugGroup.AddProperty("DebugSymbols", "true");
  30. debugGroup.AddProperty("DebugType", "portable");
  31. debugGroup.AddProperty("Optimize", "false");
  32. debugGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;TOOLS;");
  33. debugGroup.AddProperty("ErrorReport", "prompt");
  34. debugGroup.AddProperty("WarningLevel", "4");
  35. debugGroup.AddProperty("ConsolePause", "false");
  36. var coreApiRef = root.AddItem("Reference", CoreApiProjectName);
  37. coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", CoreApiProjectName + ".dll"));
  38. coreApiRef.AddMetadata("Private", "False");
  39. var editorApiRef = root.AddItem("Reference", EditorApiProjectName);
  40. editorApiRef.Condition = " '$(Configuration)' == 'Debug' ";
  41. editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", "$(ApiConfiguration)", EditorApiProjectName + ".dll"));
  42. editorApiRef.AddMetadata("Private", "False");
  43. GenAssemblyInfoFile(root, dir, name);
  44. foreach (var item in compileItems)
  45. {
  46. root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
  47. }
  48. root.Save(path);
  49. return root.GetGuid().ToString().ToUpper();
  50. }
  51. private static void GenAssemblyInfoFile(ProjectRootElement root, string dir, string name, string[] assemblyLines = null, string[] usingDirectives = null)
  52. {
  53. string propertiesDir = Path.Combine(dir, "Properties");
  54. if (!Directory.Exists(propertiesDir))
  55. Directory.CreateDirectory(propertiesDir);
  56. string usingDirectivesText = string.Empty;
  57. if (usingDirectives != null)
  58. {
  59. foreach (var usingDirective in usingDirectives)
  60. usingDirectivesText += "\nusing " + usingDirective + ";";
  61. }
  62. string assemblyLinesText = string.Empty;
  63. if (assemblyLines != null)
  64. assemblyLinesText += string.Join("\n", assemblyLines) + "\n";
  65. string content = string.Format(AssemblyInfoTemplate, usingDirectivesText, name, assemblyLinesText);
  66. string assemblyInfoFile = Path.Combine(propertiesDir, "AssemblyInfo.cs");
  67. File.WriteAllText(assemblyInfoFile, content);
  68. root.AddItem("Compile", assemblyInfoFile.RelativeToPath(dir).Replace("/", "\\"));
  69. }
  70. public static ProjectRootElement CreateLibraryProject(string name, string defaultConfig, out ProjectPropertyGroupElement mainGroup)
  71. {
  72. if (string.IsNullOrEmpty(name))
  73. throw new ArgumentException($"{nameof(name)} cannot be empty", nameof(name));
  74. var root = ProjectRootElement.Create();
  75. root.DefaultTargets = "Build";
  76. mainGroup = root.AddPropertyGroup();
  77. mainGroup.AddProperty("Configuration", defaultConfig).Condition = " '$(Configuration)' == '' ";
  78. mainGroup.AddProperty("Platform", "AnyCPU").Condition = " '$(Platform)' == '' ";
  79. mainGroup.AddProperty("ProjectGuid", "{" + Guid.NewGuid().ToString().ToUpper() + "}");
  80. mainGroup.AddProperty("OutputType", "Library");
  81. mainGroup.AddProperty("OutputPath", Path.Combine("bin", "$(Configuration)"));
  82. mainGroup.AddProperty("RootNamespace", IdentifierUtils.SanitizeQualifiedIdentifier(name, allowEmptyIdentifiers: true));
  83. mainGroup.AddProperty("AssemblyName", name);
  84. mainGroup.AddProperty("TargetFrameworkVersion", "v4.7");
  85. mainGroup.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
  86. var exportDebugGroup = root.AddPropertyGroup();
  87. exportDebugGroup.Condition = " '$(Configuration)|$(Platform)' == 'ExportDebug|AnyCPU' ";
  88. exportDebugGroup.AddProperty("DebugSymbols", "true");
  89. exportDebugGroup.AddProperty("DebugType", "portable");
  90. exportDebugGroup.AddProperty("Optimize", "false");
  91. exportDebugGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;DEBUG;");
  92. exportDebugGroup.AddProperty("ErrorReport", "prompt");
  93. exportDebugGroup.AddProperty("WarningLevel", "4");
  94. exportDebugGroup.AddProperty("ConsolePause", "false");
  95. var exportReleaseGroup = root.AddPropertyGroup();
  96. exportReleaseGroup.Condition = " '$(Configuration)|$(Platform)' == 'ExportRelease|AnyCPU' ";
  97. exportReleaseGroup.AddProperty("DebugType", "portable");
  98. exportReleaseGroup.AddProperty("Optimize", "true");
  99. exportReleaseGroup.AddProperty("DefineConstants", "$(GodotDefineConstants);GODOT;");
  100. exportReleaseGroup.AddProperty("ErrorReport", "prompt");
  101. exportReleaseGroup.AddProperty("WarningLevel", "4");
  102. exportReleaseGroup.AddProperty("ConsolePause", "false");
  103. // References
  104. var referenceGroup = root.AddItemGroup();
  105. referenceGroup.AddItem("Reference", "System");
  106. var frameworkRefAssembliesItem = referenceGroup.AddItem("PackageReference", "Microsoft.NETFramework.ReferenceAssemblies");
  107. // Use metadata (child nodes) instead of attributes for the PackageReference.
  108. // This is for compatibility with 3.2, where GodotTools uses an old Microsoft.Build.
  109. frameworkRefAssembliesItem.AddMetadata("Version", "1.0.0");
  110. frameworkRefAssembliesItem.AddMetadata("PrivateAssets", "All");
  111. root.AddImport(Path.Combine("$(MSBuildBinPath)", "Microsoft.CSharp.targets").Replace("/", "\\"));
  112. return root;
  113. }
  114. private const string AssemblyInfoTemplate =
  115. @"using System.Reflection;{0}
  116. // Information about this assembly is defined by the following attributes.
  117. // Change them to the values specific to your project.
  118. [assembly: AssemblyTitle(""{1}"")]
  119. [assembly: AssemblyDescription("""")]
  120. [assembly: AssemblyConfiguration("""")]
  121. [assembly: AssemblyCompany("""")]
  122. [assembly: AssemblyProduct("""")]
  123. [assembly: AssemblyCopyright("""")]
  124. [assembly: AssemblyTrademark("""")]
  125. [assembly: AssemblyCulture("""")]
  126. // The assembly version has the format ""{{Major}}.{{Minor}}.{{Build}}.{{Revision}}"".
  127. // The form ""{{Major}}.{{Minor}}.*"" will automatically update the build and revision,
  128. // and ""{{Major}}.{{Minor}}.{{Build}}.*"" will update just the revision.
  129. [assembly: AssemblyVersion(""1.0.*"")]
  130. // The following attributes are used to specify the signing key for the assembly,
  131. // if desired. See the Mono documentation for more information about signing.
  132. //[assembly: AssemblyDelaySign(false)]
  133. //[assembly: AssemblyKeyFile("""")]
  134. {2}";
  135. }
  136. }