Skip to content

Commit

Permalink
[Rgen] Compile all platforms provided in parallel.
Browse files Browse the repository at this point in the history
Allow the command line to be used with more than one rsp. That allows to
pass all the rsp for the different platforms we support allowing us to
merge the compilation results later to be used by the transformation.
  • Loading branch information
mandel-macaque committed Jan 21, 2025
1 parent 9516bf1 commit 98e0721
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 114 deletions.
20 changes: 20 additions & 0 deletions src/rgen/Microsoft.Macios.Transformer/CompilationResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Xamarin.Utils;

namespace Microsoft.Macios.Transformer;

/// <summary>
/// Holds the result of a compilation. This is a helper record to make code cleaner in the transformer.
/// </summary>
/// <param name="Platform">The platform the compilation targeted.</param>
/// <param name="Compilation">The compilation result.</param>
/// <param name="Errors">All compilation errors.</param>
record CompilationResult (ApplePlatform Platform, Compilation Compilation, ImmutableArray<Diagnostic> Errors) {

public (ApplePlatform Platform, Compilation compilation) ToTuple ()
=> (Platform, Compilation);
}
128 changes: 76 additions & 52 deletions src/rgen/Microsoft.Macios.Transformer/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
using Serilog.Core;
using Serilog.Events;
using Serilog.Templates;
using Xamarin.Utils;
using static System.Console;

