Example #1
0
        bool WriteFiles()
        {
            if (!Directory.Exists(Options.OutputDir))
            {
                Directory.CreateDirectory(Options.OutputDir);
            }

            foreach (var output in Output.Files)
            {
                var path = output.Key;

                var outputPath = Path.Combine(Options.OutputDir,
                                              Path.GetDirectoryName(path));

                // Make sure the target directory exists.
                Directory.CreateDirectory(outputPath);

                var fullPath = Path.Combine(outputPath, Path.GetFileName(path));

                var outputStream = output.Value;
                outputStream.Position = 0;

                using (var outputFile = File.Create(fullPath))
                    outputStream.CopyTo(outputFile);

                Diagnostics.Message("Generated: {0}", path);
            }

            if (Options.GeneratorKind == GeneratorKind.Java && Options.Compilation.Platform == TargetPlatform.Android)
            {
                Diagnostics.Message("Generating Java stubs...");
                var project = XamarinAndroidBuild.GenerateJavaStubsProject(Assemblies, Options.OutputDir);
                if (!MSBuild(project))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #2
0
        bool CreateAar()
        {
            var executableSuffix = Platform.IsWindows ? ".exe" : string.Empty;
            var jar        = Path.Combine(XamarinAndroid.JavaSdkPath, "bin", "jar" + executableSuffix);
            var classesDir = Path.Combine(Options.OutputDir, "classes");
            var androidDir = Path.Combine(Options.OutputDir, "android");
            var name       = Path.GetFileNameWithoutExtension(Project.Assemblies[0]).Replace('-', '_');

            var args = new List <string> {
                "cvf",
                Path.Combine(Options.OutputDir, name + ".aar"),
                $"-C {androidDir} ."
            };

            //Copy libmonosgen-2.0.so and libmonodroid.so
            const string libMonoSgen    = "libmonosgen-2.0.so";
            const string libMonoAndroid = "libmono-android.release.so";

            foreach (var abi in Directory.GetDirectories(XamarinAndroid.LibraryPath))
            {
                var abiDir = Path.Combine(androidDir, "jni", Path.GetFileName(abi));

                string libMonoSgenSourcePath = Path.Combine(abi, libMonoSgen);
                string libMonoSgenDestPath   = Path.Combine(abiDir, libMonoSgen);

                string libMonoAndroidSourcePath = Path.Combine(abi, libMonoAndroid);
                string libMonoAndroidDestPath   = Path.Combine(abiDir, "libmonodroid.so"); //NOTE: Xamarin.Android runtime uses different name from APK

                if (!File.Exists(libMonoSgenSourcePath) || !File.Exists(libMonoAndroidSourcePath))
                {
                    continue;
                }

                if (!Directory.Exists(abiDir))
                {
                    Directory.CreateDirectory(abiDir);
                }
                File.Copy(libMonoSgenSourcePath, libMonoSgenDestPath, true);
                File.Copy(libMonoAndroidSourcePath, libMonoAndroidDestPath, true);
            }

            //Copy JNA native libs
            foreach (var file in Directory.GetFiles(Path.Combine(FindDirectory("external"), "jna"), "android-*"))
            {
                using (var stream = File.OpenRead(file))
                    using (var zip = new ZipArchive(stream))
                    {
                        foreach (var entry in zip.Entries)
                        {
                            //Skip non-*.so files
                            if (!entry.FullName.EndsWith(".so", StringComparison.Ordinal))
                            {
                                continue;
                            }

                            var    arch = Path.GetFileNameWithoutExtension(file);
                            string abi;
                            switch (arch)
                            {
                            case "android-aarch64":
                                abi = "arm64-v8a";
                                break;

                            case "android-arm":
                                abi = "armeabi";
                                break;

                            case "android-armv7":
                                abi = "armeabi-v7a";
                                break;

                            case "android-x86-64":
                                abi = "x86_64";
                                break;

                            default:
                                abi = arch.Replace("android-", string.Empty);
                                break;
                            }

                            var abiDir = Path.Combine(androidDir, "jni", Path.GetFileName(abi));
                            if (!Directory.Exists(abiDir))
                            {
                                Directory.CreateDirectory(abiDir);
                            }

                            using (var zipEntryStream = entry.Open())
                                using (var fileStream = File.Create(Path.Combine(abiDir, entry.Name)))
                                {
                                    zipEntryStream.CopyTo(fileStream);
                                }
                        }
                    }
            }

            //Copy jar to android/classes.jar
            File.Copy(Path.Combine(Options.OutputDir, name + ".jar"), Path.Combine(androidDir, "classes.jar"), true);

            //Copy .NET assemblies
            var assembliesDir = Path.Combine(androidDir, "assets", "assemblies");

            if (!Directory.Exists(assembliesDir))
            {
                Directory.CreateDirectory(assembliesDir);
            }

            foreach (var assembly in Project.Assemblies)
            {
                File.Copy(assembly, Path.Combine(assembliesDir, Path.GetFileName(assembly)), true);
            }

            //Copy any referenced assemblies such as mscorlib.dll
            List <string> referencedAssemblies = new List <string>();

            foreach (var assembly in Assemblies)
            {
                foreach (var reference in assembly.GetReferencedAssemblies())
                {
                    if (!referencedAssemblies.Contains(reference.Name))
                    {
                        referencedAssemblies.Add(reference.Name);
                    }
                }
            }

            Diagnostics.Message("Linking assemblies...");

            //Performs Xamarin.Android build tasks such as Linking, Resource/Asset extraction, invoking aapt.
            var project = XamarinAndroidBuild.GeneratePackageProject(Assemblies, Options);

            if (!MSBuild(project))
            {
                return(false);
            }

            //Generate Resource.designer.dll
            var resourceDesigner = new ResourceDesignerGenerator
            {
                Assemblies       = Assemblies,
                MainAssembly     = Assemblies[0].Location,
                OutputDirectory  = assembliesDir,
                JavaResourceFile = Path.Combine(androidDir, "R.txt"),
            };

            resourceDesigner.Generate();

            if (!resourceDesigner.WriteAssembly())
            {
                //Let's generate CS if this failed
                string resourcePath = Path.Combine(Options.OutputDir, "Resource.designer.cs");
                resourceDesigner.WriteSource(resourcePath);
                throw new Exception($"Resource.designer.dll compilation failed! See {resourcePath} for details.");
            }

            //Runs some final processing on .NET assemblies
            XamarinAndroidBuild.ProcessAssemblies(Options.OutputDir);

            var invocation = string.Join(" ", args);
            var output     = Invoke(jar, invocation);

            return(output.ExitCode == 0);
        }
Example #3
0
        bool CreateJar()
        {
            var executableSuffix = Platform.IsWindows ? ".exe" : string.Empty;
            var jar        = Path.Combine(XamarinAndroid.JavaSdkPath, "bin", "jar" + executableSuffix);
            var classesDir = Path.Combine(Options.OutputDir, "classes");
            var name       = Path.GetFileNameWithoutExtension(Project.Assemblies[0]).Replace('-', '_');

            var args = new List <string> {
                "cf",
                Path.Combine(Options.OutputDir, name + ".jar"),
                $"-C {classesDir} ."
            };

            // On desktop Java, we need a few more files included
            if (Options.Compilation.Platform != TargetPlatform.Android)
            {
                //Copy native libs
                var platformDir = Path.Combine(classesDir, GetJnaPlatformDir());
                if (!Directory.Exists(platformDir))
                {
                    Directory.CreateDirectory(platformDir);
                }

                var libName = (Options.Compilation.Platform == TargetPlatform.Windows) ?
                              $"{name}.dll" : $"lib{name}.dylib";
                var libFile = Path.Combine(Options.OutputDir, libName);
                if (File.Exists(libFile))
                {
                    var outputFile = Path.Combine(platformDir, libName);
                    File.Copy(libFile, outputFile, true);
                }

                //Copy .NET assemblies
                var assembliesDir = Path.Combine(classesDir, "assemblies");
                if (!Directory.Exists(assembliesDir))
                {
                    Directory.CreateDirectory(assembliesDir);
                }

                foreach (var assembly in Project.Assemblies)
                {
                    File.Copy(assembly, Path.Combine(assembliesDir, Path.GetFileName(assembly)), true);
                }

                //Copy any referenced assemblies such as mscorlib.dll
                List <string> referencedAssemblies = new List <string>();
                foreach (var assembly in Assemblies)
                {
                    foreach (var reference in assembly.GetReferencedAssemblies())
                    {
                        if (!referencedAssemblies.Contains(reference.Name))
                        {
                            referencedAssemblies.Add(reference.Name);
                        }
                    }
                }

                foreach (var reference in referencedAssemblies)
                {
                    var referencePath = Path.Combine(MonoSdkPath, "lib", "mono", "4.5", reference + ".dll");
                    if (File.Exists(referencePath))
                    {
                        File.Copy(referencePath, Path.Combine(assembliesDir, reference + ".dll"), true);
                    }
                }

                // Copy the Mono runtime shared library to the JAR file
                var libDir = (Options.Compilation.Platform == TargetPlatform.Windows) ?
                             "bin" : "lib";

                switch (Options.Compilation.Platform)
                {
                case TargetPlatform.Windows:
                    libName = "mono-2.0-sgen.dll";
                    break;

                case TargetPlatform.MacOS:
                    libName = "libmonosgen-2.0.dylib";
                    break;

                case TargetPlatform.Linux:
                    libName = "libmonosgen-2.0.so";
                    break;

                default:
                    throw new NotImplementedException();
                }

                var monoLib = Path.Combine(MonoSdkPath, libDir, libName);

                if (!File.Exists(monoLib))
                {
                    throw new Exception($"Cannot find Mono runtime shared library: {monoLib}");
                }

                File.Copy(monoLib, Path.Combine(platformDir, libName), true);
            }

            //Embed JNA into our jar file
            //  If on Android, we do not need any native libraries
            var jnaJar = Path.Combine(FindDirectory("external"), "jna", "jna-4.4.0.jar");
            var filter = Options.Compilation.Platform == TargetPlatform.Android ?
                         entry => entry.Name.EndsWith(".class", StringComparison.Ordinal) :
                         default(Func <ZipArchiveEntry, bool>);

            XamarinAndroidBuild.ExtractJar(jnaJar, classesDir, filter);

            //Embed mono.android.jar into our jar file
            if (Options.Compilation.Platform == TargetPlatform.Android)
            {
                var monoAndroidJar = XamarinAndroid.FindAssembly("mono.android.jar");
                XamarinAndroidBuild.ExtractJar(monoAndroidJar, classesDir);

                //Look for other JAR file dependencies from the user's assemblies
                foreach (var assembly in Assemblies)
                {
                    var intermediateDir = Path.Combine(Options.OutputDir, XamarinAndroidBuild.IntermediateDir, Path.GetFileNameWithoutExtension(assembly.Location));
                    if (Directory.Exists(intermediateDir))
                    {
                        foreach (var dependency in Directory.GetFiles(intermediateDir, "*.jar", SearchOption.AllDirectories))
                        {
                            XamarinAndroidBuild.ExtractJar(dependency, classesDir);
                        }
                    }
                }
            }

            var invocation = string.Join(" ", args);
            var output     = Invoke(jar, invocation);

            return(output.ExitCode == 0);
        }