Skip to content

Commit be371a9

Browse files
committed
[Xamarin.Android.Build.Tasks] Use a Response file for AOT
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.
1 parent acb72d9 commit be371a9

File tree

2 files changed

+60
-60
lines changed

2 files changed

+60
-60
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,6 @@ static string GetNdkToolchainLibraryDir(string binDir)
148148
return libPath;
149149
}
150150

151-
static string GetShortPath (string path)
152-
{
153-
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
154-
return QuoteFileName (path);
155-
var shortPath = KernelEx.GetShortPathName (Path.GetDirectoryName (path));
156-
return Path.Combine (shortPath, Path.GetFileName (path));
157-
}
158-
159151
static string QuoteFileName(string fileName)
160152
{
161153
var builder = new CommandLineBuilder();
@@ -374,9 +366,9 @@ IEnumerable<Config> GetAotConfigs ()
374366
Diagnostic.Error (5101, ex.Message);
375367
}
376368
var libs = new List<string>() {
377-
GetShortPath (Path.Combine(GetNdkToolchainLibraryDir(toolchainPath), "libgcc.a")),
378-
GetShortPath (Path.Combine(androidLibPath, "libc.so")),
379-
GetShortPath (Path.Combine(androidLibPath, "libm.so"))
369+
Path.Combine (GetNdkToolchainLibraryDir (toolchainPath), "libgcc.a"),
370+
Path.Combine (androidLibPath, "libc.so"),
371+
Path.Combine (androidLibPath, "libm.so")
380372
};
381373
ldFlags = string.Join(";", libs);
382374
}
@@ -397,17 +389,17 @@ IEnumerable<Config> GetAotConfigs ()
397389
if (!string.IsNullOrEmpty (AotAdditionalArguments))
398390
aotOptions.Add (AotAdditionalArguments);
399391
if (sequencePointsMode == SequencePointsMode.Offline)
400-
aotOptions.Add ("msym-dir=" + GetShortPath (outdir));
392+
aotOptions.Add ("msym-dir=" + QuoteFileName (outdir));
401393
if (AotMode != AotMode.Normal)
402394
aotOptions.Add (AotMode.ToString ().ToLowerInvariant ());
403395

404-
aotOptions.Add ("outfile=" + GetShortPath (outputFile));
396+
aotOptions.Add ("outfile=" + QuoteFileName (outputFile));
405397
aotOptions.Add ("asmwriter");
406398
aotOptions.Add ("mtriple=" + mtriple);
407-
aotOptions.Add ("tool-prefix=" + GetShortPath (toolPrefix));
399+
aotOptions.Add ("tool-prefix=" + QuoteFileName (toolPrefix));
408400
aotOptions.Add ("ld-flags=" + ldFlags);
409-
aotOptions.Add ("llvm-path=" + GetShortPath (sdkBinDirectory));
410-
aotOptions.Add ("temp-path=" + GetShortPath (tempDir));
401+
aotOptions.Add ("llvm-path=" + QuoteFileName (sdkBinDirectory));
402+
aotOptions.Add ("temp-path=" + QuoteFileName (tempDir));
411403

412404
string aotOptionsStr = (EnableLLVM ? "--llvm " : "") + "--aot=" + string.Join (",", aotOptions);
413405

