259 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
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));
 | 
						|
    }
 | 
						|
}
 |