public void DotNetIncremental() { // Setup dependencies App A -> Lib B var path = Path.Combine("temp", TestName); var libB = new XASdkProject(outputType: "Library") { ProjectName = "LibraryB" }; libB.Sources.Clear(); libB.Sources.Add(new BuildItem.Source("Foo.cs") { TextContent = () => "public class Foo { }", }); // Will save the project, does not need to build it CreateDotNetBuilder(libB, Path.Combine(path, libB.ProjectName)); var appA = new XASdkProject { ProjectName = "AppA", Sources = { new BuildItem.Source("Bar.cs") { TextContent = () => "public class Bar : Foo { }", } } }; appA.AddReference(libB); var appBuilder = CreateDotNetBuilder(appA, Path.Combine(path, appA.ProjectName)); Assert.IsTrue(appBuilder.Build(), $"{appA.ProjectName} should succeed"); appBuilder.AssertTargetIsNotSkipped("CoreCompile"); // Build again, no changes Assert.IsTrue(appBuilder.Build(), $"{appA.ProjectName} should succeed"); appBuilder.AssertTargetIsSkipped("CoreCompile"); }
public void DotNetBuildLibrary(bool isRelease, bool duplicateAar) { var path = Path.Combine("temp", TestName); var env_var = "MY_ENVIRONMENT_VAR"; var env_val = "MY_VALUE"; // Setup dependencies App A -> Lib B -> Lib C var libC = new XASdkProject(outputType: "Library") { ProjectName = "LibraryC", IsRelease = isRelease, Sources = { new BuildItem.Source("Bar.cs") { TextContent = () => "public class Bar { }", } } }; libC.OtherBuildItems.Add(new AndroidItem.AndroidAsset("Assets\\bar\\bar.txt") { BinaryContent = () => Array.Empty <byte> (), }); var activity = libC.Sources.FirstOrDefault(s => s.Include() == "MainActivity.cs"); if (activity != null) { libC.Sources.Remove(activity); } var libCBuilder = CreateDotNetBuilder(libC, Path.Combine(path, libC.ProjectName)); Assert.IsTrue(libCBuilder.Build(), $"{libC.ProjectName} should succeed"); var libB = new XASdkProject(outputType: "Library") { ProjectName = "LibraryB", IsRelease = isRelease, Sources = { new BuildItem.Source("Foo.cs") { TextContent = () => "public class Foo : Bar { }", } } }; libB.OtherBuildItems.Add(new AndroidItem.AndroidAsset("Assets\\foo\\foo.txt") { BinaryContent = () => Array.Empty <byte> (), }); libB.OtherBuildItems.Add(new AndroidItem.AndroidResource("Resources\\layout\\MyLayout.axml") { TextContent = () => "<?xml version=\"1.0\" encoding=\"utf-8\" ?><LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" />" }); libB.OtherBuildItems.Add(new AndroidItem.AndroidResource("Resources\\raw\\bar.txt") { BinaryContent = () => Array.Empty <byte> (), }); libB.OtherBuildItems.Add(new AndroidItem.AndroidEnvironment("env.txt") { TextContent = () => $"{env_var}={env_val}", }); libB.OtherBuildItems.Add(new AndroidItem.AndroidEnvironment("sub\\directory\\env.txt") { TextContent = () => $"{env_var}={env_val}", }); libB.OtherBuildItems.Add(new AndroidItem.AndroidLibrary("sub\\directory\\foo.jar") { BinaryContent = () => Convert.FromBase64String(InlineData.JavaClassesJarBase64), }); libB.OtherBuildItems.Add(new AndroidItem.AndroidLibrary("sub\\directory\\arm64-v8a\\libfoo.so") { BinaryContent = () => Array.Empty <byte> (), }); libB.OtherBuildItems.Add(new AndroidItem.AndroidLibrary("libfoo.so") { MetadataValues = "Link=x86\\libfoo.so", BinaryContent = () => Array.Empty <byte> (), }); libB.AddReference(libC); activity = libB.Sources.FirstOrDefault(s => s.Include() == "MainActivity.cs"); if (activity != null) { libB.Sources.Remove(activity); } var libBBuilder = CreateDotNetBuilder(libB, Path.Combine(path, libB.ProjectName)); Assert.IsTrue(libBBuilder.Build(), $"{libB.ProjectName} should succeed"); // Check .aar file for class library var aarPath = Path.Combine(FullProjectDirectory, libB.OutputPath, $"{libB.ProjectName}.aar"); FileAssert.Exists(aarPath); using (var aar = ZipHelper.OpenZip(aarPath)) { aar.AssertContainsEntry(aarPath, "assets/foo/foo.txt"); aar.AssertContainsEntry(aarPath, "res/layout/mylayout.xml"); aar.AssertContainsEntry(aarPath, "res/raw/bar.txt"); aar.AssertContainsEntry(aarPath, ".net/__res_name_case_map.txt"); aar.AssertContainsEntry(aarPath, ".net/env/190E30B3D205731E.env"); aar.AssertContainsEntry(aarPath, ".net/env/2CBDAB7FEEA94B19.env"); aar.AssertContainsEntry(aarPath, "libs/A1AFA985571E728E.jar"); aar.AssertContainsEntry(aarPath, "jni/arm64-v8a/libfoo.so"); aar.AssertContainsEntry(aarPath, "jni/x86/libfoo.so"); } // Check EmbeddedResource files do not exist var assemblyPath = Path.Combine(FullProjectDirectory, libB.OutputPath, $"{libB.ProjectName}.dll"); FileAssert.Exists(assemblyPath); using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath)) { Assert.AreEqual(0, assembly.MainModule.Resources.Count); } var appA = new XASdkProject { ProjectName = "AppA", IsRelease = isRelease, Sources = { new BuildItem.Source("Bar.cs") { TextContent = () => "public class Bar : Foo { }", } } }; appA.AddReference(libB); if (duplicateAar) { // Test a duplicate @(AndroidLibrary) item with the same path of LibraryB.aar appA.OtherBuildItems.Add(new AndroidItem.AndroidLibrary(aarPath)); } var appBuilder = CreateDotNetBuilder(appA, Path.Combine(path, appA.ProjectName)); Assert.IsTrue(appBuilder.Build(), $"{appA.ProjectName} should succeed"); // Check .apk for assets, res, and native libraries var apkPath = Path.Combine(FullProjectDirectory, appA.OutputPath, $"{appA.PackageName}.apk"); FileAssert.Exists(apkPath); using (var apk = ZipHelper.OpenZip(apkPath)) { apk.AssertContainsEntry(apkPath, "assets/foo/foo.txt"); apk.AssertContainsEntry(apkPath, "assets/bar/bar.txt"); apk.AssertContainsEntry(aarPath, "res/layout/mylayout.xml"); apk.AssertContainsEntry(apkPath, "res/raw/bar.txt"); apk.AssertContainsEntry(apkPath, "lib/arm64-v8a/libfoo.so"); apk.AssertContainsEntry(apkPath, "lib/x86/libfoo.so"); } // Check classes.dex contains foo.jar var intermediate = Path.Combine(FullProjectDirectory, appA.IntermediateOutputPath); var dexFile = Path.Combine(intermediate, "android", "bin", "classes.dex"); FileAssert.Exists(dexFile); string className = "Lcom/xamarin/android/test/msbuildtest/JavaSourceJarTest;"; Assert.IsTrue(DexUtils.ContainsClass(className, dexFile, AndroidSdkPath), $"`{dexFile}` should include `{className}`!"); // Check environment variable var environmentFiles = EnvironmentHelper.GatherEnvironmentFiles(intermediate, "x86", required: true); var environmentVariables = EnvironmentHelper.ReadEnvironmentVariables(environmentFiles); Assert.IsTrue(environmentVariables.TryGetValue(env_var, out string actual), $"Environment should contain {env_var}"); Assert.AreEqual(env_val, actual, $"{env_var} should be {env_val}"); // Check Resource.designer.cs var resource_designer_cs = Path.Combine(intermediate, "Resource.designer.cs"); FileAssert.Exists(resource_designer_cs); var resource_designer_text = File.ReadAllText(resource_designer_cs); StringAssert.Contains("public const int MyLayout", resource_designer_text); }