Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Use a Response file for AOT
Browse files Browse the repository at this point in the history
Fixes https://devdiv.visualstudio.com/DevDiv/_workitems/edit/609244

Windows has a limit on the length of command line arguments.
As a result AOT can fail on windows if the project paths
are too long.

mono 2018-06 introduced a `--response=FILE` which allows
us to provide all the options in a file rather than on the
command line directly.
  • Loading branch information
dellis1972 committed Oct 15, 2018
1 parent 5e47af3 commit c75de5b
Showing 1 changed file with 51 additions and 43 deletions.
94 changes: 51 additions & 43 deletions src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -447,50 +447,58 @@ bool RunAotCompiler (string assembliesPath, string aotCompiler, string aotOption
{
var stdout_completed = new ManualResetEvent (false);
var stderr_completed = new ManualResetEvent (false);
var psi = new ProcessStartInfo () {
FileName = aotCompiler,
Arguments = aotOptions + " " + assembly,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow=true,
WindowStyle=ProcessWindowStyle.Hidden,
WorkingDirectory = WorkingDirectory,
};

// we do not want options to be provided out of band to the cross compilers
psi.EnvironmentVariables ["MONO_ENV_OPTIONS"] = String.Empty;
// the C code cannot parse all the license details, including the activation code that tell us which license level is allowed
// so we provide this out-of-band to the cross-compilers - this can be extended to communicate a few others bits as well
psi.EnvironmentVariables ["MONO_PATH"] = assembliesPath;

LogDebugMessage ("[AOT] MONO_PATH=\"{0}\" MONO_ENV_OPTIONS=\"{1}\" {2} {3}",
psi.EnvironmentVariables ["MONO_PATH"], psi.EnvironmentVariables ["MONO_ENV_OPTIONS"], psi.FileName, psi.Arguments);

using (var proc = new Process ()) {
proc.OutputDataReceived += (s, e) => {
if (e.Data != null)
OnAotOutputData (s, e);
else
stdout_completed.Set ();
};
proc.ErrorDataReceived += (s, e) => {
if (e.Data != null)
OnAotErrorData (s, e);
else
stderr_completed.Set ();
var responseFile = Path.GetTempFileName ();
try {
File.WriteAllText (responseFile, aotOptions + " " + assembly);

var psi = new ProcessStartInfo () {
FileName = aotCompiler,
Arguments = $"--response=\"{responseFile}\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = WorkingDirectory,
};
proc.StartInfo = psi;
proc.Start ();
proc.BeginOutputReadLine ();
proc.BeginErrorReadLine ();
token.Register (() => { try { proc.Kill (); } catch (Exception) { } });
proc.WaitForExit ();
if (psi.RedirectStandardError)
stderr_completed.WaitOne (TimeSpan.FromSeconds (30));
if (psi.RedirectStandardOutput)
stdout_completed.WaitOne (TimeSpan.FromSeconds (30));
return proc.ExitCode == 0;

// we do not want options to be provided out of band to the cross compilers
psi.EnvironmentVariables ["MONO_ENV_OPTIONS"] = String.Empty;
// the C code cannot parse all the license details, including the activation code that tell us which license level is allowed
// so we provide this out-of-band to the cross-compilers - this can be extended to communicate a few others bits as well
psi.EnvironmentVariables ["MONO_PATH"] = assembliesPath;

LogDebugMessage ("[AOT] MONO_PATH=\"{0}\" MONO_ENV_OPTIONS=\"{1}\" {2} {3}",
psi.EnvironmentVariables ["MONO_PATH"], psi.EnvironmentVariables ["MONO_ENV_OPTIONS"], psi.FileName, psi.Arguments);

using (var proc = new Process ()) {
proc.OutputDataReceived += (s, e) => {
if (e.Data != null)
OnAotOutputData (s, e);
else
stdout_completed.Set ();
};
proc.ErrorDataReceived += (s, e) => {
if (e.Data != null)
OnAotErrorData (s, e);
else
stderr_completed.Set ();
};
proc.StartInfo = psi;
proc.Start ();
proc.BeginOutputReadLine ();
proc.BeginErrorReadLine ();
token.Register (() => { try { proc.Kill (); } catch (Exception) { } });
proc.WaitForExit ();
if (psi.RedirectStandardError)
stderr_completed.WaitOne (TimeSpan.FromSeconds (30));
if (psi.RedirectStandardOutput)
stdout_completed.WaitOne (TimeSpan.FromSeconds (30));
return proc.ExitCode == 0;
}
} finally {
if (File.Exists (responseFile))
File.Delete (responseFile);
}
}

Expand Down

0 comments on commit c75de5b

Please sign in to comment.