/// <summary> /// The actual repacking process, called by main after parsing arguments. /// When referencing this assembly, call this after setting the merge properties. /// Skips SourceServerData step. /// </summary> public void Repack(ModuleDefinition primaryModuleDefinition, IList <ModuleDefinition> modulesToMerge) { // System.Diagnostics.Debugger.Launch(); TargetAssemblyDefinition = primaryModuleDefinition.Assembly; PrimaryAssemblyDefinition = primaryModuleDefinition.Assembly; MergedAssemblies = new List <AssemblyDefinition>(modulesToMerge.Select(m => m.Assembly)) { primaryModuleDefinition.Assembly }; GlobalAssemblyResolver.RegisterAssemblies(MergedAssemblies); OtherAssemblies = new List <AssemblyDefinition>(modulesToMerge.Select(m => m.Assembly)); _reflectionHelper = new ReflectionHelper(this); _platformFixer = new PlatformFixer(this, PrimaryAssemblyMainModule.Runtime); _mappingHandler = new MappingHandler(); // set the main module attributes TargetAssemblyMainModule.Attributes = PrimaryAssemblyMainModule.Attributes; if (Options.Version != null) { TargetAssemblyDefinition.Name.Version = Options.Version; } _lineIndexer = new IKVMLineIndexer(this, Options.LineIndexation); List <IRepackStep> repackSteps = new List <IRepackStep> { new SigningStep(this, Options), new ReferencesRepackStep(Logger, this), new TypesRepackStep(Logger, this, _repackImporter, Options), new ResourcesRepackStep(Logger, this, Options), new AttributesRepackStep(Logger, this, _repackImporter, Options), new ReferencesFixStep(Logger, this, _repackImporter, Options), new XamlResourcePathPatcherStep(Logger, this) }; foreach (var step in repackSteps) { step.Perform(); } }
public TypeDefinition Import(TypeDefinition type, Collection <TypeDefinition> col, bool internalize) { _logger.Verbose("- Importing " + type); TypeDefinition nt = _repackContext.TargetAssemblyMainModule.GetType(type.FullName); bool justCreatedType = false; if (nt == null) { nt = CreateType(type, col, internalize, null); justCreatedType = true; } else if (DuplicateTypeAllowed(type)) { _logger.Info("Merging " + type); } else if (!type.IsPublic || internalize) { // rename the type previously imported. // renaming the new one before import made Cecil throw an exception. string other = "<" + Guid.NewGuid() + ">" + nt.Name; _logger.Info("Renaming " + nt.FullName + " into " + other); nt.Name = other; nt = CreateType(type, col, internalize, null); justCreatedType = true; } else if (_options.UnionMerge) { _logger.Info("Merging " + type); } else { _logger.Error("Duplicate type " + type); throw new InvalidOperationException( "Duplicate type " + type + " from " + type.Scope + ", was also present in " + MappingHandler.GetScopeFullName(_repackContext.MappingHandler.GetOrigTypeScope <IMetadataScope>(nt))); } _repackContext.MappingHandler.StoreRemappedType(type, nt); // nested types first (are never internalized) foreach (TypeDefinition nested in type.NestedTypes) { Import(nested, nt.NestedTypes, false); } foreach (FieldDefinition field in type.Fields) { CloneTo(field, nt); } // methods before fields / events foreach (MethodDefinition meth in type.Methods) { CloneTo(meth, nt, justCreatedType); } foreach (EventDefinition evt in type.Events) { CloneTo(evt, nt, nt.Events); } foreach (PropertyDefinition prop in type.Properties) { CloneTo(prop, nt, nt.Properties); } return(nt); }
/// <summary> /// The actual repacking process, called by main after parsing arguments. /// When referencing this assembly, call this after setting the merge properties. /// </summary> public void Repack() { Options.Validate(); PrintRepackVersion(); _reflectionHelper = new ReflectionHelper(this); ResolveSearchDirectories(); // Read input assemblies only after all properties are set. ReadInputAssemblies(); GlobalAssemblyResolver.RegisterAssemblies(MergedAssemblies); _platformFixer = new PlatformFixer(this, PrimaryAssemblyMainModule.Runtime); _mappingHandler = new MappingHandler(); bool hadStrongName = PrimaryAssemblyDefinition.Name.HasPublicKey; ModuleKind kind = PrimaryAssemblyMainModule.Kind; if (Options.TargetKind.HasValue) { switch (Options.TargetKind.Value) { case Kind.Dll: kind = ModuleKind.Dll; break; case Kind.Exe: kind = ModuleKind.Console; break; case Kind.WinExe: kind = ModuleKind.Windows; break; } } TargetRuntime runtime = ParseTargetPlatform(); // change assembly's name to correspond to the file we create string mainModuleName = Path.GetFileNameWithoutExtension(Options.OutputFile); if (TargetAssemblyDefinition == null) { AssemblyNameDefinition asmName = Clone(PrimaryAssemblyDefinition.Name); asmName.Name = mainModuleName; TargetAssemblyDefinition = AssemblyDefinition.CreateAssembly(asmName, mainModuleName, new ModuleParameters() { Kind = kind, Architecture = PrimaryAssemblyMainModule.Architecture, AssemblyResolver = GlobalAssemblyResolver, Runtime = runtime }); } else { // TODO: does this work or is there more to do? TargetAssemblyMainModule.Kind = kind; TargetAssemblyMainModule.Runtime = runtime; TargetAssemblyDefinition.Name.Name = mainModuleName; TargetAssemblyMainModule.Name = mainModuleName; } // set the main module attributes TargetAssemblyMainModule.Attributes = PrimaryAssemblyMainModule.Attributes; TargetAssemblyMainModule.Win32ResourceDirectory = MergeWin32Resources(PrimaryAssemblyMainModule.Win32ResourceDirectory); if (Options.Version != null) TargetAssemblyDefinition.Name.Version = Options.Version; _lineIndexer = new IKVMLineIndexer(this, Options.LineIndexation); var signingStep = new SigningStep(this, Options); List<IRepackStep> repackSteps = new List<IRepackStep> { signingStep, new ReferencesRepackStep(Logger, this), new TypesRepackStep(Logger, this, _repackImporter, Options), new ResourcesRepackStep(Logger, this, Options), new AttributesRepackStep(Logger, this, _repackImporter, Options), new ReferencesFixStep(Logger, this, _repackImporter, Options), new XamlResourcePathPatcherStep(Logger, this) }; foreach (var step in repackSteps) { step.Perform(); } var parameters = new WriterParameters { StrongNameKeyPair = signingStep.KeyPair, WriteSymbols = Options.DebugInfo }; // create output directory if it does not exist var outputDir = Path.GetDirectoryName(Options.OutputFile); if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir)) { Logger.Info("Output directory does not exist. Creating output directory: " + outputDir); Directory.CreateDirectory(outputDir); } TargetAssemblyDefinition.Write(Options.OutputFile, parameters); Logger.Info("Writing output assembly to disk"); // If this is an executable and we are on linux/osx we should copy file permissions from // the primary assembly if (Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix) { Stat stat; Logger.Info("Copying permissions from " + PrimaryAssemblyFile); Syscall.stat(PrimaryAssemblyFile, out stat); Syscall.chmod(Options.OutputFile, stat.st_mode); } if (hadStrongName && !TargetAssemblyDefinition.Name.HasPublicKey) Options.StrongNameLost = true; // nice to have, merge .config (assembly configuration file) & .xml (assembly documentation) ConfigMerger.Process(this); if (Options.XmlDocumentation) DocumentationMerger.Process(this); }
/// <summary> /// The actual repacking process, called by main after parsing arguments. /// When referencing this assembly, call this after setting the merge properties. /// </summary> public void Repack() { Options.Validate(); _reflectionHelper = new ReflectionHelper(this); ResolveSearchDirectories(); // Read input assemblies only after all properties are set. ReadInputAssemblies(); GlobalAssemblyResolver.RegisterAssemblies(MergedAssemblies); _platformFixer = new PlatformFixer(PrimaryAssemblyMainModule.Runtime); _mappingHandler = new MappingHandler(); bool hadStrongName = PrimaryAssemblyDefinition.Name.HasPublicKey; ModuleKind kind = PrimaryAssemblyMainModule.Kind; if (Options.TargetKind.HasValue) { switch (Options.TargetKind.Value) { case Kind.Dll: kind = ModuleKind.Dll; break; case Kind.Exe: kind = ModuleKind.Console; break; case Kind.WinExe: kind = ModuleKind.Windows; break; } } TargetRuntime runtime = ParseTargetPlatform(); // change assembly's name to correspond to the file we create string mainModuleName = Path.GetFileNameWithoutExtension(Options.OutputFile); if (TargetAssemblyDefinition == null) { AssemblyNameDefinition asmName = Clone(PrimaryAssemblyDefinition.Name); asmName.Name = mainModuleName; TargetAssemblyDefinition = AssemblyDefinition.CreateAssembly(asmName, mainModuleName, new ModuleParameters() { Kind = kind, Architecture = PrimaryAssemblyMainModule.Architecture, AssemblyResolver = GlobalAssemblyResolver, Runtime = runtime }); } else { // TODO: does this work or is there more to do? TargetAssemblyMainModule.Kind = kind; TargetAssemblyMainModule.Runtime = runtime; TargetAssemblyDefinition.Name.Name = mainModuleName; TargetAssemblyMainModule.Name = mainModuleName; } // set the main module attributes TargetAssemblyMainModule.Attributes = PrimaryAssemblyMainModule.Attributes; TargetAssemblyMainModule.Win32ResourceDirectory = MergeWin32Resources(PrimaryAssemblyMainModule.Win32ResourceDirectory); if (Options.Version != null) { TargetAssemblyDefinition.Name.Version = Options.Version; } _lineIndexer = new IKVMLineIndexer(this); var signingStep = new SigningStep(this, Options); List <IRepackStep> repackSteps = new List <IRepackStep> { signingStep, new ReferencesRepackStep(Logger, this), new TypesRepackStep(Logger, this, _repackImporter, Options), new ResourcesRepackStep(Logger, this, Options), new AttributesRepackStep(Logger, this, _repackImporter, Options), new ReferencesFixStep(Logger, this, _repackImporter, Options), new XamlResourcePathPatcherStep(Logger, this) }; foreach (var step in repackSteps) { step.Perform(); } var parameters = new WriterParameters { StrongNameKeyPair = signingStep.KeyPair, WriteSymbols = Options.DebugInfo }; // create output directory if it does not exist var outputDir = Path.GetDirectoryName(Options.OutputFile); if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir)) { Logger.Info("Output directory does not exist. Creating output directory: " + outputDir); Directory.CreateDirectory(outputDir); } TargetAssemblyDefinition.Write(Options.OutputFile, parameters); Logger.Info("Writing output assembly to disk"); // If this is an executable and we are on linux/osx we should copy file permissions from // the primary assembly if (Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix) { Stat stat; Logger.Info("Copying permissions from " + PrimaryAssemblyFile); Syscall.stat(PrimaryAssemblyFile, out stat); Syscall.chmod(Options.OutputFile, stat.st_mode); } if (hadStrongName && !TargetAssemblyDefinition.Name.HasPublicKey) { Options.StrongNameLost = true; } // nice to have, merge .config (assembly configuration file) & .xml (assembly documentation) ConfigMerger.Process(this); if (Options.XmlDocumentation) { DocumentationMerger.Process(this); } // TODO: we're done here, the code below is only test code which can be removed once it's all running fine // 'verify' generated assembly AssemblyDefinition asm2 = AssemblyDefinition.ReadAssembly(Options.OutputFile, new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = GlobalAssemblyResolver }); // lazy match on the name (not full) to catch requirements about merging different versions bool failed = false; foreach (var a in asm2.MainModule.AssemblyReferences.Where(x => MergedAssemblies.Any(y => Options.KeepOtherVersionReferences ? x.FullName == y.FullName : x.Name == y.Name.Name))) { // failed Logger.Error("Merged assembly still references " + a.FullName); failed = true; } if (failed) { throw new Exception("Merging failed, see above errors"); } }
/// <summary> /// The actual repacking process, called by main after parsing arguments. /// When referencing this assembly, call this after setting the merge properties. /// </summary> public void Repack() { var timer = new Stopwatch(); timer.Start(); Options.Validate(); PrintRepackVersion(); _reflectionHelper = new ReflectionHelper(this); ResolveSearchDirectories(); // Read input assemblies only after all properties are set. ReadInputAssemblies(); GlobalAssemblyResolver.RegisterAssemblies(MergedAssemblies); _platformFixer = new PlatformFixer(this, PrimaryAssemblyMainModule.Runtime); _mappingHandler = new MappingHandler(); bool hadStrongName = PrimaryAssemblyDefinition.Name.HasPublicKey; ModuleKind kind = PrimaryAssemblyMainModule.Kind; if (Options.TargetKind.HasValue) { switch (Options.TargetKind.Value) { case Kind.Dll: kind = ModuleKind.Dll; break; case Kind.Exe: kind = ModuleKind.Console; break; case Kind.WinExe: kind = ModuleKind.Windows; break; } } TargetRuntime runtime = ParseTargetPlatform(); // change assembly's name to correspond to the file we create string mainModuleName = Path.GetFileNameWithoutExtension(Options.OutputFile); if (TargetAssemblyDefinition == null) { AssemblyNameDefinition asmName = Clone(PrimaryAssemblyDefinition.Name); asmName.Name = mainModuleName; TargetAssemblyDefinition = AssemblyDefinition.CreateAssembly(asmName, mainModuleName, new ModuleParameters() { Kind = kind, Architecture = PrimaryAssemblyMainModule.Architecture, AssemblyResolver = GlobalAssemblyResolver, Runtime = runtime }); } else { // TODO: does this work or is there more to do? TargetAssemblyMainModule.Kind = kind; TargetAssemblyMainModule.Runtime = runtime; TargetAssemblyDefinition.Name.Name = mainModuleName; TargetAssemblyMainModule.Name = mainModuleName; } // set the main module attributes TargetAssemblyMainModule.Attributes = PrimaryAssemblyMainModule.Attributes; TargetAssemblyMainModule.Win32ResourceDirectory = MergeWin32Resources(PrimaryAssemblyMainModule.Win32ResourceDirectory); if (Options.Version != null) { TargetAssemblyDefinition.Name.Version = Options.Version; } _lineIndexer = new IKVMLineIndexer(this, Options.LineIndexation); var signingStep = new SigningStep(this, Options); var sourceServerDataRepackStep = new SourceServerDataRepackStep(Options.OutputFile, MergedAssemblyFiles); List <IRepackStep> repackSteps = new List <IRepackStep> { signingStep, new ReferencesRepackStep(Logger, this), new TypesRepackStep(Logger, this, _repackImporter, Options), new ResourcesRepackStep(Logger, this, Options), new AttributesRepackStep(Logger, this, _repackImporter, Options), new ReferencesFixStep(Logger, this, _repackImporter, Options), new XamlResourcePathPatcherStep(Logger, this), sourceServerDataRepackStep }; foreach (var step in repackSteps) { step.Perform(); } var parameters = new WriterParameters { StrongNameKeyPair = signingStep.KeyPair, WriteSymbols = Options.DebugInfo }; // create output directory if it does not exist var outputDir = Path.GetDirectoryName(Options.OutputFile); if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir)) { Logger.Info("Output directory does not exist. Creating output directory: " + outputDir); Directory.CreateDirectory(outputDir); } TargetAssemblyDefinition.Write(Options.OutputFile, parameters); sourceServerDataRepackStep.Write(); Logger.Info("Writing output assembly to disk"); // If this is an executable and we are on linux/osx we should copy file permissions from // the primary assembly if (Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix) { Stat stat; Logger.Info("Copying permissions from " + PrimaryAssemblyFile); Syscall.stat(PrimaryAssemblyFile, out stat); Syscall.chmod(Options.OutputFile, stat.st_mode); } if (hadStrongName && !TargetAssemblyDefinition.Name.HasPublicKey) { Options.StrongNameLost = true; } // nice to have, merge .config (assembly configuration file) & .xml (assembly documentation) ConfigMerger.Process(this); if (Options.XmlDocumentation) { DocumentationMerger.Process(this); } Logger.Info($"Finished in {timer.Elapsed}"); }