Exemplo n.º 1
0
        void AddNativeLibraryToArchive(ZipArchiveEx apk, string abi, string filesystemPath, string inArchiveFileName)
        {
            string archivePath = $"lib/{abi}/{inArchiveFileName}";

            Log.LogDebugMessage($"Adding native library: {filesystemPath} (APK path: {archivePath})");
            apk.Archive.AddEntry(archivePath, File.OpenRead(filesystemPath), compressionMethod: GetCompressionMethod(archivePath));
        }
Exemplo n.º 2
0
        void AddRuntimeLibraries(ZipArchiveEx apk, string [] supportedAbis)
        {
            bool use_shared_runtime = String.Equals(UseSharedRuntime, "true", StringComparison.OrdinalIgnoreCase);

            foreach (var abi in supportedAbis)
            {
                string library = string.Format("libmono-android.{0}.so", _Debug ? "debug" : "release");
                AddNativeLibrary(apk, abi, library, "libmonodroid.so");

                foreach (ITaskItem item in ApplicationSharedLibraries)
                {
                    if (String.Compare(abi, item.GetMetadata("abi"), StringComparison.Ordinal) != 0)
                    {
                        continue;
                    }
                    AddNativeLibraryToArchive(apk, abi, item.ItemSpec, Path.GetFileName(item.ItemSpec));
                }

                if (!use_shared_runtime)
                {
                    // include the sgen
                    AddNativeLibrary(apk, abi, "libmonosgen-2.0.so");
                }
                AddBtlsLibs(apk, abi);
                AddProfilers(apk, abi);
            }
        }
Exemplo n.º 3
0
        void AddAssemblyConfigEntry(ZipArchiveEx apk, string assemblyPath, string configFile)
        {
            string inArchivePath = assemblyPath + Path.GetFileName(configFile);

            existingEntries.Remove(inArchivePath);

            if (!File.Exists(configFile))
            {
                return;
            }

            CompressionMethod compressionMethod = UncompressedMethod;

            if (apk.SkipExistingFile(configFile, inArchivePath, compressionMethod))
            {
                Log.LogDebugMessage($"Skipping {configFile} as the archive file is up to date.");
                return;
            }

            Log.LogDebugMessage($"Adding {configFile} as the archive file is out of date.");
            using (var source = File.OpenRead(configFile)) {
                var dest = new MemoryStream();
                source.CopyTo(dest);
                dest.WriteByte(0);
                dest.Position = 0;
                apk.Archive.AddEntry(inArchivePath, dest, compressionMethod);
            }
        }
Exemplo n.º 4
0
 void AddBtlsLibs(ZipArchiveEx apk, string abi)
 {
     if (string.Compare("btls", TlsProvider, StringComparison.OrdinalIgnoreCase) == 0)
     {
         AddNativeLibrary(apk, abi, "libmono-btls-shared.so");
     }
     // These are the other supported values
     //  * "default":
     //  * "legacy":
 }
Exemplo n.º 5
0
		void AddRuntimeLibraries (ZipArchiveEx apk, string [] supportedAbis)
		{
			foreach (var abi in supportedAbis) {
				foreach (ITaskItem item in ApplicationSharedLibraries) {
					if (String.Compare (abi, item.GetMetadata ("abi"), StringComparison.Ordinal) != 0)
						continue;
					AddNativeLibraryToArchive (apk, abi, item.ItemSpec, Path.GetFileName (item.ItemSpec));
				}
			}
		}
        public override bool Execute()
        {
            Log.LogDebugMessage("EmbeddedNativeLibraries Task");
            Log.LogDebugMessage("  OutputDirectory: {0}", OutputDirectory);
            Log.LogDebugTaskItems("  EmbeddedNativeLibraries:", EmbeddedNativeLibraries);

            var outDirInfo = new DirectoryInfo(OutputDirectory);

            // Copy files into _NativeLibraryImportsDirectoryName (native_library_imports) dir.
            if (!outDirInfo.Exists)
            {
                outDirInfo.Create();
            }
            foreach (var lib in EmbeddedNativeLibraries)
            {
                // seealso bug #3477 to find out why we use this method.
                var abi = MonoAndroidHelper.GetNativeLibraryAbi(lib);
                if (abi == null)
                {
                    Log.LogWarning(
                        subcategory:      string.Empty,
                        warningCode:      "XA4300",
                        helpKeyword:      string.Empty,
                        file:             lib.ItemSpec,
                        lineNumber:       0,
                        columnNumber:     0,
                        endLineNumber:    0,
                        endColumnNumber:  0,
                        message:          "Native library '{0}' will not be bundled because it has an unsupported ABI.",
                        messageArgs:      new [] {
                        lib.ItemSpec,
                    }
                        );
                    continue;
                }
                if (!outDirInfo.GetDirectories(abi).Any())
                {
                    outDirInfo.CreateSubdirectory(abi);
                }
                MonoAndroidHelper.CopyIfChanged(lib.ItemSpec, Path.Combine(OutputDirectory, abi, Path.GetFileName(lib.ItemSpec)));
            }

            var outpath = Path.Combine(outDirInfo.Parent.FullName, "__AndroidNativeLibraries__.zip");

            if (Files.ArchiveZip(outpath, f => {
                using (var zip = new ZipArchiveEx(f)) {
                    zip.AddDirectory(OutputDirectory, outDirInfo.Name);
                }
            }))
            {
                Log.LogDebugMessage("Saving contents to " + outpath);
            }

            return(true);
        }
Exemplo n.º 7
0
 void AddProfilers(ZipArchiveEx apk, string abi)
 {
     if (!string.IsNullOrEmpty(AndroidEmbedProfilers))
     {
         foreach (var profiler in ParseProfilers(AndroidEmbedProfilers))
         {
             var library = string.Format("libmono-profiler-{0}.so", profiler);
             AddNativeLibrary(apk, abi, library);
         }
     }
 }
Exemplo n.º 8
0
		bool AddFileToArchiveIfNewer (ZipArchiveEx apk, string file, string inArchivePath, CompressionMethod compressionMethod = CompressionMethod.Default)
		{
			existingEntries.Remove (inArchivePath);
			if (apk.SkipExistingFile (file, inArchivePath, compressionMethod)) {
				Log.LogDebugMessage ($"Skipping {file} as the archive file is up to date.");
				return false;
			}
			Log.LogDebugMessage ($"Adding {file} as the archive file is out of date.");
			apk.Archive.AddFile (file, inArchivePath, compressionMethod: compressionMethod);
			return true;
		}
Exemplo n.º 9
0
        /// <summary>
        /// aapt2 is putting AndroidManifest.xml in the root of the archive instead of at manifest/AndroidManifest.xml that bundletool expects.
        /// I see no way to change this behavior, so we can move the file for now:
        /// https://github.com/aosp-mirror/platform_frameworks_base/blob/e80b45506501815061b079dcb10bf87443bd385d/tools/aapt2/LoadedApk.h#L34
        /// </summary>
        protected override void FixupArchive(ZipArchiveEx zip)
        {
            var entry = zip.Archive.ReadEntry("AndroidManifest.xml");

            using (var stream = new MemoryStream()) {
                entry.Extract(stream);
                stream.Position = 0;
                zip.Archive.AddEntry("manifest/AndroidManifest.xml", stream);
                zip.Archive.DeleteEntry(entry);
                zip.Flush();
            }
        }
