示例#1
0
        private void InnerEmbed(string prefix, string fullPath, bool compress, bool addChecksum, bool disableCleanup, Checksums checksums)
        {
            if (!disableCleanup)
            {
                // in any case we can remove this from the copy local paths, because either it's already embedded, or it will be embedded.
                // ReferenceCopyLocalPaths.RemoveAll(item => string.Equals(item, fullPath, StringComparison.OrdinalIgnoreCase));
            }

            var resourceName = $"{prefix}{Path.GetFileName(fullPath).ToLowerInvariant()}";

            if (manifest.Resources.Any(x => string.Equals(x.Name, resourceName, StringComparison.OrdinalIgnoreCase)))
            {
                // - an assembly that is already embedded uncompressed, using <EmbeddedResource> in the project file
                // - if compress == false: an assembly that appeared twice in the ReferenceCopyLocalPaths, e.g. the same library from different nuget packages (https://github.com/Fody/Costura/issues/332)
                if (addChecksum && !checksums.ContainsKey(resourceName))
                {
                    checksums.Add(resourceName, Checksums.CalculateChecksum(fullPath));
                }

                return;
            }

            if (compress)
            {
                resourceName += ".compressed";

                if (manifest.Resources.Any(x => string.Equals(x.Name, resourceName, StringComparison.OrdinalIgnoreCase)))
                {
                    // an assembly that appeared twice in the ReferenceCopyLocalPaths, e.g. the same library from different nuget packages (https://github.com/Fody/Costura/issues/332)
                    return;
                }
            }

            var checksum     = Checksums.CalculateChecksum(fullPath);
            var cacheFile    = Path.Combine(cachePath, $"{checksum}.{resourceName}");
            var memoryStream = BuildMemoryStream(fullPath, compress, cacheFile);

            streams.Add(memoryStream);
            ManifestResourceDeclaration resource = new ManifestResourceDeclaration
            {
                Name     = resourceName,
                IsPublic = false
            };

            resource.ContentStreamProvider = () => memoryStream;

            manifest.Resources.Add(resource);

            if (addChecksum)
            {
                checksums.Add(resourceName, checksum);
            }
        }
示例#2
0
        public override bool Execute()
        {
            // Find configuration:
            var annotations =
                annotationsService.GetAnnotationsOfType(typeof(PackerAttribute), false, true);
            PackerAttribute config = new PackerAttribute();

            if (annotations.MoveNext())
            {
                config = Configuration.Read(annotations.Current);
            }

            // Find gatherable assemblies:
            string[] paths = Project.Properties["ReferenceCopyLocalPaths"]?.Split('|') ?? new string[0];

            AssemblyManifestDeclaration manifest = Project.Module.AssemblyManifest;

            // I have no idea what this is doing:
            ResourceCaseFixer.FixResourceCase(manifest);

            // Embed resources:
            var  checksums = new Checksums();
            bool unmanagedFromProcessor = NativeResourcesProcessor.ProcessNativeResources(manifest, !config.DisableCompression, checksums);
            var  resourceEmbedder       = new ResourceEmbedder(manifest);

            resourceEmbedder.EmbedResources(config, paths, checksums);
            bool unmanagedFromEmbedder = resourceEmbedder.HasUnmanaged;

            // Load references:
            var assets = new Assets(Project.Module);
            AssemblyLoaderInfo info = AssemblyLoaderInfo.LoadAssemblyLoader(config.CreateTemporaryAssemblies,
                                                                            unmanagedFromEmbedder || unmanagedFromProcessor,
                                                                            Project.Module);

            // Alter code:
            string resourcesHash = ResourceHash.CalculateHash(manifest);

            new AttachCallSynthesis().SynthesizeCallToAttach(config, Project, info);
            new ResourceNameFinder(info, manifest, assets).FillInStaticConstructor(
                config.CreateTemporaryAssemblies,
                config.PreloadOrder,
                resourcesHash,
                checksums);

            return(true);
        }