@@ -440,50 +432,58 @@ bool RunAotCompiler (string assembliesPath, string aotCompiler, string aotOption
440432
{
441433
var stdout_completed = new ManualResetEvent (false);
442434
var stderr_completed = new ManualResetEvent (false);
443-
var psi = new ProcessStartInfo () {
444-
FileName = aotCompiler,
445-
Arguments = aotOptions + " " + assembly,
446-
UseShellExecute = false,
447-
RedirectStandardOutput = true,
448-
RedirectStandardError = true,
449-
CreateNoWindow=true,
450-
WindowStyle=ProcessWindowStyle.Hidden,
451-
WorkingDirectory = WorkingDirectory,
452-
};
453-
454-
// we do not want options to be provided out of band to the cross compilers
455-
psi.EnvironmentVariables ["MONO_ENV_OPTIONS"] = String.Empty;
456-
// the C code cannot parse all the license details, including the activation code that tell us which license level is allowed
457-
// so we provide this out-of-band to the cross-compilers - this can be extended to communicate a few others bits as well
458-
psi.EnvironmentVariables ["MONO_PATH"] = assembliesPath;
459-
460-
LogDebugMessage ("[AOT] MONO_PATH=\"{0}\" MONO_ENV_OPTIONS=\"{1}\" {2} {3}",
461-
psi.EnvironmentVariables ["MONO_PATH"], psi.EnvironmentVariables ["MONO_ENV_OPTIONS"], psi.FileName, psi.Arguments);
462-
463-
using (var proc = new Process ()) {
464-
proc.OutputDataReceived += (s, e) => {
465-
if (e.Data != null)
466-
OnAotOutputData (s, e);
467-
else
468-
stdout_completed.Set ();
469-
};
470-
proc.ErrorDataReceived += (s, e) => {
471-
if (e.Data != null)
472-
OnAotErrorData (s, e);
473-
else
474-
stderr_completed.Set ();
435+
var responseFile = Path.GetTempFileName ();
436+
try {
437+
File.WriteAllText (responseFile, aotOptions + " " + assembly);
438+
439+
var psi = new ProcessStartInfo () {
440+
FileName = aotCompiler,
441+
Arguments = $"--response=\"{responseFile}\"",
442+
UseShellExecute = false,
443+
RedirectStandardOutput = true,
444+
RedirectStandardError = true,
445+
CreateNoWindow = true,
446+
WindowStyle = ProcessWindowStyle.Hidden,
447+
WorkingDirectory = WorkingDirectory,
475448
};
476-
proc.StartInfo = psi;
477-
proc.Start ();
478-
proc.BeginOutputReadLine ();
479-
proc.BeginErrorReadLine ();
480-
Token.Register (() => { try { proc.Kill (); } catch (Exception) { } });
481-
proc.WaitForExit ();
482-
if (psi.RedirectStandardError)
483-
stderr_completed.WaitOne (TimeSpan.FromSeconds (30));
484-
if (psi.RedirectStandardOutput)
485-
stdout_completed.WaitOne (TimeSpan.FromSeconds (30));
486-
return proc.ExitCode == 0;
449+
450+
// we do not want options to be provided out of band to the cross compilers
451+
psi.EnvironmentVariables ["MONO_ENV_OPTIONS"] = String.Empty;
452+
// the C code cannot parse all the license details, including the activation code that tell us which license level is allowed
453+
// so we provide this out-of-band to the cross-compilers - this can be extended to communicate a few others bits as well
454+
psi.EnvironmentVariables ["MONO_PATH"] = assembliesPath;
455+
456+
LogDebugMessage ("[AOT] MONO_PATH=\"{0}\" MONO_ENV_OPTIONS=\"{1}\" {2} {3}",
457+
psi.EnvironmentVariables ["MONO_PATH"], psi.EnvironmentVariables ["MONO_ENV_OPTIONS"], psi.FileName, psi.Arguments);
458+
459+
using (var proc = new Process ()) {
460+
proc.OutputDataReceived += (s, e) => {
461+
if (e.Data != null)
462+
OnAotOutputData (s, e);
463+
else
464+
stdout_completed.Set ();
465+
};
466+
proc.ErrorDataReceived += (s, e) => {
467+
if (e.Data != null)
468+
OnAotErrorData (s, e);
469+
else
470+
stderr_completed.Set ();
471+
};
472+
proc.StartInfo = psi;
473+
proc.Start ();
474+
proc.BeginOutputReadLine ();
475+
proc.BeginErrorReadLine ();
476+
Token.Register (() => { try { proc.Kill (); } catch (Exception) { } });
477+
proc.WaitForExit ();
478+
if (psi.RedirectStandardError)
479+
stderr_completed.WaitOne (TimeSpan.FromSeconds (30));
480+
if (psi.RedirectStandardOutput)
481+
stdout_completed.WaitOne (TimeSpan.FromSeconds (30));
482+
return proc.ExitCode == 0;
483+
}
484+
} finally {
485+
if (File.Exists (responseFile))
486+
File.Delete (responseFile);
487487
}
488488
}
489489

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ public void BuildAotApplication (string supportedAbis, bool enableLLVM, bool exp
673673
// LLVM passes a direct path to libc.so, and we need to use the libc.so
674674
// which corresponds to the *minimum* SDK version specified in AndroidManifest.xml
675675
// Since we overrode minSdkVersion=10, that means we should use libc.so from android-9.
676-
var rightLibc = new Regex (@"^\s*\[AOT\].*cross-.*--llvm.*,ld-flags=.*android-9.arch-.*.usr.lib.libc\.so", RegexOptions.Multiline);
676+
var rightLibc = new Regex (@"\s*\[aot-compiler stdout].*android-9.arch-.*.usr.lib.libc\.so", RegexOptions.Multiline);
677677
var m = rightLibc.Match (string.Join ("\n",b.LastBuildOutput));
678678
Assert.IsTrue (m.Success, "AOT+LLVM should use libc.so from minSdkVersion!");
679679
}

0 commit comments

Comments
 (0)