Example #1
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);
            }
        }
        void AddAssemblies(ZipArchiveEx apk, bool debug, bool compress, IDictionary <string, CompressedAssemblyInfo> compressedAssembliesInfo)
        {
            bool   use_shared_runtime = String.Equals(UseSharedRuntime, "true", StringComparison.OrdinalIgnoreCase);
            string sourcePath;

            AssemblyCompression.AssemblyData compressedAssembly = null;

            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
                AddFileToArchiveIfNewer(apk, sourcePath, GetTargetDirectory(assembly.ItemSpec) + "/" + Path.GetFileName(assembly.ItemSpec), compressionMethod: UncompressedMethod);

                // 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))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }

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

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }
                }
                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 (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);
                AddFileToArchiveIfNewer(apk, sourcePath, AssembliesPath + Path.GetFileName(assembly.ItemSpec), compressionMethod: UncompressedMethod);
                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))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }

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

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }
                }
                count++;
                if (count == ZipArchiveEx.ZipFlushLimit)
                {
                    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);
                }

                if (compressedAssembliesInfo.TryGetValue(Path.GetFileName(assembly.ItemSpec), out CompressedAssemblyInfo info) && info != null)
                {
                    EnsureCompressedAssemblyData(assembly.ItemSpec, info.DescriptorIndex);
                    AssemblyCompression.CompressionResult result = AssemblyCompression.Compress(compressedAssembly);
                    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);
                }

                return(assembly.ItemSpec);
            }
        }