2020-10-07 03:15:32 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
namespace LibHacBuild.CodeGen;
|
|
|
|
|
|
|
|
|
|
public static class Common
|
2020-10-07 03:15:32 +02:00
|
|
|
|
{
|
2021-11-14 20:08:57 +01:00
|
|
|
|
public static string GetHeader()
|
2020-10-07 03:15:32 +02:00
|
|
|
|
{
|
2021-11-14 20:08:57 +01:00
|
|
|
|
string nl = Environment.NewLine;
|
|
|
|
|
return
|
|
|
|
|
"//-----------------------------------------------------------------------------" + nl +
|
|
|
|
|
"// This file was automatically generated." + nl +
|
|
|
|
|
"// Changes to this file will be lost when the file is regenerated." + nl +
|
|
|
|
|
"//" + nl +
|
|
|
|
|
"// To change this file, modify /build/CodeGen/results.csv at the root of this" + nl +
|
|
|
|
|
"// repo and run the build script." + nl +
|
|
|
|
|
"//" + nl +
|
|
|
|
|
"// The script can be run with the \"codegen\" option to run only the" + nl +
|
|
|
|
|
"// code generation portion of the build." + nl +
|
|
|
|
|
"//-----------------------------------------------------------------------------";
|
|
|
|
|
}
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2022-11-11 07:13:27 +01:00
|
|
|
|
private static void WriteToLog(string message)
|
|
|
|
|
{
|
|
|
|
|
// If the logger is of type "SilentLogger", we're probably running as a separate process from nuke,
|
|
|
|
|
// so we want to log to the console so the nuke instance that launched us will get our output.
|
|
|
|
|
if (Serilog.Log.Logger.GetType().Name.Contains("SilentLogger"))
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(message);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Serilog.Log.Debug(message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
// Write the file only if it has changed
|
|
|
|
|
// Preserve the UTF-8 BOM usage if the file already exists
|
|
|
|
|
public static void WriteOutput(string relativePath, string text)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(relativePath))
|
|
|
|
|
return;
|
2021-01-09 04:45:52 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
string rootPath = FindProjectDirectory();
|
|
|
|
|
string fullPath = Path.Combine(rootPath, relativePath);
|
|
|
|
|
string directoryName = Path.GetDirectoryName(fullPath);
|
2021-01-09 04:45:52 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
if (directoryName == null)
|
|
|
|
|
throw new InvalidDataException($"Invalid output path {relativePath}");
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
if (!Directory.Exists(directoryName))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(directoryName);
|
|
|
|
|
}
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
// Default is true because Visual Studio saves .cs files with the BOM by default
|
|
|
|
|
bool hasBom = true;
|
|
|
|
|
byte[] bom = Encoding.UTF8.GetPreamble();
|
|
|
|
|
byte[] oldFile = null;
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
if (File.Exists(fullPath))
|
|
|
|
|
{
|
|
|
|
|
oldFile = File.ReadAllBytes(fullPath);
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
if (oldFile.Length >= 3)
|
|
|
|
|
hasBom = oldFile.AsSpan(0, 3).SequenceEqual(bom);
|
|
|
|
|
}
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
// Make line endings the same on Windows and Unix
|
|
|
|
|
if (Environment.NewLine == "\n")
|
|
|
|
|
{
|
|
|
|
|
text = text.Replace("\n", "\r\n");
|
|
|
|
|
}
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
byte[] newFile = (hasBom ? bom : new byte[0]).Concat(Encoding.UTF8.GetBytes(text)).ToArray();
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
if (oldFile?.SequenceEqual(newFile) == true)
|
|
|
|
|
{
|
2022-11-11 07:13:27 +01:00
|
|
|
|
WriteToLog($"{relativePath} is already up-to-date");
|
2021-11-14 20:08:57 +01:00
|
|
|
|
return;
|
2020-10-07 03:15:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-11 07:13:27 +01:00
|
|
|
|
WriteToLog($"Generated file {relativePath}");
|
2021-11-14 20:08:57 +01:00
|
|
|
|
File.WriteAllBytes(fullPath, newFile);
|
|
|
|
|
}
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
public static Stream GetResource(string name)
|
|
|
|
|
{
|
|
|
|
|
var assembly = Assembly.GetExecutingAssembly();
|
|
|
|
|
string path = $"LibHacBuild.CodeGen.{name}";
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
Stream stream = assembly.GetManifestResourceStream(path);
|
|
|
|
|
if (stream == null) throw new FileNotFoundException($"Resource {path} was not found.");
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
return stream;
|
|
|
|
|
}
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
public static string FindProjectDirectory()
|
|
|
|
|
{
|
|
|
|
|
string currentDir = Environment.CurrentDirectory;
|
2020-10-07 03:15:32 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
while (currentDir != null)
|
|
|
|
|
{
|
|
|
|
|
if (File.Exists(Path.Combine(currentDir, "LibHac.sln")))
|
|
|
|
|
{
|
|
|
|
|
break;
|
2020-10-07 03:15:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
currentDir = Path.GetDirectoryName(currentDir);
|
2020-10-07 03:15:32 +02:00
|
|
|
|
}
|
2021-11-14 20:08:57 +01:00
|
|
|
|
|
|
|
|
|
if (currentDir == null)
|
|
|
|
|
throw new DirectoryNotFoundException("Unable to find project directory.");
|
|
|
|
|
|
|
|
|
|
return Path.Combine(currentDir, "src");
|
2020-10-07 03:15:32 +02:00
|
|
|
|
}
|
2022-04-02 04:57:16 +02:00
|
|
|
|
}
|