Directory.Build.targets 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- This file contains the build tasks and targets for verifying the manifest, zipping Release builds,
  3. and copying the plugin to to your Beat Saber folder. Only edit this if you know what you are doing. -->
  4. <Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  5. <PropertyGroup>
  6. <BuildTargetsVersion>1.4</BuildTargetsVersion>
  7. <BuildTargetsModified>false</BuildTargetsModified> <!--Set this to true if you edit this file to prevent automatic updates-->
  8. </PropertyGroup>
  9. <!--Build Targets-->
  10. <Target Name="CheckManifest" AfterTargets="Build" Condition="'$(DisableZipRelease)' == 'True' OR '$(Configuration)' == 'Debug'">
  11. <GetManifestInfo ErrorOnMismatch="False">
  12. <Output TaskParameter="PluginVersion" PropertyName="PluginVersion" />
  13. <Output TaskParameter="GameVersion" PropertyName="GameVersion" />
  14. <Output TaskParameter="AssemblyVersion" PropertyName="AssemblyVersion" />
  15. </GetManifestInfo>
  16. <Message Text="PluginVersion: $(PluginVersion), AssemblyVersion: $(AssemblyVersion), GameVersion: $(GameVersion)" Importance="high" />
  17. </Target>
  18. <Target Name="ZipRelease" AfterTargets="Build" Condition="'$(DisableZipRelease)' != 'True' AND '$(Configuration)' == 'Release'">
  19. <Message Text="Zipping plugin for release." Importance="high" />
  20. <GetCommitHash ProjectDir="$(ProjectDir)">
  21. <Output TaskParameter="CommitShortHash" PropertyName="CommitShortHash" />
  22. </GetCommitHash>
  23. <Copy SourceFiles="$(OutputPath)$(AssemblyName).dll" DestinationFiles="$(IntermediateOutputPath)zip\Plugins\$(AssemblyName).dll" />
  24. <GetManifestInfo ErrorOnMismatch="False">
  25. <Output TaskParameter="PluginVersion" PropertyName="PluginVersion" />
  26. <Output TaskParameter="GameVersion" PropertyName="GameVersion" />
  27. <Output TaskParameter="AssemblyVersion" PropertyName="AssemblyVersion" />
  28. </GetManifestInfo>
  29. <Message Text="PluginVersion: $(PluginVersion), AssemblyVersion: $(AssemblyVersion), GameVersion: $(GameVersion)" Importance="high" />
  30. <ZipDir DirectoryName="$(IntermediateOutputPath)zip" ZipFileName="$(OutDir)zip\$(AssemblyName)-$(PluginVersion)-bs$(GameVersion)-$(CommitShortHash).zip" />
  31. </Target>
  32. <Target Name="CopyToPlugins" AfterTargets="Build" Condition="'$(DisableCopyToPlugins)' != 'True' AND '$(BeatSaberDir)' != ''">
  33. <Error Text="Unable to copy assembly to game folder. BeatSaberDir doesn't exist: $(BeatSaberDir)" Condition="!Exists($(BeatSaberDir))"/>
  34. <IsProcessRunning ProcessName="Beat Saber">
  35. <Output TaskParameter="IsRunning" PropertyName="IsRunning" />
  36. </IsProcessRunning>
  37. <PropertyGroup Condition="'$(IsRunning)' == 'True'">
  38. <PluginDir>$(BeatSaberDir)\IPA\Pending\Plugins</PluginDir>
  39. </PropertyGroup>
  40. <PropertyGroup Condition="'$(IsRunning)' == 'False'">
  41. <PluginDir>$(BeatSaberDir)\Plugins</PluginDir>
  42. </PropertyGroup>
  43. <Message Text="Copying $(OutputPath)$(AssemblyName).dll to $(PluginDir)" Importance="high" />
  44. <Copy SourceFiles="$(OutputPath)$(AssemblyName).dll" DestinationFiles="$(PluginDir)\$(AssemblyName).dll" />
  45. <Copy SourceFiles="$(OutputPath)$(AssemblyName).pdb" DestinationFiles="$(PluginDir)\$(AssemblyName).pdb" />
  46. </Target>
  47. <!--Build Tasks-->
  48. <UsingTask TaskName="GetManifestInfo" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
  49. <ParameterGroup>
  50. <GameVersion ParameterType="System.String" Output="true" />
  51. <PluginVersion ParameterType="System.String" Output="true" />
  52. <AssemblyVersion ParameterType="System.String" Output="true" />
  53. <ErrorOnMismatch ParameterType="System.Boolean" Required="false" />
  54. </ParameterGroup>
  55. <Task>
  56. <Reference Include="System.Runtime" />
  57. <Reference Include="System.Dynamic.Runtime" />
  58. <Reference Include="System.ObjectModel" />
  59. <Using Namespace="System.IO" />
  60. <Using Namespace="System.Text.RegularExpressions" />
  61. <Code Type="Fragment" Language="cs">
  62. <![CDATA[
  63. try
  64. {
  65. string manifestFile = "manifest.json";
  66. string assemblyFile = "Properties\\AssemblyInfo.cs";
  67. string manifest_gameVerStart = "\"gameVersion\"";
  68. string manifest_versionStart = "\"version\"";
  69. string manifest_gameVerLine = null;
  70. string manifest_versionLine = null;
  71. string startString = "[assembly: AssemblyVersion(\"";
  72. string secondStartString = "[assembly: AssemblyFileVersion(\"";
  73. string assemblyFileVersion = null;
  74. string firstLineStr = null;
  75. string endLineStr = null;
  76. bool badParse = false;
  77. int startLine = 1;
  78. int endLine = 0;
  79. int startColumn = 0;
  80. int endColumn = 0;
  81. if (!File.Exists(manifestFile))
  82. {
  83. throw new FileNotFoundException("Could not find manifest: " + Path.GetFullPath(manifestFile));
  84. }
  85. if (!File.Exists(assemblyFile))
  86. {
  87. throw new FileNotFoundException("Could not find AssemblyInfo: " + Path.GetFullPath(assemblyFile));
  88. }
  89. string line;
  90. using (StreamReader manifestStream = new StreamReader(manifestFile))
  91. {
  92. while ((line = manifestStream.ReadLine()) != null && (manifest_versionLine == null || manifest_gameVerLine == null))
  93. {
  94. line = line.Trim();
  95. if (line.StartsWith(manifest_gameVerStart))
  96. {
  97. manifest_gameVerLine = line;
  98. }
  99. else if (line.StartsWith(manifest_versionStart))
  100. {
  101. manifest_versionLine = line;
  102. }
  103. }
  104. }
  105. if (!string.IsNullOrEmpty(manifest_versionLine))
  106. {
  107. PluginVersion = manifest_versionLine.Substring(manifest_versionStart.Length).Replace(":", "").Replace("\"", "").TrimEnd(',').Trim();
  108. }
  109. else
  110. {
  111. Log.LogError("Build", "BSMOD04", "", manifestFile, 0, 0, 0, 0, "PluginVersion not found in manifest.json");
  112. PluginVersion = "E.R.R";
  113. if(ErrorOnMismatch)
  114. return false;
  115. }
  116. if (!string.IsNullOrEmpty(manifest_gameVerLine))
  117. {
  118. GameVersion = manifest_gameVerLine.Substring(manifest_gameVerStart.Length).Replace(":", "").Replace("\"", "").TrimEnd(',').Trim();
  119. }
  120. else
  121. {
  122. Log.LogError("Build", "BSMOD05", "", manifestFile, 0, 0, 0, 0, "GameVersion not found in manifest.json");
  123. GameVersion = "E.R.R";
  124. if(ErrorOnMismatch)
  125. return false;
  126. }
  127. line = null;
  128. using (StreamReader assemblyStream = new StreamReader(assemblyFile))
  129. {
  130. while ((line = assemblyStream.ReadLine()) != null)
  131. {
  132. if (line.Trim().StartsWith(startString))
  133. {
  134. firstLineStr = line;
  135. break;
  136. }
  137. startLine++;
  138. endLine = startLine + 1;
  139. }
  140. while ((line = assemblyStream.ReadLine()) != null)
  141. {
  142. if (line.Trim().StartsWith(secondStartString))
  143. {
  144. endLineStr = line;
  145. break;
  146. }
  147. endLine++;
  148. }
  149. }
  150. if (!string.IsNullOrEmpty(firstLineStr))
  151. {
  152. startColumn = firstLineStr.IndexOf('"') + 1;
  153. endColumn = firstLineStr.LastIndexOf('"');
  154. if (startColumn > 0 && endColumn > 0)
  155. AssemblyVersion = firstLineStr.Substring(startColumn, endColumn - startColumn);
  156. else
  157. badParse = true;
  158. }
  159. else
  160. badParse = true;
  161. if (badParse)
  162. {
  163. Log.LogError("Build", "BSMOD03", "", assemblyFile, 0, 0, 0, 0, "Unable to parse the AssemblyVersion from {0}", assemblyFile);
  164. if(ErrorOnMismatch)
  165. return false;
  166. badParse = false;
  167. }
  168. if (PluginVersion != "E.R.R" && AssemblyVersion != PluginVersion)
  169. {
  170. Log.LogError("Build", "BSMOD01", "", assemblyFile, startLine, startColumn + 1, startLine, endColumn + 1, "PluginVersion {0} in manifest.json does not match AssemblyVersion {1} in AssemblyInfo.cs", PluginVersion, AssemblyVersion, assemblyFile);
  171. Log.LogMessage(MessageImportance.High, "PluginVersion {0} does not match AssemblyVersion {1}", PluginVersion, AssemblyVersion);
  172. if(ErrorOnMismatch)
  173. return false;
  174. }
  175. if (!string.IsNullOrEmpty(endLineStr))
  176. {
  177. startColumn = endLineStr.IndexOf('"') + 1;
  178. endColumn = endLineStr.LastIndexOf('"');
  179. if (startColumn > 0 && endColumn > 0)
  180. {
  181. assemblyFileVersion = endLineStr.Substring(startColumn, endColumn - startColumn);
  182. if (AssemblyVersion != assemblyFileVersion)
  183. {
  184. Log.LogWarning("Build", "BSMOD02", "", assemblyFile, endLine, startColumn + 1, endLine, endColumn + 1, "AssemblyVersion {0} does not match AssemblyFileVersion {1} in AssemblyInfo.cs", AssemblyVersion, assemblyFileVersion);
  185. if(ErrorOnMismatch)
  186. return false;
  187. }
  188. }
  189. else
  190. {
  191. Log.LogWarning("Build", "BSMOD06", "", assemblyFile, 0, 0, 0, 0, "Unable to parse the AssemblyFileVersion from {0}", assemblyFile);
  192. if(ErrorOnMismatch)
  193. return false;
  194. }
  195. }
  196. return true;
  197. }
  198. catch (Exception ex)
  199. {
  200. Log.LogErrorFromException(ex);
  201. return false;
  202. }
  203. ]]>
  204. </Code>
  205. </Task>
  206. </UsingTask>
  207. <!-- Source: https://stackoverflow.com/a/38127938 -->
  208. <UsingTask TaskName="ZipDir" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
  209. <ParameterGroup>
  210. <DirectoryName ParameterType="System.String" Required="true" />
  211. <ZipFileName ParameterType="System.String" Required="true" />
  212. </ParameterGroup>
  213. <Task>
  214. <Reference Include="System.IO.Compression.FileSystem" />
  215. <Reference Include="System.IO" />
  216. <Using Namespace="System.IO.Compression" />
  217. <Using Namespace="System.IO" />
  218. <Using Namespace="System.Threading" />
  219. <Code Type="Fragment" Language="cs">
  220. <![CDATA[
  221. try
  222. {
  223. var zipDir = new DirectoryInfo(Path.GetDirectoryName(Path.GetFullPath(ZipFileName)));
  224. if (zipDir.Exists)
  225. zipDir.Delete(true);
  226. zipDir.Create();
  227. zipDir.Refresh();
  228. int tries = 0;
  229. while(!zipDir.Exists || tries < 10) // Prevents breaking when Explorer is in the folder.
  230. {
  231. tries++;
  232. Thread.Sleep(50);
  233. zipDir.Create();
  234. zipDir.Refresh();
  235. }
  236. if(File.Exists(ZipFileName))
  237. File.Delete(ZipFileName);
  238. Log.LogMessage(MessageImportance.High, "Zipping Directory \"{0}\" to \"{1}\"", DirectoryName, ZipFileName);
  239. ZipFile.CreateFromDirectory( DirectoryName, ZipFileName );
  240. return true;
  241. }
  242. catch(Exception ex)
  243. {
  244. Log.LogErrorFromException(ex);
  245. return false;
  246. }
  247. ]]>
  248. </Code>
  249. </Task>
  250. </UsingTask>
  251. <UsingTask TaskName="GetCommitHash" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
  252. <ParameterGroup>
  253. <ProjectDir ParameterType="System.String" Required="true" />
  254. <CommitShortHash ParameterType="System.String" Output="true" />
  255. </ParameterGroup>
  256. <Task>
  257. <Using Namespace="System.Diagnostics" />
  258. <Using Namespace="System.ComponentModel" />
  259. <Code Type="Fragment" Language="cs">
  260. <![CDATA[
  261. CommitShortHash = "local";
  262. bool noGitFound = false;
  263. try
  264. {
  265. ProjectDir = Path.GetFullPath(ProjectDir);
  266. Process process = new Process();
  267. string arg = "rev-parse HEAD";
  268. process.StartInfo = new ProcessStartInfo("git", arg);
  269. process.StartInfo.UseShellExecute = false;
  270. process.StartInfo.WorkingDirectory = ProjectDir;
  271. process.StartInfo.RedirectStandardOutput = true;
  272. process.Start();
  273. string outText = process.StandardOutput.ReadToEnd();
  274. if (outText.Length >= 7)
  275. {
  276. CommitShortHash = outText.Substring(0, 7);
  277. return true;
  278. }
  279. }
  280. catch (Win32Exception ex)
  281. {
  282. noGitFound = true;
  283. }
  284. catch (Exception ex)
  285. {
  286. Log.LogErrorFromException(ex);
  287. return true;
  288. }
  289. try
  290. {
  291. string gitPath = Path.GetFullPath(Path.Combine(ProjectDir, ".git"));
  292. string headPath = Path.Combine(gitPath, "HEAD");
  293. string headContents = null;
  294. if (File.Exists(headPath))
  295. headContents = File.ReadAllText(headPath);
  296. else
  297. {
  298. gitPath = Path.GetFullPath(Path.Combine(ProjectDir, "..", ".git"));
  299. headPath = Path.Combine(gitPath, "HEAD");
  300. if (File.Exists(headPath))
  301. headContents = File.ReadAllText(headPath);
  302. }
  303. headPath = null;
  304. if (!string.IsNullOrEmpty(headContents) && headContents.StartsWith("ref:"))
  305. headPath = Path.Combine(gitPath, headContents.Replace("ref:", "").Trim());
  306. if (File.Exists(headPath))
  307. {
  308. headContents = File.ReadAllText(headPath);
  309. if (headContents.Length >= 7)
  310. CommitShortHash = headContents.Substring(0, 7);
  311. }
  312. }
  313. catch { }
  314. if (CommitShortHash == "local")
  315. {
  316. if(noGitFound)
  317. Log.LogMessage(MessageImportance.High, " 'git' command not found, unable to retrieve current commit hash.");
  318. else
  319. Log.LogMessage(MessageImportance.High, " Unable to retrieve current commit hash.");
  320. }
  321. return true;
  322. ]]>
  323. </Code>
  324. </Task>
  325. </UsingTask>
  326. <UsingTask TaskName="IsProcessRunning" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
  327. <ParameterGroup>
  328. <ProcessName ParameterType="System.String" Required="true" />
  329. <IsRunning ParameterType="System.Boolean" Output="true" />
  330. </ParameterGroup>
  331. <Task>
  332. <Using Namespace="System.Diagnostics" />
  333. <Code Type="Fragment" Language="cs">
  334. <![CDATA[
  335. if (string.IsNullOrEmpty(ProcessName))
  336. {
  337. return false;
  338. }
  339. foreach (Process proc in Process.GetProcesses())
  340. {
  341. if (proc.ProcessName.Contains(ProcessName))
  342. {
  343. IsRunning = true;
  344. break;
  345. }
  346. }
  347. ]]>
  348. </Code>
  349. </Task>
  350. </UsingTask>
  351. </Project>