diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt.cs index 445c04f1a5b..26cf0411498 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Text; using System.Threading; using System.Xml; using System.Xml.Linq; @@ -113,6 +114,7 @@ bool RunAapt (string commandLine, IList output) UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, + StandardOutputEncoding = Encoding.UTF8, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, WorkingDirectory = WorkingDirectory, diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2.cs index 26e5a5a1c4d..889926d8987 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Aapt2.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Xml; using System.Xml.Linq; +using System.Text; using Microsoft.Build.Utilities; using Microsoft.Build.Framework; using System.Text.RegularExpressions; @@ -53,6 +54,7 @@ protected bool RunAapt (string commandLine, IList output) UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, + StandardOutputEncoding = Encoding.UTF8, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, WorkingDirectory = WorkingDirectory, diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs index 966dbaa5bcf..4c1de77a341 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Text; using System.Threading; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -173,14 +174,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(); @@ -282,12 +275,14 @@ bool RunParallelAotCompiler (List nativeLibs) return; } - if (!RunAotCompiler (config.AssembliesPath, config.AotCompiler, config.AotOptions, config.AssemblyPath)) { + if (!RunAotCompiler (config.AssembliesPath, config.AotCompiler, config.AotOptions, config.AssemblyPath, config.ResponseFile)) { LogCodedError ("XA3001", "Could not AOT the assembly: {0}", Path.GetFileName (config.AssemblyPath)); Cancel (); return; } + File.Delete (config.ResponseFile); + lock (nativeLibs) nativeLibs.Add (config.OutputFile); } @@ -361,6 +356,11 @@ IEnumerable GetAotConfigs () if (!Directory.Exists (outdir)) Directory.CreateDirectory (outdir); + // dont use a full path if the outdir is withing the WorkingDirectory. + if (outdir.StartsWith (WorkingDirectory, StringComparison.InvariantCultureIgnoreCase)) { + outdir = outdir.Replace (WorkingDirectory + Path.DirectorySeparatorChar, string.Empty); + } + int level = 0; string toolPrefix = EnableLLVM ? NdkUtil.GetNdkToolPrefix (AndroidNdkDirectory, arch, level = GetNdkApiLevel (AndroidNdkDirectory, AndroidApiLevel, arch)) @@ -388,19 +388,19 @@ IEnumerable GetAotConfigs () var libs = new List(); 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); } @@ -422,25 +422,28 @@ IEnumerable GetAotConfigs () aotOptions.Add ("profile-only"); foreach (var p in Profiles) { var fp = Path.GetFullPath (p.ItemSpec); - aotOptions.Add ($"profile={GetShortPath (fp)}"); + aotOptions.Add ($"profile={fp}"); } } if (!string.IsNullOrEmpty (AotAdditionalArguments)) aotOptions.Add (AotAdditionalArguments); if (sequencePointsMode == SequencePointsMode.Offline) - aotOptions.Add ("msym-dir=" + GetShortPath (outdir)); + aotOptions.Add ($"msym-dir={outdir}"); if (AotMode != AotMode.Normal) aotOptions.Add (AotMode.ToString ().ToLowerInvariant ()); - aotOptions.Add ("outfile=" + GetShortPath (outputFile)); + aotOptions.Add ($"outfile={outputFile}"); aotOptions.Add ("asmwriter"); - aotOptions.Add ("mtriple=" + mtriple); - aotOptions.Add ("tool-prefix=" + GetShortPath (toolPrefix)); - aotOptions.Add ("ld-flags=" + ldFlags); - aotOptions.Add ("llvm-path=" + GetShortPath (sdkBinDirectory)); - aotOptions.Add ("temp-path=" + GetShortPath (tempDir)); + aotOptions.Add ($"mtriple={mtriple}"); + aotOptions.Add ($"tool-prefix={toolPrefix}"); + aotOptions.Add ($"ld-flags={ldFlags}"); + aotOptions.Add ($"llvm-path={sdkBinDirectory}"); + aotOptions.Add ($"temp-path={tempDir}"); - string aotOptionsStr = (EnableLLVM ? "--llvm " : "") + "--aot=" + string.Join (",", aotOptions); + // we need to quote the entire --aot arguments here to make sure it is parsed + // on windows as one argument. Otherwise it will be split up into multiple + // values, which wont work. + string aotOptionsStr = (EnableLLVM ? "--llvm " : "") + $"\"--aot={string.Join (",", aotOptions)}\""; if (!string.IsNullOrEmpty (ExtraAotOptions)) { aotOptionsStr += (aotOptions.Count > 0 ? "," : "") + ExtraAotOptions; @@ -460,23 +463,29 @@ IEnumerable GetAotConfigs () } var assembliesPath = Path.GetFullPath (Path.GetDirectoryName (resolvedPath)); - var assemblyPath = QuoteFileName (Path.GetFullPath (resolvedPath)); + var assemblyPath = Path.GetFullPath (resolvedPath); - yield return new Config (assembliesPath, QuoteFileName (aotCompiler), aotOptionsStr, assemblyPath, outputFile); + yield return new Config (assembliesPath, aotCompiler, aotOptionsStr, assemblyPath, outputFile, Path.Combine (tempDir, "response.txt")); } } } - bool RunAotCompiler (string assembliesPath, string aotCompiler, string aotOptions, string assembly) + bool RunAotCompiler (string assembliesPath, string aotCompiler, string aotOptions, string assembly, string responseFile) { var stdout_completed = new ManualResetEvent (false); var stderr_completed = new ManualResetEvent (false); + + using (var sw = new StreamWriter (responseFile, append: false, encoding: new UTF8Encoding (encoderShouldEmitUTF8Identifier: false))) { + sw.WriteLine (aotOptions + " " + QuoteFileName (assembly)); + } + var psi = new ProcessStartInfo () { - FileName = aotCompiler, - Arguments = aotOptions + " " + assembly, + FileName = QuoteFileName (aotCompiler), + Arguments = $"--response={QuoteFileName (responseFile)}", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, + StandardOutputEncoding = Encoding.UTF8, CreateNoWindow=true, WindowStyle=ProcessWindowStyle.Hidden, WorkingDirectory = WorkingDirectory, @@ -536,16 +545,18 @@ struct Config { public string AotOptions { get; } public string AssemblyPath { get; } public string OutputFile { get; } + public string ResponseFile { get; } public bool Valid { get; private set; } - public Config (string assembliesPath, string aotCompiler, string aotOptions, string assemblyPath, string outputFile) + public Config (string assembliesPath, string aotCompiler, string aotOptions, string assemblyPath, string outputFile, string responseFile) { AssembliesPath = assembliesPath; AotCompiler = aotCompiler; AotOptions = aotOptions; AssemblyPath = assemblyPath; OutputFile = outputFile; + ResponseFile = responseFile; Valid = true; } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 9447731df22..12ab4048706 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -732,9 +732,9 @@ public void BuildMkBundleApplicationReleaseAllAbi () [Test] [TestCaseSource (nameof (AotChecks))] [Category ("Minor")] - public void BuildAotApplication (string supportedAbis, bool enableLLVM, bool expectedResult) + public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult) { - var path = Path.Combine ("temp", string.Format ("BuildAotApplication_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult)); + var path = Path.Combine ("temp", string.Format ("BuildAotApplication AndÜmläüts_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult)); var proj = new XamarinAndroidApplicationProject () { IsRelease = true, BundleAssemblies = false, @@ -768,7 +768,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!"); } @@ -803,9 +803,9 @@ public void BuildAotApplication (string supportedAbis, bool enableLLVM, bool exp [Test] [TestCaseSource (nameof (AotChecks))] [Category ("Minor")] - public void BuildAotApplicationAndBundle (string supportedAbis, bool enableLLVM, bool expectedResult) + public void BuildAotApplicationAndBundleAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult) { - var path = Path.Combine ("temp", string.Format ("BuildAotApplicationAndBundle_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult)); + var path = Path.Combine ("temp", string.Format ("BuildAotApplicationAndBundle AndÜmläüts_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult)); var proj = new XamarinAndroidApplicationProject () { IsRelease = true, BundleAssemblies = true,