public class Program {
static internal readonly LoggingLevelSwitch LogLevelSwitch = new (LogEventLevel.Information);
static internal readonly LoggingLevelSwitch LogLevelSwitch = new(LogEventLevel.Information);
public static ILogger logger = Log.ForContext<Program> ();

public static int Main (string [] args)
{
// Create options
var rspOption = new Option<string> (
var rspOption = new Option<string []> (
new [] { "--response-file", "--rsp" },
"Path to the RSP file"
);
Expand All @@ -41,9 +42,7 @@ public static int Main (string [] args)

var verbosityOption = new Option<Verbosity> (["--verbosity", "-v"],
getDefaultValue: () => Verbosity.Normal) {
IsRequired = false,
Arity = ArgumentArity.ZeroOrOne,
Description = "Set the verbosity level"
IsRequired = false, Arity = ArgumentArity.ZeroOrOne, Description = "Set the verbosity level"
};

// Create root command and add options
Expand All @@ -63,47 +62,39 @@ public static int Main (string [] args)
}

// Set handler for parsing and executing
rootCmd.SetHandler (async (rspPath, destPath, workingDirectory, sdkPath, force, verbosity) => {
WriteLine ($"Microsoft.Macios.Transformer v{typeof (Program).Assembly.GetName ().Version}, (c) Microsoft Corporation. All rights reserved.\n");

// Convert local to absolute, expand ~
rspPath = ToAbsolutePath (rspPath);
workingDirectory = ToAbsolutePath (workingDirectory);
destPath = ToAbsolutePath (destPath);
sdkPath = ToAbsolutePath (sdkPath);

ValidateRsp (rspPath);
ValidateSdk (sdkPath);
ValidateWorkingDirectory (workingDirectory);
ValidateVerbosity (verbosity);
PrepareDestination (destPath, force);

// logging options
Log.Logger = new LoggerConfiguration ()
.MinimumLevel.ControlledBy (LogLevelSwitch)
.Enrich.WithThreadName ()
.Enrich.WithThreadId ()
.Enrich.FromLogContext ()
.WriteTo.Console (new ExpressionTemplate (
"[{@t:HH:mm:ss} {@l:u3} {Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)} (Thread: {ThreadId})] {@m}\n"))
.CreateLogger ();

// Parse the .rsp file with Roslyn's CSharpCommandLineParser
var args = new [] { $"@{rspPath}" };
var parseResult = CSharpCommandLineParser.Default.Parse (args, workingDirectory, null);
logger.Information ("RSP parsed. Errors: {ParserErrorLength}", parseResult.Errors.Length);
foreach (var resultError in parseResult.Errors) {
logger.Error ("{Error}", resultError);
WriteLine (resultError);
}

await Transformer.Execute (
destinationDirectory: destPath,
rspFile: rspPath,
workingDirectory: workingDirectory,
sdkDirectory: sdkPath
);
},
rootCmd.SetHandler (async (rspPlatformPaths, destPath, workingDirectory, sdkPath, force, verbosity) => {
WriteLine (
$"Microsoft.Macios.Transformer v{typeof(Program).Assembly.GetName ().Version}, (c) Microsoft Corporation. All rights reserved.\n");

// Convert local to absolute, expand ~
//rspPath = ToAbsolutePath (rspPath);
workingDirectory = ToAbsolutePath (workingDirectory);
destPath = ToAbsolutePath (destPath);
sdkPath = ToAbsolutePath (sdkPath);

ValidateRsp (rspPlatformPaths, out var rspFiles);
ValidateSdk (sdkPath);
ValidateWorkingDirectory (workingDirectory);
ValidateVerbosity (verbosity);
PrepareDestination (destPath, force);

// logging options
Log.Logger = new LoggerConfiguration ()
.MinimumLevel.ControlledBy (LogLevelSwitch)
.Enrich.WithThreadName ()
.Enrich.WithThreadId ()
.Enrich.FromLogContext ()
.WriteTo.Console (new ExpressionTemplate (
"[{@t:HH:mm:ss} {@l:u3} {Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)} (Thread: {ThreadId})] {@m}\n"))
.CreateLogger ();

await Transformer.Execute (
destinationDirectory: destPath,
rspFiles: rspFiles,
workingDirectory: workingDirectory,
sdkDirectory: sdkPath
);
},
rspOption, destinationOption, workingDirectoryOption, sdkPathOption, forceOption, verbosityOption
);

Expand All @@ -119,13 +110,46 @@ static string ToAbsolutePath (string path)
return absolutePath;
}

static void ValidateRsp (string path)
static void ValidateRsp (string [] paths, out List<(ApplePlatform Platform, string RspPath)> rspFiles)
{
if (string.IsNullOrWhiteSpace (path) || !File.Exists (path))
throw new FileNotFoundException ("RSP file not found.");
if ((File.GetAttributes (path) & FileAttributes.Directory) == FileAttributes.Directory)
throw new Exception ("RSP path is a directory.");
using var stream = File.OpenRead (path); // validate readability
rspFiles = [];
// loop over all the strings, split them by the ':' and retrieve the platform and path. Then
// validate the path
foreach (var cmdPath in paths) {
var parts = cmdPath.Split (':');
if (parts.Length != 2)
throw new Exception ("Invalid RSP format. Expected platform:path");
ApplePlatform platform;
var rspPath = ToAbsolutePath (parts [1]);
switch (parts [0]) {
case "ios":
platform = ApplePlatform.iOS;
break;
case "tvos":
platform = ApplePlatform.TVOS;
break;
case "macos":
platform = ApplePlatform.MacOSX;
break;
case "maccatalys":
platform = ApplePlatform.MacCatalyst;
break;
default:
platform = ApplePlatform.None;
break;
}

if (platform == ApplePlatform.None)
throw new Exception ("Invalid platform in RSP file.");

if (string.IsNullOrWhiteSpace (rspPath) || !File.Exists (rspPath))
throw new FileNotFoundException ($"RSP '{rspPath}' file not found.");
if ((File.GetAttributes (rspPath) & FileAttributes.Directory) == FileAttributes.Directory)
throw new Exception ($"RSP {rspPath} is a directory.");
using var stream = File.OpenRead (rspPath); // validate readability
logger.Debug ("Adding RSP file {RspPath} for platform {Platform}", rspPath, platform);
rspFiles.Add ((platform, rspPath));
}
}

static void ValidateWorkingDirectory (string path)
Expand Down
Loading

0 comments on commit 98e0721

Please sign in to comment.