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 isUnixEnvironment = Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix;
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),
};
if (!isUnixEnvironment)
repackSteps.Add(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);
if (!isUnixEnvironment)
sourceServerDataRepackStep.Write();
else
Logger.Warn("Did not write source server data to output assembly. " +
"Source server data is only writeable on Windows");
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 (isUnixEnvironment)
{
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}");
}