Exemplo n.º 10
0
        void AddNativeLibrariesFromAssemblies(ZipArchiveEx apk, string supportedAbis)
        {
            int count = 0;
            var abis  = supportedAbis.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);

            using (var res = new DirectoryAssemblyResolver(this.CreateTaskLogger(), loadDebugSymbols: false)) {
                foreach (var assembly in EmbeddedNativeLibraryAssemblies)
                {
                    res.Load(assembly.ItemSpec);
                }
                foreach (var assemblyPath in EmbeddedNativeLibraryAssemblies)
                {
                    var assembly = res.GetAssembly(assemblyPath.ItemSpec);
                    foreach (var mod in assembly.Modules)
                    {
                        var ressozip = mod.Resources.FirstOrDefault(r => r.Name == "__AndroidNativeLibraries__.zip") as EmbeddedResource;
                        if (ressozip == null)
                        {
                            continue;
                        }
                        var data = ressozip.GetResourceData();
                        using (var ms = new MemoryStream(data)) {
                            using (var zip = ZipArchive.Open(ms)) {
                                foreach (var e in zip.Where(x => abis.Any(a => x.FullName.Contains($"/{a}/"))))
                                {
                                    if (e.IsDirectory)
                                    {
                                        continue;
                                    }
                                    var key = e.FullName.Replace("native_library_imports", "lib");
                                    if (apk.Archive.Any(k => k.FullName == key))
                                    {
                                        Log.LogCodedWarning("4301", "Apk already contains the item {0}; ignoring.", key);
                                        continue;
                                    }
                                    using (var s = new MemoryStream()) {
                                        e.Extract(s);
                                        s.Position = 0;
                                        apk.Archive.AddEntry(s.ToArray(), key);
                                    }
                                }
                            }
                        }
                    }
                    count++;
                    if (count == ZipArchiveEx.ZipFlushLimit)
                    {
                        apk.Flush();
                        count = 0;
                    }
                }
            }
        }
Exemplo n.º 11
0
		void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemPath, string inArchiveFileName)
		{
			string archivePath = $"lib/{abi}/{inArchiveFileName}";
			existingEntries.Remove (archivePath);
			CompressionMethod compressionMethod = GetCompressionMethod (archivePath);
			if (apk.SkipExistingFile (filesystemPath, archivePath, compressionMethod)) {
				Log.LogDebugMessage ($"Skipping {filesystemPath} (APK path: {archivePath}) as it is up to date.");
				return;
			}
			Log.LogDebugMessage ($"Adding native library: {filesystemPath} (APK path: {archivePath})");
			apk.Archive.AddEntry (archivePath, File.OpenRead (filesystemPath), compressionMethod);
		}
Exemplo n.º 12
0
        public override bool RunTask()
        {
            var outDirInfo = new DirectoryInfo(OutputDirectory);

            // Copy files into _NativeLibraryImportsDirectoryName (native_library_imports) dir.
            if (!outDirInfo.Exists)
            {
                outDirInfo.Create();
            }
            foreach (var lib in EmbeddedNativeLibraries)
            {
                // seealso bug #3477 to find out why we use this method.
                var abi = MonoAndroidHelper.GetNativeLibraryAbi(lib);
                if (abi == null)
                {
                    Log.LogWarning(
                        subcategory:      string.Empty,
                        warningCode:      "XA4300",
                        helpKeyword:      string.Empty,
                        file:             lib.ItemSpec,
                        lineNumber:       0,
                        columnNumber:     0,
                        endLineNumber:    0,
                        endColumnNumber:  0,
                        message:          Properties.Resources.XA4300,
                        messageArgs:      new [] {
                        lib.ItemSpec,
                    }
                        );
                    continue;
                }
                if (!outDirInfo.GetDirectories(abi).Any())
                {
                    outDirInfo.CreateSubdirectory(abi);
                }
                MonoAndroidHelper.CopyIfChanged(lib.ItemSpec, Path.Combine(OutputDirectory, abi, Path.GetFileName(lib.ItemSpec)));
            }

            var outpath = Path.Combine(outDirInfo.Parent.FullName, "__AndroidNativeLibraries__.zip");

            if (Files.ArchiveZip(outpath, f => {
                using (var zip = new ZipArchiveEx(f)) {
                    zip.AddDirectory(OutputDirectory, "native_library_imports");
                }
            }))
            {
                Log.LogDebugMessage("Saving contents to " + outpath);
            }

            return(!Log.HasLoggedErrors);
        }
Exemplo n.º 13
0
        void AddAssemblyConfigEntry(ZipArchiveEx apk, string configFile)
        {
            if (!File.Exists(configFile))
            {
                return;
            }

            using (var source = File.OpenRead(configFile)) {
                var dest = new MemoryStream();
                source.CopyTo(dest);
                dest.WriteByte(0);
                dest.Position = 0;
                apk.Archive.AddEntry("assemblies/" + Path.GetFileName(configFile), dest, compressionMethod: CompressionMethod.Store);
            }
        }
Exemplo n.º 14
0
        void AddNativeLibrary(ZipArchiveEx apk, string abi, string filename, string inArchiveFileName = null)
        {
            string libPath = Path.Combine(MSBuildXamarinAndroidDirectory, "lib", abi);
            string path    = Path.Combine(libPath, filename);

            if (PreferNativeLibrariesWithDebugSymbols)
            {
                string debugPath = Path.Combine(libPath, Path.ChangeExtension(filename, ".d.so"));
                if (File.Exists(debugPath))
                {
                    path = debugPath;
                }
            }

            AddNativeLibraryToArchive(apk, abi, path, inArchiveFileName ?? filename);
        }
Exemplo n.º 15
0
        public override bool Execute()
        {
            if (!Directory.Exists(ClassesOutputDirectory))
            {
                Directory.CreateDirectory(ClassesOutputDirectory);
            }
            var result = base.Execute();

            if (!result)
            {
                return(result);
            }
            // compress all the class files
            using (var zip = new ZipArchiveEx(Path.Combine(ClassesOutputDirectory, "..", "classes.zip"), FileMode.OpenOrCreate))
                zip.AddDirectory(ClassesOutputDirectory, "", CompressionMethod.Store);
            return(result);
        }
Exemplo n.º 16
0
        /// <summary>
        /// aapt2 is putting AndroidManifest.xml in the root of the archive instead of at manifest/AndroidManifest.xml that bundletool expects.
        /// I see no way to change this behavior, so we can move the file for now:
        /// https://github.com/aosp-mirror/platform_frameworks_base/blob/e80b45506501815061b079dcb10bf87443bd385d/tools/aapt2/LoadedApk.h#L34
        /// </summary>
        protected override void FixupArchive(ZipArchiveEx zip)
        {
            if (!zip.Archive.ContainsEntry("AndroidManifest.xml"))
            {
                Log.LogDebugMessage($"No AndroidManifest.xml. Skipping Fixup");
                return;
            }
            var entry = zip.Archive.ReadEntry("AndroidManifest.xml");

            Log.LogDebugMessage($"Fixing up AndroidManifest.xml to be manifest/AndroidManifest.xml.");
            using (var stream = new MemoryStream()) {
                entry.Extract(stream);
                stream.Position = 0;
                zip.Archive.AddEntry("manifest/AndroidManifest.xml", stream);
                zip.Archive.DeleteEntry(entry);
                zip.Flush();
            }
        }
