public void BuildBasicApplicationReleaseWithCustomAotProfile() { var proj = new XamarinAndroidApplicationProject() { IsRelease = true, AndroidEnableProfiledAot = true, }; proj.SetProperty(proj.ActiveConfigurationProperties, "AndroidExtraAotOptions", "--verbose"); byte [] custom_aot_profile; using (var stream = typeof(XamarinAndroidApplicationProject).Assembly.GetManifestResourceStream("Xamarin.ProjectTools.Resources.Base.custom.aotprofile")) { custom_aot_profile = new byte [stream.Length]; stream.Read(custom_aot_profile, 0, (int)stream.Length); } proj.OtherBuildItems.Add(new BuildItem("AndroidAotProfile", "custom.aotprofile") { BinaryContent = () => custom_aot_profile }); using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) { Assert.IsTrue(b.Build(proj), "Build should have succeeded."); StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Using profile data file.*custom\.aotprofile", b.LastBuildOutput, "Should use custom AOT profile", RegexOptions.IgnoreCase); StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Method.*emitted at", b.LastBuildOutput, "Should contain verbose AOT compiler output", RegexOptions.IgnoreCase); } }
public void BuildBasicApplicationReleaseProfiledAot() { var proj = new XamarinAndroidApplicationProject() { IsRelease = true, AndroidEnableProfiledAot = true, }; proj.SetProperty(proj.ActiveConfigurationProperties, "AndroidExtraAotOptions", "--verbose"); using (var b = CreateApkBuilder(Path.Combine("temp", TestName))) { Assert.IsTrue(b.Build(proj), "Build should have succeeded."); StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Using profile data file.*build.Xamarin.Android.startup\.aotprofile", b.LastBuildOutput, "Should use default AOT profile", RegexOptions.IgnoreCase); StringAssertEx.ContainsRegex(@"\[aot-compiler stdout\] Method.*emitted at", b.LastBuildOutput, "Should contain verbose AOT compiler output", RegexOptions.IgnoreCase); } }
public void BuildAotApplicationAndÜmläüts(string supportedAbis, bool enableLLVM, bool 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, AotAssemblies = true, }; proj.SetProperty(KnownProperties.TargetFrameworkVersion, "v5.1"); proj.SetAndroidSupportedAbis(supportedAbis); proj.SetProperty("EnableLLVM", enableLLVM.ToString()); bool checkMinLlvmPath = enableLLVM && (supportedAbis == "armeabi-v7a" || supportedAbis == "x86"); if (checkMinLlvmPath) { // Set //uses-sdk/@android:minSdkVersion so that LLVM uses the right libc.so proj.AndroidManifest = $@"<?xml version=""1.0"" encoding=""utf-8""?> <manifest xmlns:android=""http://schemas.android.com/apk/res/android"" android:versionCode=""1"" android:versionName=""1.0"" package=""{proj.PackageName}""> <uses-sdk android:minSdkVersion=""{Xamarin.Android.Tools.XABuildConfig.NDKMinimumApiAvailable}"" /> <application android:label=""{proj.ProjectName}""> </application> </manifest>"; } using (var b = CreateApkBuilder(path)) { if (!b.CrossCompilerAvailable(supportedAbis)) { Assert.Ignore($"Cross compiler for {supportedAbis} was not available"); } if (!b.GetSupportedRuntimes().Any(x => supportedAbis == x.Abi)) { Assert.Ignore($"Runtime for {supportedAbis} was not available."); } b.ThrowOnBuildFailure = false; Assert.AreEqual(expectedResult, b.Build(proj), "Build should have {0}.", expectedResult ? "succeeded" : "failed"); if (!expectedResult) { return; } //NOTE: Windows has shortened paths such as: C:\Users\myuser\ANDROI~3\ndk\PLATFO~1\AN3971~1\arch-x86\usr\lib\libc.so if (checkMinLlvmPath && !IsWindows) { bool ndk22OrNewer = false; if (Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainRelease(AndroidNdkPath, out Xamarin.Android.Tasks.NdkUtilOld.NdkVersion ndkVersion)) { ndk22OrNewer = ndkVersion.Version >= 22; } // 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. if (ndk22OrNewer) { // NDK r22 or newer store libc in [toolchain]/sysroot/usr/lib/[ARCH]/[API]/libc.so StringAssertEx.ContainsRegex(@"\s*\[aot-compiler stdout].*sysroot.*.usr.lib.*16.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!"); } else { StringAssertEx.ContainsRegex(@"\s*\[aot-compiler stdout].*android-16.arch-.*.usr.lib.libc\.so", b.LastBuildOutput, "AOT+LLVM should use libc.so from minSdkVersion!"); } } foreach (var abi in supportedAbis.Split(new char [] { ';' })) { var libapp = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "bundles", abi, "libmonodroid_bundle_app.so"); Assert.IsFalse(File.Exists(libapp), abi + " libmonodroid_bundle_app.so should not exist"); var assemblies = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "aot", abi, "libaot-UnnamedProject.dll.so"); Assert.IsTrue(File.Exists(assemblies), "{0} libaot-UnnamedProject.dll.so does not exist", abi); var apk = Path.Combine(Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "bin", "UnnamedProject.UnnamedProject.apk"); using (var zipFile = ZipHelper.OpenZip(apk)) { Assert.IsNotNull(ZipHelper.ReadFileFromZip(zipFile, string.Format("lib/{0}/libaot-UnnamedProject.dll.so", abi)), "lib/{0}/libaot-UnnamedProject.dll.so should be in the UnnamedProject.UnnamedProject.apk", abi); Assert.IsNotNull(ZipHelper.ReadFileFromZip(zipFile, "assemblies/UnnamedProject.dll"), "UnnamedProject.dll should be in the UnnamedProject.UnnamedProject.apk"); } } Assert.AreEqual(expectedResult, b.Build(proj), "Second Build should have {0}.", expectedResult ? "succeeded" : "failed"); Assert.IsTrue( b.Output.IsTargetSkipped("_CompileJava"), "the _CompileJava target should be skipped"); Assert.IsTrue( b.Output.IsTargetSkipped("_BuildApkEmbed"), "the _BuildApkEmbed target should be skipped"); } }
public void ApplicationRunsWithDebuggerAndBreaks(bool embedAssemblies, string fastDevType, bool allowDeltaInstall, string username) { AssertCommercialBuild(); AssertHasDevices(); var path = Path.Combine("temp", TestName); int userId = GetUserId(username); List <string> parameters = new List <string> (); if (userId >= 0) { parameters.Add($"AndroidDeviceUserId={userId}"); } if (SwitchUser(username)) { WaitFor(5); ClickButton("", "android:id/button1", "Yes continue"); } var lib = new XamarinAndroidLibraryProject { ProjectName = "Library1", Sources = { new BuildItem.Source("Foo.cs") { TextContent = () => @"public class Foo { public Foo () { } }" }, }, }; var app = new XamarinFormsAndroidApplicationProject { ProjectName = "App", IsRelease = false, EmbedAssembliesIntoApk = embedAssemblies, AndroidFastDeploymentType = fastDevType }; app.MainPage = app.MainPage.Replace("InitializeComponent ();", "InitializeComponent (); new Foo ();"); app.AddReference(lib); app.SetAndroidSupportedAbis("armeabi-v7a", "x86"); app.SetProperty(KnownProperties._AndroidAllowDeltaInstall, allowDeltaInstall.ToString()); app.SetDefaultTargetDevice(); using (var libBuilder = CreateDllBuilder(Path.Combine(path, lib.ProjectName))) using (var appBuilder = CreateApkBuilder(Path.Combine(path, app.ProjectName))) { Assert.True(libBuilder.Build(lib), "Library should have built."); SetTargetFrameworkAndManifest(app, appBuilder); Assert.True(appBuilder.Install(app, parameters: parameters.ToArray()), "App should have installed."); if (!embedAssemblies) { // Check that we deployed .pdb files StringAssertEx.ContainsRegex($@"NotifySync CopyFile.+{app.ProjectName}\.pdb", appBuilder.LastBuildOutput, $"{app.ProjectName}.pdb should be deployed!"); StringAssertEx.ContainsRegex($@"NotifySync CopyFile.+{lib.ProjectName}\.pdb", appBuilder.LastBuildOutput, $"{lib.ProjectName}.pdb should be deployed!"); } int breakcountHitCount = 0; ManualResetEvent resetEvent = new ManualResetEvent(false); var sw = new Stopwatch(); // setup the debugger var session = new SoftDebuggerSession(); session.Breakpoints = new BreakpointStore { { Path.Combine(Root, appBuilder.ProjectDirectory, "MainActivity.cs"), 20 }, { Path.Combine(Root, appBuilder.ProjectDirectory, "MainPage.xaml.cs"), 14 }, { Path.Combine(Root, appBuilder.ProjectDirectory, "MainPage.xaml.cs"), 19 }, { Path.Combine(Root, appBuilder.ProjectDirectory, "App.xaml.cs"), 12 }, { Path.Combine(Root, libBuilder.ProjectDirectory, "Foo.cs"), 4 }, }; session.TargetHitBreakpoint += (sender, e) => { TestContext.WriteLine($"BREAK {e.Type}, {e.Backtrace.GetFrame (0)}"); breakcountHitCount++; session.Continue(); }; var rnd = new Random(); int port = rnd.Next(10000, 20000); TestContext.Out.WriteLine($"{port}"); var args = new SoftDebuggerConnectArgs("", IPAddress.Loopback, port) { MaxConnectionAttempts = 10, }; var startInfo = new SoftDebuggerStartInfo(args) { WorkingDirectory = Path.Combine(appBuilder.ProjectDirectory, app.IntermediateOutputPath, "android", "assets"), }; var options = new DebuggerSessionOptions() { EvaluationOptions = EvaluationOptions.DefaultOptions, }; options.EvaluationOptions.UseExternalTypeResolver = true; ClearAdbLogcat(); appBuilder.BuildLogFile = "run.log"; parameters.Add($"AndroidSdbTargetPort={port}"); parameters.Add($"AndroidSdbHostPort={port}"); parameters.Add("AndroidAttachDebugger=True"); Assert.True(appBuilder.RunTarget(app, "_Run", doNotCleanupOnUpdate: true, parameters: parameters.ToArray()), "Project should have run."); Assert.IsTrue(WaitForDebuggerToStart(Path.Combine(Root, appBuilder.ProjectDirectory, "logcat.log")), "Activity should have started"); // we need to give a bit of time for the debug server to start up. WaitFor(2000); session.LogWriter += (isStderr, text) => { Console.WriteLine(text); }; session.OutputWriter += (isStderr, text) => { Console.WriteLine(text); }; session.DebugWriter += (level, category, message) => { Console.WriteLine(message); }; session.Run(startInfo, options); WaitFor(TimeSpan.FromSeconds(30), () => session.IsConnected); Assert.True(session.IsConnected, "Debugger should have connected but it did not."); // we need to wait here for a while to allow the breakpoints to hit // but we need to timeout TimeSpan timeout = TimeSpan.FromSeconds(60); int expected = 4; while (session.IsConnected && breakcountHitCount < 3 && timeout >= TimeSpan.Zero) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } WaitFor(2000); Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}"); breakcountHitCount = 0; ClearAdbLogcat(); ClickButton(app.PackageName, "myXFButton", "CLICK ME"); while (session.IsConnected && breakcountHitCount < 1 && timeout >= TimeSpan.Zero) { Thread.Sleep(10); timeout = timeout.Subtract(TimeSpan.FromMilliseconds(10)); } expected = 1; Assert.AreEqual(expected, breakcountHitCount, $"Should have hit {expected} breakpoints. Only hit {breakcountHitCount}"); appBuilder.BuildLogFile = "uninstall.log"; Assert.True(appBuilder.Uninstall(app), "Project should have uninstalled."); session.Exit(); } }