示例#3
0
        /// <summary>
        /// Calculates checksums for costura-processed unmanaged resources of the assembly, and returns true if
        /// any unprocessed resources exist.
        /// </summary>
        public static bool ProcessNativeResources(AssemblyManifestDeclaration manifest, bool compress, Checksums checksums)
        {
            var  unprocessedNameMatch = new Regex(@"^(.*\.)?costura(32|64)\.", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
            var  processedNameMatch   = new Regex(@"^costura(32|64)\.", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
            bool hasUnmanaged         = false;

            foreach (var resource in manifest.Resources)
            {
                var match = unprocessedNameMatch.Match(resource.Name);
                if (match.Success)
                {
                    resource.Name = resource.Name.Substring(match.Groups[1].Length).ToLowerInvariant();
                    hasUnmanaged  = true;
                }

                if (processedNameMatch.IsMatch(resource.Name))
                {
                    using (var stream = resource.ContentStreamProvider())
                    {
                        if (compress && resource.Name.EndsWith(".compressed", StringComparison.OrdinalIgnoreCase))
                        {
                            using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress))
                            {
                                checksums.Add(resource.Name, Checksums.CalculateChecksum(compressStream));
                            }
                        }
                        else
                        {
                            checksums.Add(resource.Name, Checksums.CalculateChecksum(stream));
                        }
                    }
                }
            }

            return(hasUnmanaged);
        }
        public void FillInStaticConstructor(bool createTemporaryAssemblies, string[] preloadOrder, string resourcesHash, Checksums checksums)
        {
            var loaderMethod         = info.StaticConstructorMethod;
            InstructionReader reader = loaderMethod.MethodBody.CreateInstructionReader();

            reader.EnterInstructionBlock(loaderMethod.MethodBody.RootInstructionBlock);
            reader.EnterInstructionSequence(loaderMethod.MethodBody.RootInstructionBlock.LastInstructionSequence);
            while (reader.ReadInstruction())
            {
                if (reader.CurrentInstruction.OpCodeNumber == OpCodeNumber.Ret)
                {
                    break;
                }
            }
            Console.WriteLine(reader.CurrentInstruction);
            reader.CurrentInstructionSequence.SplitAroundReaderPosition(reader, out _, out _);
            var newSequence =
                reader.CurrentInstructionBlock.AddInstructionSequence(null, NodePosition.Before,
                                                                      reader.CurrentInstructionSequence);

            InstructionWriter writer = InstructionWriter.GetInstance();

            writer.AttachInstructionSequence(newSequence);
            var orderedResources = preloadOrder
                                   .Join(this.manifest.Resources, p => p.ToLowerInvariant(),
                                         r =>
            {
                var parts = r.Name.Split('.');
                GetNameAndExt(parts, out var name, out _);
                return(name);
            }, (s, r) => r)
示例#5
0
        public void EmbedResources(PackerAttribute config, string[] referenceCopyLocalPaths, Checksums checksums)
        {
            string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());

            cachePath = tempDirectory; //  Path.Combine(Path.GetDirectoryName(AssemblyFilePath), "Costura");
            Directory.CreateDirectory(cachePath);

            var onlyBinaries = referenceCopyLocalPaths.Where(x => x.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) ||
                                                             x.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)).ToArray();

            var disableCompression        = config.DisableCompression;
            var createTemporaryAssemblies = config.CreateTemporaryAssemblies;

            foreach (var dependency in GetFilteredReferences(onlyBinaries, config))
            {
                var fullPath = Path.GetFullPath(dependency);

                if (!config.IgnoreSatelliteAssemblies)
                {
                    if (dependency.EndsWith(".resources.dll", StringComparison.OrdinalIgnoreCase))
                    {
                        Embed($"costura.{Path.GetFileName(Path.GetDirectoryName(fullPath))}.", fullPath, !disableCompression, createTemporaryAssemblies, config.DisableCleanup, checksums);
                        continue;
                    }
                }

                Embed("costura.", fullPath, !disableCompression, createTemporaryAssemblies, config.DisableCleanup, checksums);

                if (!config.IncludeDebugSymbols)
                {
                    continue;
                }
                var pdbFullPath = Path.ChangeExtension(fullPath, "pdb");
                if (File.Exists(pdbFullPath))
                {
                    Embed("costura.", pdbFullPath, !disableCompression, createTemporaryAssemblies, config.DisableCleanup, checksums);
                }
            }

            foreach (var dependency in onlyBinaries)
            {
                var prefix = "";

                if (config.Unmanaged32Assemblies.Any(x => string.Equals(x, Path.GetFileNameWithoutExtension(dependency), StringComparison.OrdinalIgnoreCase)))
                {
                    prefix            = "costura32.";
                    this.HasUnmanaged = true;
                }
                if (config.Unmanaged64Assemblies.Any(x => string.Equals(x, Path.GetFileNameWithoutExtension(dependency), StringComparison.OrdinalIgnoreCase)))
                {
                    prefix            = "costura64.";
                    this.HasUnmanaged = true;
                }

                if (string.IsNullOrEmpty(prefix))
                {
                    continue;
                }

                var fullPath = Path.GetFullPath(dependency);
                Embed(prefix, fullPath, !disableCompression, true, config.DisableCleanup, checksums);

                if (!config.IncludeDebugSymbols)
                {
                    continue;
                }
                var pdbFullPath = Path.ChangeExtension(fullPath, "pdb");
                if (File.Exists(pdbFullPath))
                {
                    Embed(prefix, pdbFullPath, !disableCompression, true, config.DisableCleanup, checksums);
                }
            }
        }
示例#6
0
        void Embed(string prefix, string fullPath, bool compress, bool addChecksum, bool disableCleanup, Checksums checksums)
        {
            try
            {
                InnerEmbed(prefix, fullPath, compress, addChecksum, disableCleanup, checksums);
            }
            catch (Exception exception)
            {
                throw new Exception(
                          innerException: exception,
                          message: $@"Failed to embed.
prefix: {prefix}
fullPath: {fullPath}
compress: {compress}
addChecksum: {addChecksum}
disableCleanup: {disableCleanup}");
            }
        }