Exemplo n.º 17
0
        void AddRuntimeLibraries(ZipArchiveEx apk, string supportedAbis)
        {
            bool use_shared_runtime = String.Equals(UseSharedRuntime, "true", StringComparison.OrdinalIgnoreCase);
            var  abis = supportedAbis.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var abi in abis)
            {
                string library = string.Format("libmono-android.{0}.so", _Debug ? "debug" : "release");
                AddNativeLibrary(apk, abi, library, "libmonodroid.so");
                if (!use_shared_runtime)
                {
                    // include the sgen
                    AddNativeLibrary(apk, abi, "libmonosgen-2.0.so");
                }
                AddBtlsLibs(apk, abi);
                AddProfilers(apk, abi);
            }
        }
Exemplo n.º 18
0
        void AddNativeLibrary(ZipArchiveEx apk, string abi, string filename, string inArchiveFileName = null)
        {
            string libPath = Path.Combine(MSBuildXamarinAndroidDirectory, "lib", abi);
            string path    = Path.Combine(libPath, filename);

            if (PreferNativeLibrariesWithDebugSymbols)
            {
                string debugPath = Path.Combine(libPath, Path.ChangeExtension(filename, ".d.so"));
                if (File.Exists(debugPath))
                {
                    path = debugPath;
                }
            }

            string archivePath = string.Format("lib/{0}/{1}", abi, inArchiveFileName ?? filename);

            Log.LogDebugMessage($"Adding native library: {path} (APK path: {archivePath})");
            apk.Archive.AddEntry(archivePath, File.OpenRead(path));
        }
Exemplo n.º 19
0
        public override bool RunTask()
        {
            if (!Directory.Exists(ClassesOutputDirectory))
            {
                Directory.CreateDirectory(ClassesOutputDirectory);
            }
            var result = base.RunTask();

            if (!result)
            {
                return(result);
            }
            // compress all the class files
            if (!string.IsNullOrEmpty(ClassesZip))
            {
                using (var zip = new ZipArchiveEx(ClassesZip, FileMode.OpenOrCreate)) {
                    zip.AddDirectory(ClassesOutputDirectory, "", CompressionMethod.Store);
                }
            }
            return(result);
        }
Exemplo n.º 20
0
        private void AddGdbservers(ZipArchiveEx apk, ArchiveFileList files, string supportedAbis, AndroidDebugServer debugServer)
        {
            if (string.IsNullOrEmpty(AndroidNdkDirectory))
            {
                return;
            }

            var sdkBinDirectory = MonoAndroidHelper.GetOSBinPath();
            int count           = 0;

            foreach (var sabi in supportedAbis.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries))
            {
                var arch = GdbPaths.GetArchFromAbi(sabi);
                var abi  = GdbPaths.GetAbiFromArch(arch);
                if (abi == null)
                {
                    continue;
                }
                var debugServerFile = GdbPaths.GetDebugServerFileName(debugServer);
                if (files.Any(f => string.Equals(Path.GetFileName(f.Item1), debugServerFile, StringComparison.Ordinal) &&
                              string.Equals(f.Item2, "lib/" + sabi, StringComparison.Ordinal)))
                {
                    continue;
                }
                var entryName       = string.Format("lib/{0}/{1}", sabi, debugServerFile);
                var debugServerPath = GdbPaths.GetDebugServerPath(debugServer, arch, AndroidNdkDirectory, sdkBinDirectory);
                if (!File.Exists(debugServerPath))
                {
                    continue;
                }
                Log.LogDebugMessage("Adding {0} debug server '{1}' to the APK as '{2}'", sabi, debugServerPath, entryName);
                apk.Archive.AddEntry(entryName, File.OpenRead(debugServerPath));
                count++;
                if (count == ZipArchiveEx.ZipFlushLimit)
                {
                    apk.Flush();
                    count = 0;
                }
            }
        }
Exemplo n.º 21
0
        public override bool RunTask()
        {
            var outDirInfo = new DirectoryInfo(OutputDirectory);

            // Copy files into _LibraryProjectImportsDirectoryName (library_project_imports) dir.
            if (!outDirInfo.Exists)
            {
                outDirInfo.Create();
            }
            foreach (var sub in new string [] { "assets", "res", "java", "bin" })
            {
                var subdirInfo = new DirectoryInfo(Path.Combine(outDirInfo.FullName, sub));
                if (!subdirInfo.Exists)
                {
                    subdirInfo.Create();
                }
            }

            var compiledArchive = Path.Combine(FlatArchivesDirectory, "compiled.flata");

            if (File.Exists(compiledArchive))
            {
                Log.LogDebugMessage($"Coping: {compiledArchive} to {outDirInfo.FullName}");
                MonoAndroidHelper.CopyIfChanged(compiledArchive, Path.Combine(outDirInfo.FullName, "compiled.flata"));
            }

            var dir_sep = new char [] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };

            if (AndroidAssets != null)
            {
                var dstsub = Path.Combine(outDirInfo.FullName, "assets");
                if (!Directory.Exists(dstsub))
                {
                    Directory.CreateDirectory(dstsub);
                }
                foreach (var item in AndroidAssets)
                {
                    var path = item.GetMetadata("Link");
                    path = !string.IsNullOrWhiteSpace(path) ? path : item.ItemSpec;
                    var head = string.Join("\\", path.Split(dir_sep).TakeWhile(s => !s.Equals(MonoAndroidAssetsPrefix, StringComparison.OrdinalIgnoreCase)));
                    path = head.Length == path.Length ? path : path.Substring((head.Length == 0 ? 0 : head.Length + Path.DirectorySeparatorChar) + MonoAndroidAssetsPrefix.Length).TrimStart(dir_sep);
                    MonoAndroidHelper.CopyIfChanged(item.ItemSpec, Path.Combine(dstsub, path));
                }
            }
            // resources folders are converted to the structure that aapt accepts.
            foreach (var srcsub in Directory.GetDirectories(ResourceDirectory))
            {
                var dstsub = Path.Combine(outDirInfo.FullName, "res", Path.GetFileName(srcsub));
                if (!Directory.Exists(dstsub))
                {
                    Directory.CreateDirectory(dstsub);
                }
                foreach (var file in Directory.GetFiles(srcsub))
                {
                    var filename = Path.GetFileName(file);
                    MonoAndroidHelper.CopyIfChanged(file, Path.Combine(dstsub, Path.GetFileName(file)));
                }
            }
            if (RemovedAndroidResourceFiles != null)
            {
                foreach (var removedFile in RemovedAndroidResourceFiles)
                {
                    var removed = Path.Combine(outDirInfo.FullName, removedFile.ItemSpec);
                    if (File.Exists(removed))
                    {
                        File.Delete(removed);
                        Log.LogDebugMessage($"Removed: {removed}");
                    }
                }
            }
            if (AndroidJavaSources != null)
            {
                foreach (var item in AndroidJavaSources)
                {
                    MonoAndroidHelper.CopyIfChanged(item.ItemSpec, Path.Combine(outDirInfo.FullName, item.ItemSpec));
                }
            }
            if (AndroidJavaLibraries != null)
            {
                foreach (var item in AndroidJavaLibraries)
                {
                    MonoAndroidHelper.CopyIfChanged(item.ItemSpec, Path.Combine(outDirInfo.FullName, item.ItemSpec));
                }
            }

            var nameCaseMap = new StringWriter();

            // add resource case mapping descriptor to the archive.
            if (AndroidResourcesInThisExactProject != null && AndroidResourcesInThisExactProject.Any())
            {
                Log.LogMessage("writing __res_name_case_map.txt...");
                foreach (var res in AndroidResourcesInThisExactProject)
                {
                    nameCaseMap.WriteLine("{0};{1}", res.GetMetadata("LogicalName").Replace('\\', '/'), Path.Combine(Path.GetFileName(Path.GetDirectoryName(res.ItemSpec)), Path.GetFileName(res.ItemSpec)).Replace('\\', '/'));
                }
                File.WriteAllText(Path.Combine(outDirInfo.FullName, "__res_name_case_map.txt"), nameCaseMap.ToString());
            }

            var outpath  = Path.Combine(outDirInfo.Parent.FullName, "__AndroidLibraryProjects__.zip");
            var fileMode = File.Exists(outpath) ? FileMode.Open : FileMode.CreateNew;

            if (Files.ArchiveZipUpdate(outpath, f => {
                using (var zip = new ZipArchiveEx(f, fileMode)) {
                    zip.AddDirectory(outDirInfo.FullName, "library_project_imports");
                    if (RemovedAndroidResourceFiles != null)
                    {
                        foreach (var r in RemovedAndroidResourceFiles)
                        {
                            Log.LogDebugMessage($"Removed {r.ItemSpec} from {outpath}");
                            zip.RemoveFile("library_project_imports", r.ItemSpec);
                        }
                    }
                }
            }))
            {
                Log.LogDebugMessage("Saving contents to " + outpath);
            }

            return(!Log.HasLoggedErrors);
        }
