예제 #1
0
        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");
        }
예제 #2
0
        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);
        }