Files

259 lines
8.4 KiB
C#
Raw Permalink Normal View History

using System.Xml.Linq;
using CommandLine;
using Newtonsoft.Json;
using UnrealSharpBuildTool.Actions;
namespace UnrealSharpBuildTool;
public static class Program
{
public static BuildToolOptions BuildToolOptions = null!;
public static int Main(string[] args)
{
try
{
Console.WriteLine(">>> UnrealSharpBuildTool");
Parser parser = new Parser(with => with.HelpWriter = null);
ParserResult<BuildToolOptions> result = parser.ParseArguments<BuildToolOptions>(args);
if (result.Tag == ParserResultType.NotParsed)
{
BuildToolOptions.PrintHelp(result);
string errors = string.Empty;
foreach (Error error in result.Errors)
{
if (error is TokenError tokenError)
{
errors += $"{tokenError.Tag}: {tokenError.Token} \n";
}
}
throw new Exception($"Invalid arguments. Errors: {errors}");
}
BuildToolOptions = result.Value;
if (!BuildToolAction.InitializeAction())
{
return 1;
}
Console.WriteLine($"UnrealSharpBuildTool executed {BuildToolOptions.Action.ToString()} action successfully.");
}
catch (Exception exception)
{
Console.WriteLine("An error occurred: " + exception.Message + Environment.NewLine + exception.StackTrace);
return 1;
}
return 0;
}
public static string TryGetArgument(string argument)
{
return BuildToolOptions.TryGetArgument(argument);
}
public static IEnumerable<string> GetArguments(string argument)
{
return BuildToolOptions.GetArguments(argument);
}
public static bool HasArgument(string argument)
{
return BuildToolOptions.HasArgument(argument);
}
public static string GetSolutionFile()
{
return Path.Combine(GetScriptFolder(), BuildToolOptions.ProjectName + ".sln");
}
public static string GetUProjectFilePath()
{
return Path.Combine(BuildToolOptions.ProjectDirectory, BuildToolOptions.ProjectName + ".uproject");
}
public static string GetBuildConfiguration()
{
string buildConfig = TryGetArgument("BuildConfig");
if (string.IsNullOrEmpty(buildConfig))
{
buildConfig = "Debug";
}
return buildConfig;
}
public static BuildConfig GetBuildConfig()
{
string buildConfig = GetBuildConfiguration();
Enum.TryParse(buildConfig, out BuildConfig config);
return config;
}
public static string GetBuildConfiguration(BuildConfig buildConfig)
{
return buildConfig switch
{
BuildConfig.Debug => "Debug",
BuildConfig.Release => "Release",
BuildConfig.Publish => "Release",
_ => "Release"
};
}
public static string GetScriptFolder()
{
return Path.Combine(BuildToolOptions.ProjectDirectory, "Script");
}
public static string GetPluginsFolder()
{
return Path.Combine(BuildToolOptions.ProjectDirectory, "Plugins");
}
public static string GetProjectDirectory()
{
return BuildToolOptions.ProjectDirectory;
}
public static string FixPath(string path)
{
if (OperatingSystem.IsWindows())
{
return path.Replace('/', '\\');
}
return path;
}
public static string GetProjectNameAsManaged()
{
return "Managed" + BuildToolOptions.ProjectName;
}
public static string GetOutputPath(string rootDir = "")
{
if (string.IsNullOrEmpty(rootDir))
{
rootDir = BuildToolOptions.ProjectDirectory;
}
return Path.Combine(rootDir, "Binaries", "Managed");
}
public static string GetWeaver()
{
return Path.Combine(GetManagedBinariesDirectory(), "UnrealSharpWeaver.dll");
}
public static string GetManagedBinariesDirectory()
{
return Path.Combine(BuildToolOptions.PluginDirectory, "Binaries", "Managed");
}
public static string GetVersion()
{
Version currentVersion = Environment.Version;
string currentVersionStr = $"{currentVersion.Major}.{currentVersion.Minor}";
return "net" + currentVersionStr;
}
public static void CreateOrUpdateLaunchSettings(string launchSettingsPath)
{
Root root = new Root();
string executablePath = string.Empty;
if (OperatingSystem.IsWindows())
{
executablePath = Path.Combine(BuildToolOptions.EngineDirectory, "Binaries", "Win64", "UnrealEditor.exe");
}
else if (OperatingSystem.IsMacOS())
{
executablePath = Path.Combine(BuildToolOptions.EngineDirectory, "Binaries", "Mac", "UnrealEditor");
}
string commandLineArgs = FixPath(GetUProjectFilePath());
// Create a new profile if it doesn't exist
if (root.Profiles == null)
{
root.Profiles = new Profiles();
}
root.Profiles.ProfileName = new Profile
{
CommandName = "Executable",
ExecutablePath = executablePath,
CommandLineArgs = $"\"{commandLineArgs}\"",
};
string newJsonString = JsonConvert.SerializeObject(root, Formatting.Indented);
StreamWriter writer = File.CreateText(launchSettingsPath);
writer.Write(newJsonString);
writer.Close();
}
public static List<FileInfo> GetAllProjectFiles(DirectoryInfo folder)
{
return folder.GetDirectories("Script")
.SelectMany(GetProjectsInDirectory)
.Concat(folder.GetDirectories("Plugins")
.SelectMany(x => x.EnumerateFiles("*.uplugin", SearchOption.AllDirectories))
.Select(x => x.Directory)
.Select(x => x!.GetDirectories("Script").FirstOrDefault())
.Where(x => x is not null)
.SelectMany(GetProjectsInDirectory!))
.ToList();
}
public static Dictionary<string, List<FileInfo>> GetProjectFilesByDirectory(DirectoryInfo folder)
{
Dictionary<string, List<FileInfo>> result = new Dictionary<string, List<FileInfo>>();
DirectoryInfo? scriptsFolder = folder.GetDirectories("Script").FirstOrDefault();
if (scriptsFolder is not null)
{
result.Add(GetOutputPathForDirectory(scriptsFolder), GetProjectsInDirectory(scriptsFolder).ToList());
}
foreach (DirectoryInfo? pluginFolder in folder.GetDirectories("Plugins")
.SelectMany(x => x.EnumerateFiles("*.uplugin", SearchOption.AllDirectories))
.Select(x => x.Directory)
.Select(x => x!.GetDirectories("Script").FirstOrDefault())
.Where(x => x is not null))
{
result.Add(GetOutputPathForDirectory(pluginFolder!), GetProjectsInDirectory(pluginFolder!).ToList());
}
return result;
}
private static string GetOutputPathForDirectory(DirectoryInfo directory)
{
return Path.Combine(directory.Parent!.FullName, "Binaries", "Managed");
}
private static IEnumerable<FileInfo> GetProjectsInDirectory(DirectoryInfo folder)
{
var csprojFiles = folder.EnumerateFiles("*.csproj", SearchOption.AllDirectories);
var fsprojFiles = folder.EnumerateFiles("*.fsproj", SearchOption.AllDirectories);
return csprojFiles.Concat(fsprojFiles).Where(IsWeavableProject);
}
private static bool IsWeavableProject(FileInfo projectFile)
{
// We need to be able to filter out certain non-production projects.
// The main target of this is source generators and analyzers which users
// may want to leverage as part of their solution and can't be weaved because
// they have to use netstandard2.0.
XDocument doc = XDocument.Load(projectFile.FullName);
return !doc.Descendants()
.Where(element => element.Name.LocalName == "PropertyGroup")
.SelectMany(element => element.Elements())
.Any(element => element.Name.LocalName == "ExcludeFromWeaver" &&
element.Value.Equals("true", StringComparison.OrdinalIgnoreCase));
}
}