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); }
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); }
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); }