Exemplo n.º 22
0
        void AddAssemblies(ZipArchiveEx apk, bool debug, bool compress, IDictionary <string, CompressedAssemblyInfo> compressedAssembliesInfo)
        {
            string sourcePath;

            AssemblyCompression.AssemblyData compressedAssembly = null;
            string compressedOutputDir = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(ApkOutputPath), "..", "lz4"));

            int count = 0;

            foreach (ITaskItem assembly in ResolvedUserAssemblies)
            {
                if (bool.TryParse(assembly.GetMetadata("AndroidSkipAddToPackage"), out bool value) && value)
                {
                    Log.LogDebugMessage($"Skipping {assembly.ItemSpec} due to 'AndroidSkipAddToPackage' == 'true' ");
                    continue;
                }
                if (MonoAndroidHelper.IsReferenceAssembly(assembly.ItemSpec))
                {
                    Log.LogCodedWarning("XA0107", assembly.ItemSpec, 0, Properties.Resources.XA0107, assembly.ItemSpec);
                }

                sourcePath = CompressAssembly(assembly);

                // Add assembly
                var assemblyPath = GetAssemblyPath(assembly, frameworkAssembly: false);
                AddFileToArchiveIfNewer(apk, sourcePath, assemblyPath + Path.GetFileName(assembly.ItemSpec), compressionMethod: UncompressedMethod);

                // Try to add config if exists
                var config = Path.ChangeExtension(assembly.ItemSpec, "dll.config");
                AddAssemblyConfigEntry(apk, assemblyPath, config);

                // Try to add symbols if Debug
                if (debug)
                {
                    var symbols = Path.ChangeExtension(assembly.ItemSpec, "dll.mdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, assemblyPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }

                    symbols = Path.ChangeExtension(assembly.ItemSpec, "pdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, assemblyPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }
                }
                count++;
                if (count >= ZipArchiveEx.ZipFlushFilesLimit)
                {
                    apk.Flush();
                    count = 0;
                }
            }

            count = 0;
            // Add framework assemblies
            foreach (ITaskItem assembly in ResolvedFrameworkAssemblies)
            {
                if (bool.TryParse(assembly.GetMetadata("AndroidSkipAddToPackage"), out bool value) && value)
                {
                    Log.LogDebugMessage($"Skipping {assembly.ItemSpec} due to 'AndroidSkipAddToPackage' == 'true' ");
                    continue;
                }

                if (MonoAndroidHelper.IsReferenceAssembly(assembly.ItemSpec))
                {
                    Log.LogCodedWarning("XA0107", assembly.ItemSpec, 0, Properties.Resources.XA0107, assembly.ItemSpec);
                }

                sourcePath = CompressAssembly(assembly);
                var assemblyPath = GetAssemblyPath(assembly, frameworkAssembly: true);
                AddFileToArchiveIfNewer(apk, sourcePath, assemblyPath + Path.GetFileName(assembly.ItemSpec), compressionMethod: UncompressedMethod);
                var config = Path.ChangeExtension(assembly.ItemSpec, "dll.config");
                AddAssemblyConfigEntry(apk, assemblyPath, config);
                // Try to add symbols if Debug
                if (debug)
                {
                    var symbols = Path.ChangeExtension(assembly.ItemSpec, "dll.mdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, assemblyPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }

                    symbols = Path.ChangeExtension(assembly.ItemSpec, "pdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, assemblyPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }
                }
                count++;
                if (count >= ZipArchiveEx.ZipFlushFilesLimit)
                {
                    apk.Flush();
                    count = 0;
                }
            }

            void EnsureCompressedAssemblyData(string sourcePath, uint descriptorIndex)
            {
                if (compressedAssembly == null)
                {
                    compressedAssembly = new AssemblyCompression.AssemblyData(sourcePath, descriptorIndex);
                }
                else
                {
                    compressedAssembly.SetData(sourcePath, descriptorIndex);
                }
            }

            string CompressAssembly(ITaskItem assembly)
            {
                if (!compress)
                {
                    return(assembly.ItemSpec);
                }

                if (bool.TryParse(assembly.GetMetadata("AndroidSkipCompression"), out bool value) && value)
                {
                    Log.LogDebugMessage($"Skipping compression of {assembly.ItemSpec} due to 'AndroidSkipCompression' == 'true' ");
                    return(assembly.ItemSpec);
                }

                var key = CompressedAssemblyInfo.GetDictionaryKey(assembly);

                if (compressedAssembliesInfo.TryGetValue(key, out CompressedAssemblyInfo info) && info != null)
                {
                    EnsureCompressedAssemblyData(assembly.ItemSpec, info.DescriptorIndex);
                    string assemblyOutputDir;
                    string subDirectory = assembly.GetMetadata("DestinationSubDirectory");
                    if (!String.IsNullOrEmpty(subDirectory))
                    {
                        assemblyOutputDir = Path.Combine(compressedOutputDir, subDirectory);
                    }
                    else
                    {
                        assemblyOutputDir = compressedOutputDir;
                    }
                    AssemblyCompression.CompressionResult result = AssemblyCompression.Compress(compressedAssembly, assemblyOutputDir);
                    if (result != AssemblyCompression.CompressionResult.Success)
                    {
                        switch (result)
                        {
                        case AssemblyCompression.CompressionResult.EncodingFailed:
                            Log.LogMessage($"Failed to compress {assembly.ItemSpec}");
                            break;

                        case AssemblyCompression.CompressionResult.InputTooBig:
                            Log.LogMessage($"Input assembly {assembly.ItemSpec} exceeds maximum input size");
                            break;

                        default:
                            Log.LogMessage($"Unknown error compressing {assembly.ItemSpec}");
                            break;
                        }
                        return(assembly.ItemSpec);
                    }
                    return(compressedAssembly.DestinationPath);
                }
                else
                {
                    Log.LogDebugMessage($"Assembly missing from {nameof (CompressedAssemblyInfo)}: {key}");
                }

                return(assembly.ItemSpec);
            }
        }
Exemplo n.º 23
0
        void ExecuteWithAbi(string [] supportedAbis, string apkInputPath, string apkOutputPath, bool debug, bool compress, IDictionary <string, CompressedAssemblyInfo> compressedAssembliesInfo)
        {
            if (InterpreterEnabled)
            {
                foreach (string abi in supportedAbis)
                {
                    if (String.Compare("x86", abi, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        Log.LogCodedError("XA0124", Properties.Resources.XA0124);
                        return;
                    }
                }
            }

            ArchiveFileList files   = new ArchiveFileList();
            bool            refresh = true;

            if (apkInputPath != null && File.Exists(apkInputPath) && !File.Exists(apkOutputPath))
            {
                Log.LogDebugMessage($"Copying {apkInputPath} to {apkInputPath}");
                File.Copy(apkInputPath, apkOutputPath, overwrite: true);
                refresh = false;
            }
            using (var apk = new ZipArchiveEx(apkOutputPath, File.Exists(apkOutputPath) ? FileMode.Open : FileMode.Create)) {
                if (refresh)
                {
                    for (long i = 0; i < apk.Archive.EntryCount; i++)
                    {
                        ZipEntry e = apk.Archive.ReadEntry((ulong)i);
                        Log.LogDebugMessage($"Registering item {e.FullName}");
                        existingEntries.Add(e.FullName);
                    }
                }
                if (apkInputPath != null && File.Exists(apkInputPath) && refresh)
                {
                    var lastWriteOutput = File.Exists(apkOutputPath) ? File.GetLastWriteTimeUtc(apkOutputPath) : DateTime.MinValue;
                    var lastWriteInput  = File.GetLastWriteTimeUtc(apkInputPath);
                    using (var packaged = new ZipArchiveEx(apkInputPath, FileMode.Open)) {
                        foreach (var entry in packaged.Archive)
                        {
                            // NOTE: aapt2 is creating zip entries on Windows such as `assets\subfolder/asset2.txt`
                            var entryName = entry.FullName;
                            if (entryName.Contains("\\"))
                            {
                                entryName = entryName.Replace('\\', '/');
                                Log.LogDebugMessage($"Fixing up malformed entry `{entry.FullName}` -> `{entryName}`");
                            }
                            Log.LogDebugMessage($"Deregistering item {entryName}");
                            existingEntries.Remove(entryName);
                            if (lastWriteInput <= lastWriteOutput)
                            {
                                continue;
                            }
                            if (apk.Archive.ContainsEntry(entryName))
                            {
                                ZipEntry e = apk.Archive.ReadEntry(entryName);
                                // check the CRC values as the ModifiedDate is always 01/01/1980 in the aapt generated file.
                                if (entry.CRC == e.CRC && entry.CompressedSize == e.CompressedSize)
                                {
                                    Log.LogDebugMessage($"Skipping {entryName} from {apkInputPath} as its up to date.");
                                    continue;
                                }
                            }
                            var ms = new MemoryStream();
                            entry.Extract(ms);
                            Log.LogDebugMessage($"Refreshing {entryName} from {apkInputPath}");
                            apk.Archive.AddStream(ms, entryName, compressionMethod: entry.CompressionMethod);
                        }
                    }
                }
                apk.FixupWindowsPathSeparators((a, b) => Log.LogDebugMessage($"Fixing up malformed entry `{a}` -> `{b}`"));

                // Add classes.dx
                foreach (var dex in DalvikClasses)
                {
                    string apkName = dex.GetMetadata("ApkName");
                    string dexPath = string.IsNullOrWhiteSpace(apkName) ? Path.GetFileName(dex.ItemSpec) : apkName;
                    AddFileToArchiveIfNewer(apk, dex.ItemSpec, DalvikPath + dexPath);
                }

                if (EmbedAssemblies && !BundleAssemblies)
                {
                    AddAssemblies(apk, debug, compress, compressedAssembliesInfo);
                }

                AddRuntimeLibraries(apk, supportedAbis);
                apk.Flush();
                AddNativeLibraries(files, supportedAbis);
                AddAdditionalNativeLibraries(files, supportedAbis);

                if (TypeMappings != null)
                {
                    foreach (ITaskItem typemap in TypeMappings)
                    {
                        AddFileToArchiveIfNewer(apk, typemap.ItemSpec, RootPath + Path.GetFileName(typemap.ItemSpec), compressionMethod: UncompressedMethod);
                    }
                }

                int count = 0;
                foreach (var file in files)
                {
                    var item = Path.Combine(file.archivePath.Replace(Path.DirectorySeparatorChar, '/'));
                    existingEntries.Remove(item);
                    CompressionMethod compressionMethod = GetCompressionMethod(file.filePath);
                    if (apk.SkipExistingFile(file.filePath, item, compressionMethod))
                    {
                        Log.LogDebugMessage($"Skipping {file.filePath} as the archive file is up to date.");
                        continue;
                    }
                    Log.LogDebugMessage("\tAdding {0}", file.filePath);
                    apk.Archive.AddFile(file.filePath, item, compressionMethod: compressionMethod);
                    count++;
                    if (count >= ZipArchiveEx.ZipFlushFilesLimit)
                    {
                        apk.Flush();
                        count = 0;
                    }
                }

                var jarFiles = (JavaSourceFiles != null) ? JavaSourceFiles.Where(f => f.ItemSpec.EndsWith(".jar")) : null;
                if (jarFiles != null && JavaLibraries != null)
                {
                    jarFiles = jarFiles.Concat(JavaLibraries);
                }
                else if (JavaLibraries != null)
                {
                    jarFiles = JavaLibraries;
                }

                var libraryProjectJars = MonoAndroidHelper.ExpandFiles(LibraryProjectJars)
                                         .Where(jar => !MonoAndroidHelper.IsEmbeddedReferenceJar(jar));

                var jarFilePaths = libraryProjectJars.Concat(jarFiles != null ? jarFiles.Select(j => j.ItemSpec) : Enumerable.Empty <string> ());
                jarFilePaths = MonoAndroidHelper.DistinctFilesByContent(jarFilePaths);

                count = 0;
                foreach (var jarFile in jarFilePaths)
                {
                    using (var stream = File.OpenRead(jarFile))
                        using (var jar = ZipArchive.Open(stream)) {
                            foreach (var jarItem in jar)
                            {
                                if (jarItem.IsDirectory)
                                {
                                    continue;
                                }
                                var name = jarItem.FullName;
                                if (!PackagingUtils.CheckEntryForPackaging(name))
                                {
                                    continue;
                                }
                                var path = RootPath + name;
                                existingEntries.Remove(path);
                                if (apk.SkipExistingEntry(jarItem, path))
                                {
                                    Log.LogDebugMessage($"Skipping {path} as the archive file is up to date.");
                                    continue;
                                }
                                if (apk.Archive.Any(e => e.FullName == path))
                                {
                                    Log.LogDebugMessage("Failed to add jar entry {0} from {1}: the same file already exists in the apk", name, Path.GetFileName(jarFile));
                                    continue;
                                }
                                byte [] data;
                                using (var d = new MemoryStream()) {
                                    jarItem.Extract(d);
                                    data = d.ToArray();
                                }
                                Log.LogDebugMessage($"Adding {path} as the archive file is out of date.");
                                apk.Archive.AddEntry(data, path);
                            }
                        }
                    count++;
                    if (count >= ZipArchiveEx.ZipFlushFilesLimit)
                    {
                        apk.Flush();
                        count = 0;
                    }
                }
                // Clean up Removed files.
                foreach (var entry in existingEntries)
                {
                    Log.LogDebugMessage($"Removing {entry} as it is not longer required.");
                    apk.Archive.DeleteEntry(entry);
                }
                apk.Flush();
                FixupArchive(apk);
            }
        }
Exemplo n.º 24
0
 protected virtual void FixupArchive(ZipArchiveEx zip)
 {
 }
Exemplo n.º 25
0
        void AddNativeLibrary(ZipArchiveEx apk, string abi, string filename)
        {
            var path = Path.Combine(MSBuildXamarinAndroidDirectory, "lib", abi, filename);

            apk.Archive.AddEntry(string.Format("lib/{0}/{1}", abi, filename), File.OpenRead(path));
        }
Exemplo n.º 26
0
        public override bool RunTask()
        {
            if (LibraryProjectPropertiesFiles.Length == 0 && LibraryProjectZipFiles.Length == 0)
            {
                return(true);
            }

            var outDirInfo = new DirectoryInfo(OutputDirectory);

            // Copy files into _LibraryProjectImportsDirectoryName (library_project_imports) dir.
            if (!outDirInfo.Exists)
            {
                outDirInfo.Create();
            }

            var projectsResolved = ResolveLibraryProjectReferences(LibraryProjectPropertiesFiles.Select(p => Path.GetFullPath(p.ItemSpec)));
            var imports          = projectsResolved.Concat(LibraryProjectZipFiles.Select(p => p.ItemSpec));

            foreach (var p in imports)
            {
                // note that imports could contain file name that neither of build items contains
                // (it may be one of those resolved references in project.properties).
                // Also non-zip files are now specified in full path.
                if (!LibraryProjectZipFiles.Any(l => l.ItemSpec == p))
                {
                    // project.properties

                    var fileInfo = new FileInfo(p);
                    if (!fileInfo.Exists)
                    {
                        throw new InvalidOperationException(String.Format("Library project properties file '{0}' does not exist.", p));
                    }
                    var bindir = fileInfo.Directory.FullName;

                    CopyLibraryContent(bindir, false);
                }
                else
                {
                    // zip
                    string tmpname = Path.Combine(Path.GetTempPath(), "monodroid_import_" + Guid.NewGuid().ToString());
                    try {
                        Directory.CreateDirectory(tmpname);
                        var archive = ZipArchive.Open(p, FileMode.Open);
                        archive.ExtractAll(tmpname);

                        if (!CopyLibraryContent(tmpname, p.EndsWith(".aar", StringComparison.OrdinalIgnoreCase)))
                        {
                            return(false);
                        }
                    } finally {
                        Directory.Delete(tmpname, true);
                    }
                }
            }

            var outpath = Path.Combine(outDirInfo.Parent.FullName, "__AndroidLibraryProjects__.zip");

            if (Files.ArchiveZip(outpath, f => {
                using (var zip = new ZipArchiveEx(f)) {
                    zip.AddDirectory(OutputDirectory, "library_project_imports");
                }
            }))
            {
                Log.LogDebugMessage("Saving contents to " + outpath);
            }
            return(true);
        }
Exemplo n.º 27
0
        void AddEnvironment(ZipArchiveEx apk)
        {
            var environment = new StringWriter()
            {
                NewLine = "\n",
            };

            if (EnableLLVM)
            {
                environment.WriteLine("mono.llvm=true");
            }

            AotMode aotMode;

            if (AndroidAotMode != null && Aot.GetAndroidAotMode(AndroidAotMode, out aotMode))
            {
                environment.WriteLine("mono.aot={0}", aotMode.ToString().ToLowerInvariant());
            }

            const string defaultLogLevel           = "MONO_LOG_LEVEL=info";
            const string defaultMonoDebug          = "MONO_DEBUG=gen-compact-seq-points";
            const string defaultHttpMessageHandler = "XA_HTTP_CLIENT_HANDLER_TYPE=System.Net.Http.HttpClientHandler, System.Net.Http";
            const string defaultTlsProvider        = "XA_TLS_PROVIDER=default";
            string       xamarinBuildId            = string.Format("XAMARIN_BUILD_ID={0}", buildId);

            bool haveLogLevel           = false;
            bool haveMonoDebug          = false;
            bool havebuildId            = false;
            bool haveHttpMessageHandler = false;
            bool haveTlsProvider        = false;
            bool haveMonoGCParams       = false;

            foreach (ITaskItem env in Environments ?? new TaskItem[0])
            {
                environment.WriteLine("## Source File: {0}", env.ItemSpec);
                foreach (string line in File.ReadLines(env.ItemSpec))
                {
                    var lineToWrite = line;
                    if (lineToWrite.StartsWith("MONO_LOG_LEVEL=", StringComparison.Ordinal))
                    {
                        haveLogLevel = true;
                    }
                    if (lineToWrite.StartsWith("MONO_GC_PARAMS=", StringComparison.Ordinal))
                    {
                        haveMonoGCParams = true;
                    }
                    if (lineToWrite.StartsWith("XAMARIN_BUILD_ID=", StringComparison.Ordinal))
                    {
                        havebuildId = true;
                    }
                    if (lineToWrite.StartsWith("MONO_DEBUG=", StringComparison.Ordinal))
                    {
                        haveMonoDebug = true;
                        if (sequencePointsMode != SequencePointsMode.None && !lineToWrite.Contains("gen-compact-seq-points"))
                        {
                            lineToWrite = line + ",gen-compact-seq-points";
                        }
                    }
                    if (lineToWrite.StartsWith("XA_HTTP_CLIENT_HANDLER_TYPE=", StringComparison.Ordinal))
                    {
                        haveHttpMessageHandler = true;
                    }
                    if (lineToWrite.StartsWith("XA_TLS_PROVIDER=", StringComparison.Ordinal))
                    {
                        haveTlsProvider = true;
                    }
                    environment.WriteLine(lineToWrite);
                }
            }

            if (_Debug && !haveLogLevel)
            {
                environment.WriteLine(defaultLogLevel);
            }

            if (sequencePointsMode != SequencePointsMode.None && !haveMonoDebug)
            {
                environment.WriteLine(defaultMonoDebug);
            }

            if (!havebuildId)
            {
                environment.WriteLine(xamarinBuildId);
            }

            if (!haveHttpMessageHandler)
            {
                environment.WriteLine(HttpClientHandlerType == null ? defaultHttpMessageHandler : $"XA_HTTP_CLIENT_HANDLER_TYPE={HttpClientHandlerType.Trim ()}");
            }
            if (!haveTlsProvider)
            {
                environment.WriteLine(TlsProvider == null ? defaultTlsProvider : $"XA_TLS_PROVIDER={TlsProvider.Trim ()}");
            }
            if (!haveMonoGCParams)
            {
                if (EnableSGenConcurrent)
                {
                    environment.WriteLine("MONO_GC_PARAMS=major=marksweep-conc");
                }
                else
                {
                    environment.WriteLine("MONO_GC_PARAMS=major=marksweep");
                }
            }

            apk.Archive.AddEntry("environment", environment.ToString(),
                                 new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
        }
Exemplo n.º 28
0
        public override bool Execute()
        {
            if (IsApplication)
            {
                return(true);
            }

            Log.LogDebugMessage("CreateManagedLibraryResourceArchive Task");
            Log.LogDebugMessage("  OutputDirectory: {0}", OutputDirectory);
            Log.LogDebugMessage("  ResourceDirectory: {0}", ResourceDirectory);
            Log.LogDebugTaskItems("  AndroidAssets:", AndroidAssets);
            Log.LogDebugTaskItems("  AndroidJavaSources:", AndroidJavaSources);
            Log.LogDebugTaskItems("  AndroidJavaLibraries:", AndroidJavaLibraries);

            var outDirInfo = new DirectoryInfo(OutputDirectory);

            // Copy files into _LibraryProjectImportsDirectoryName (library_project_imports) dir.
            if (!outDirInfo.Exists)
            {
                outDirInfo.Create();
            }
            foreach (var sub in new string [] { "assets", "res", "java", "bin" })
            {
                var subdirInfo = new DirectoryInfo(Path.Combine(outDirInfo.FullName, sub));
                if (!subdirInfo.Exists)
                {
                    subdirInfo.Create();
                }
            }

            var dir_sep = new char [] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };

            if (AndroidAssets != null)
            {
                var dstsub = Path.Combine(outDirInfo.FullName, "assets");
                if (!Directory.Exists(dstsub))
                {
                    Directory.CreateDirectory(dstsub);
                }
                foreach (var item in AndroidAssets)
                {
                    var path = item.GetMetadata("Link");
                    path = !string.IsNullOrWhiteSpace(path) ? path : item.ItemSpec;
                    var head = string.Join("\\", path.Split(dir_sep).TakeWhile(s => !s.Equals(MonoAndroidAssetsPrefix, StringComparison.OrdinalIgnoreCase)));
                    path = head.Length == path.Length ? path : path.Substring((head.Length == 0 ? 0 : head.Length + Path.DirectorySeparatorChar) + MonoAndroidAssetsPrefix.Length).TrimStart(dir_sep);
                    MonoAndroidHelper.CopyIfChanged(item.ItemSpec, Path.Combine(dstsub, path));
                }
            }
            // resources folders are converted to the structure that aapt accepts.
            bool hasInvalidName = false;

            foreach (var srcsub in Directory.GetDirectories(ResourceDirectory))
            {
                var dstsub = Path.Combine(outDirInfo.FullName, "res", Path.GetFileName(srcsub));
                if (!Directory.Exists(dstsub))
                {
                    Directory.CreateDirectory(dstsub);
                }
                foreach (var file in Directory.GetFiles(srcsub))
                {
                    var filename = Path.GetFileName(file);
                    MonoAndroidHelper.CopyIfChanged(file, Path.Combine(dstsub, Path.GetFileName(file)));
                }
            }
            if (hasInvalidName)
            {
                return(false);
            }
            if (AndroidJavaSources != null)
            {
                foreach (var item in AndroidJavaSources)
                {
                    MonoAndroidHelper.CopyIfChanged(item.ItemSpec, Path.Combine(outDirInfo.FullName, item.ItemSpec));
                }
            }
            if (AndroidJavaLibraries != null)
            {
                foreach (var item in AndroidJavaLibraries)
                {
                    MonoAndroidHelper.CopyIfChanged(item.ItemSpec, Path.Combine(outDirInfo.FullName, item.ItemSpec));
                }
            }

            var nameCaseMap = new StringWriter();

            // add resource case mapping descriptor to the archive.
            if (AndroidResourcesInThisExactProject != null && AndroidResourcesInThisExactProject.Any())
            {
                Log.LogMessage("writing __res_name_case_map.txt...");
                foreach (var res in AndroidResourcesInThisExactProject)
                {
                    nameCaseMap.WriteLine("{0};{1}", res.GetMetadata("LogicalName").Replace('\\', '/'), Path.Combine(Path.GetFileName(Path.GetDirectoryName(res.ItemSpec)), Path.GetFileName(res.ItemSpec)).Replace('\\', '/'));
                }
                File.WriteAllText(Path.Combine(OutputDirectory, "__res_name_case_map.txt"), nameCaseMap.ToString());
            }

            var outpath = Path.Combine(outDirInfo.Parent.FullName, "__AndroidLibraryProjects__.zip");

            if (Files.ArchiveZip(outpath, f => {
                using (var zip = new ZipArchiveEx(f)) {
                    zip.AddDirectory(OutputDirectory, outDirInfo.Name);
                }
            }))
            {
                Log.LogDebugMessage("Saving contents to " + outpath);
            }

            return(true);
        }
Exemplo n.º 29
0
        private void AddAssemblies(ZipArchiveEx apk)
        {
            bool debug = _Debug;
            bool use_shared_runtime = String.Equals(UseSharedRuntime, "true", StringComparison.OrdinalIgnoreCase);

            int count = 0;

            foreach (ITaskItem assembly in ResolvedUserAssemblies)
            {
                if (MonoAndroidHelper.IsReferenceAssembly(assembly.ItemSpec))
                {
                    Log.LogWarning($"{assembly.ItemSpec} is a reference assembly!");
                }
                // Add assembly
                apk.Archive.AddFile(assembly.ItemSpec, GetTargetDirectory(assembly.ItemSpec) + "/" + Path.GetFileName(assembly.ItemSpec), compressionMethod: CompressionMethod.Store);

                // Try to add config if exists
                var config = Path.ChangeExtension(assembly.ItemSpec, "dll.config");
                AddAssemblyConfigEntry(apk, config);

                // Try to add symbols if Debug
                if (debug)
                {
                    var symbols = Path.ChangeExtension(assembly.ItemSpec, "dll.mdb");

                    if (File.Exists(symbols))
                    {
                        apk.Archive.AddFile(symbols, "assemblies/" + Path.GetFileName(symbols), compressionMethod: CompressionMethod.Store);
                    }

                    symbols = Path.ChangeExtension(assembly.ItemSpec, "pdb");

                    if (File.Exists(symbols))
                    {
                        apk.Archive.AddFile(symbols, "assemblies/" + Path.GetFileName(symbols), compressionMethod: CompressionMethod.Store);
                    }
                }
                count++;
                if (count == ZipArchiveEx.ZipFlushLimit)
                {
                    apk.Flush();
                    count = 0;
                }
            }

            if (use_shared_runtime)
            {
                return;
            }

            count = 0;
            // Add framework assemblies
            foreach (ITaskItem assembly in ResolvedFrameworkAssemblies)
            {
                if (MonoAndroidHelper.IsReferenceAssembly(assembly.ItemSpec))
                {
                    Log.LogWarning($"{assembly.ItemSpec} is a reference assembly!");
                }
                apk.Archive.AddFile(assembly.ItemSpec, "assemblies/" + Path.GetFileName(assembly.ItemSpec), compressionMethod: CompressionMethod.Store);
                var config = Path.ChangeExtension(assembly.ItemSpec, "dll.config");
                AddAssemblyConfigEntry(apk, config);
                // Try to add symbols if Debug
                if (debug)
                {
                    var symbols = Path.ChangeExtension(assembly.ItemSpec, "dll.mdb");

                    if (File.Exists(symbols))
                    {
                        apk.Archive.AddFile(symbols, "assemblies/" + Path.GetFileName(symbols), compressionMethod: CompressionMethod.Store);
                    }

                    symbols = Path.ChangeExtension(assembly.ItemSpec, "pdb");

                    if (File.Exists(symbols))
                    {
                        apk.Archive.AddFile(symbols, "assemblies/" + Path.GetFileName(symbols), compressionMethod: CompressionMethod.Store);
                    }
                }
                count++;
                if (count == ZipArchiveEx.ZipFlushLimit)
                {
                    apk.Flush();
                    count = 0;
                }
            }
        }
Exemplo n.º 30
0
        void ExecuteWithAbi(string supportedAbis, string apkInputPath, string apkOutputPath)
        {
            ArchiveFileList files = new ArchiveFileList();

            if (apkInputPath != null)
            {
                File.Copy(apkInputPath, apkOutputPath + "new", overwrite: true);
            }
            using (var apk = new ZipArchiveEx(apkOutputPath + "new", apkInputPath != null ? FileMode.Open : FileMode.Create)) {
                apk.Archive.AddEntry("NOTICE",
                                     Assembly.GetExecutingAssembly().GetManifestResourceStream("NOTICE.txt"));

                // Add classes.dx
                apk.Archive.AddFiles(DalvikClasses, useFileDirectories: false);

                if (EmbedAssemblies && !BundleAssemblies)
                {
                    AddAssemblies(apk);
                }

                AddEnvironment(apk);
                AddRuntimeLibraries(apk, supportedAbis);
                apk.Flush();
                AddNativeLibraries(files, supportedAbis);
                apk.Flush();
                AddAdditionalNativeLibraries(files, supportedAbis);
                apk.Flush();
                AddNativeLibrariesFromAssemblies(apk, supportedAbis);
                apk.Flush();

                foreach (ITaskItem typemap in TypeMappings)
                {
                    apk.Archive.AddFile(typemap.ItemSpec, Path.GetFileName(typemap.ItemSpec), compressionMethod: CompressionMethod.Store);
                }

                int count = 0;
                foreach (var file in files)
                {
                    var item = Path.Combine(file.Item2, Path.GetFileName(file.Item1))
                               .Replace(Path.DirectorySeparatorChar, '/');
                    if (apk.Archive.ContainsEntry(item))
                    {
                        Log.LogWarning(null, "XA4301", null, file.Item1, 0, 0, 0, 0, "Apk already contains the item {0}; ignoring.", item);
                        continue;
                    }
                    apk.Archive.AddFile(file.Item1, item);
                    count++;
                    if (count == ZipArchiveEx.ZipFlushLimit)
                    {
                        apk.Flush();
                        count = 0;
                    }
                }
                if (_Debug)
                {
                    AddGdbservers(apk, files, supportedAbis, debugServer);
                }

                var jarFiles = (JavaSourceFiles != null) ? JavaSourceFiles.Where(f => f.ItemSpec.EndsWith(".jar")) : null;
                if (jarFiles != null && JavaLibraries != null)
                {
                    jarFiles = jarFiles.Concat(JavaLibraries);
                }
                else if (JavaLibraries != null)
                {
                    jarFiles = JavaLibraries;
                }

                var libraryProjectJars = MonoAndroidHelper.ExpandFiles(LibraryProjectJars)
                                         .Where(jar => !MonoAndroidHelper.IsEmbeddedReferenceJar(jar));

                var jarFilePaths = libraryProjectJars.Concat(jarFiles != null ? jarFiles.Select(j => j.ItemSpec) : Enumerable.Empty <string> ());
                jarFilePaths = MonoAndroidHelper.DistinctFilesByContent(jarFilePaths);

                count = 0;
                foreach (var jarFile in jarFilePaths)
                {
                    using (var jar = ZipArchive.Open(File.OpenRead(jarFile))) {
                        foreach (var jarItem in jar.Where(ze => !ze.IsDirectory && !ze.FullName.StartsWith("META-INF") && !ze.FullName.EndsWith(".class") && !ze.FullName.EndsWith(".java") && !ze.FullName.EndsWith("MANIFEST.MF")))
                        {
                            byte [] data;
                            using (var d = new System.IO.MemoryStream()) {
                                jarItem.Extract(d);
                                data = d.ToArray();
                            }
                            if (apk.Archive.Any(e => e.FullName == jarItem.FullName))
                            {
                                Log.LogMessage("Warning: failed to add jar entry {0} from {1}: the same file already exists in the apk", jarItem.FullName, Path.GetFileName(jarFile));
                            }
                            else
                            {
                                apk.Archive.AddEntry(data, jarItem.FullName);
                            }
                        }
                    }
                    count++;
                    if (count == ZipArchiveEx.ZipFlushLimit)
                    {
                        apk.Flush();
                        count = 0;
                    }
                }
                if (StubApplicationDataFile != null && File.Exists(StubApplicationDataFile))
                {
                    apk.Archive.AddFile(StubApplicationDataFile, Path.GetFileName(StubApplicationDataFile));
                }
            }
            MonoAndroidHelper.CopyIfZipChanged(apkOutputPath + "new", apkOutputPath);
            File.Delete(apkOutputPath + "new");
        }