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 Jan 31, 2019
1 parent c5065c4 commit 85c6ce4
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 64 deletions.
126 changes: 63 additions & 63 deletions src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,6 @@ static string GetNdkToolchainLibraryDir (string binDir, AndroidTargetArch arch)
return GetNdkToolchainLibraryDir (binDir, NdkUtil.GetArchDirName (arch));
}

static string GetShortPath (string path)
{
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
return QuoteFileName (path);
var shortPath = KernelEx.GetShortPathName (Path.GetDirectoryName (path));
return Path.Combine (shortPath, Path.GetFileName (path));
}

static string QuoteFileName(string fileName)
{
var builder = new CommandLineBuilder();
Expand Down Expand Up @@ -385,7 +377,6 @@ IEnumerable<Config> GetAotConfigs ()
} catch (InvalidOperationException ex) {
Diagnostic.Error (5101, ex.Message);
}

string toolchainLibDir;
if (NdkUtil.UsingClangNDK)
toolchainLibDir = GetNdkToolchainLibraryDir (toolchainPath, arch);
Expand All @@ -394,19 +385,19 @@ IEnumerable<Config> GetAotConfigs ()

var libs = new List<string>();
if (NdkUtil.UsingClangNDK) {
libs.Add ($"-L{GetShortPath (toolchainLibDir)}");
libs.Add ($"-L{GetShortPath (androidLibPath)}");
libs.Add ($"-L{toolchainLibDir}");
libs.Add ($"-L{androidLibPath}");

if (arch == AndroidTargetArch.Arm) {
// Needed for -lunwind to work
string compilerLibDir = Path.Combine (toolchainPath, "..", "sysroot", "usr", "lib", NdkUtil.GetArchDirName (arch));
libs.Add ($"-L{GetShortPath (compilerLibDir)}");
libs.Add ($"-L{compilerLibDir}");
}
}

libs.Add (GetShortPath (Path.Combine (toolchainLibDir, "libgcc.a")));
libs.Add (GetShortPath (Path.Combine (androidLibPath, "libc.so")));
libs.Add (GetShortPath (Path.Combine (androidLibPath, "libm.so")));
libs.Add (Path.Combine (toolchainLibDir, "libgcc.a"));
libs.Add (Path.Combine (androidLibPath, "libc.so"));
libs.Add (Path.Combine (androidLibPath, "libm.so"));

ldFlags = string.Join(";", libs);
}
Expand All @@ -427,17 +418,17 @@ IEnumerable<Config> GetAotConfigs ()
if (!string.IsNullOrEmpty (AotAdditionalArguments))
aotOptions.Add (AotAdditionalArguments);
if (sequencePointsMode == SequencePointsMode.Offline)
aotOptions.Add ("msym-dir=" + GetShortPath (outdir));
aotOptions.Add ("msym-dir=" + QuoteFileName (outdir));
if (AotMode != AotMode.Normal)
aotOptions.Add (AotMode.ToString ().ToLowerInvariant ());

aotOptions.Add ("outfile=" + GetShortPath (outputFile));
aotOptions.Add ("outfile=" + QuoteFileName (outputFile));
aotOptions.Add ("asmwriter");
aotOptions.Add ("mtriple=" + mtriple);
aotOptions.Add ("tool-prefix=" + GetShortPath (toolPrefix));
aotOptions.Add ("tool-prefix=" + QuoteFileName (toolPrefix));
aotOptions.Add ("ld-flags=" + ldFlags);
aotOptions.Add ("llvm-path=" + GetShortPath (sdkBinDirectory));
aotOptions.Add ("temp-path=" + GetShortPath (tempDir));
aotOptions.Add ("llvm-path=" + QuoteFileName (sdkBinDirectory));
aotOptions.Add ("temp-path=" + QuoteFileName (tempDir));

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

Expand Down Expand Up @@ -470,50 +461,59 @@ 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] {aotOptions} {assembly}");
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
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ public void BuildAotApplication (string supportedAbis, bool enableLLVM, bool exp
// LLVM passes a direct path to libc.so, and we need to use the libc.so
// which corresponds to the *minimum* SDK version specified in AndroidManifest.xml
// Since we overrode minSdkVersion=16, that means we should use libc.so from android-16.
var rightLibc = new Regex (@"^\s*\[AOT\].*cross-.*--llvm.*,ld-flags=.*android-16.arch-.*.usr.lib.libc\.so", RegexOptions.Multiline);
var rightLibc = new Regex (@"\s*\[aot-compiler stdout].*android-16.arch-.*.usr.lib.libc\.so", RegexOptions.Multiline);
var m = rightLibc.Match (string.Join ("\n",b.LastBuildOutput));
Assert.IsTrue (m.Success, "AOT+LLVM should use libc.so from minSdkVersion!");
}
Expand Down

0 comments on commit 85c6ce4

Please sign in to comment.