private static CSharpCompilationOptions AddSigningOptions(CSharpCompilationOptions options, CommonCompilerOptions compilerOptions, string projectDirectory) { var useOssSigning = compilerOptions.PublicSign == true; var keyFile = compilerOptions.KeyFile; if (!string.IsNullOrEmpty(keyFile)) { keyFile = Path.GetFullPath(Path.Combine(projectDirectory, compilerOptions.KeyFile)); if ( #if !NET451 !RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || #endif useOssSigning) { return(options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile)))); } options = options.WithCryptoKeyFile(keyFile); return(options.WithDelaySign(compilerOptions.DelaySign)); } return(options); }
private static CSharpCompilationOptions AddSigningOptions(CSharpCompilationOptions options, ICompilerOptions compilerOptions, string projectDirectory) { var useOssSigning = compilerOptions.UseOssSigning == true; var keyFile = Environment.GetEnvironmentVariable(EnvironmentNames.BuildKeyFile) ?? GetKeyFileFullPath(projectDirectory, compilerOptions.KeyFile); if (!string.IsNullOrWhiteSpace(keyFile)) { #if DOTNET5_4 return(options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile)))); #else if (RuntimeEnvironmentHelper.IsMono || useOssSigning) { return(options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile)))); } options = options.WithCryptoKeyFile(keyFile); var delaySignString = Environment.GetEnvironmentVariable(EnvironmentNames.BuildDelaySign); var delaySign = delaySignString == null ? compilerOptions.DelaySign : string.Equals(delaySignString, "true", StringComparison.OrdinalIgnoreCase) || string.Equals(delaySignString, "1", StringComparison.Ordinal); return(options.WithDelaySign(delaySign)); #endif } return(useOssSigning ? options.WithCryptoPublicKey(StrongNameKey) : options); }
private static CSharpCompilationOptions AddSigningOptions(CSharpCompilationOptions options, CommonCompilerOptions compilerOptions, string projectDirectory) { var useOssSigning = compilerOptions.PublicSign == true; var keyFile = compilerOptions.KeyFile; if (!string.IsNullOrEmpty(keyFile)) { keyFile = Path.GetFullPath(Path.Combine(projectDirectory, compilerOptions.KeyFile)); if (RuntimeEnvironment.OperatingSystemPlatform != InternalAbstractions.Platform.Windows || useOssSigning) { return(options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile)))); } options = options.WithCryptoKeyFile(keyFile); return(options.WithDelaySign(compilerOptions.DelaySign)); } return(options); }
private static CSharpCompilationOptions AddSigningOptions(CSharpCompilationOptions options, CommonCompilerOptions compilerOptions, string projectDirectory) { var useOssSigning = compilerOptions.UseOssSigning == true; var keyFile = compilerOptions.KeyFile; if (!string.IsNullOrEmpty(keyFile)) { keyFile = Path.GetFullPath(Path.Combine(projectDirectory, compilerOptions.KeyFile)); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || useOssSigning) { return options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile))); } options = options.WithCryptoKeyFile(keyFile); return options.WithDelaySign(compilerOptions.DelaySign); } return options; }
public HostBuildData Create(HostBuildOptions options) { var parseOptions = new CSharpParseOptions(languageVersion: LanguageVersion.CSharp6, documentationMode: DocumentationMode.Parse); var compilationOptions = new CSharpCompilationOptions( OutputKind.ConsoleApplication, xmlReferenceResolver: new XmlFileResolver(options.ProjectDirectory), sourceReferenceResolver: new SourceFileResolver(ImmutableArray<string>.Empty, options.ProjectDirectory), metadataReferenceResolver: new AssemblyReferenceResolver( new MetadataFileReferenceResolver(ImmutableArray<string>.Empty, options.ProjectDirectory), MetadataFileReferenceProvider.Default), strongNameProvider: new DesktopStrongNameProvider(ImmutableArray.Create(options.ProjectDirectory, options.OutputDirectory)), assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default); var warnings = new List<KeyValuePair<string, ReportDiagnostic>>(options.Warnings); if (options.OutputKind.HasValue) { var kind = options.OutputKind.Value; compilationOptions = compilationOptions.WithOutputKind(kind); if (compilationOptions.Platform == Platform.AnyCpu32BitPreferred && (kind == OutputKind.DynamicallyLinkedLibrary || kind == OutputKind.NetModule || kind == OutputKind.WindowsRuntimeMetadata)) { compilationOptions = compilationOptions.WithPlatform(Platform.AnyCpu); } } if (!string.IsNullOrEmpty(options.DefineConstants)) { IEnumerable<Diagnostic> diagnostics; parseOptions = parseOptions.WithPreprocessorSymbols(CSharpCommandLineParser.ParseConditionalCompilationSymbols(options.DefineConstants, out diagnostics)); } if (options.DocumentationFile != null) { parseOptions = parseOptions.WithDocumentationMode(!string.IsNullOrEmpty(options.DocumentationFile) ? DocumentationMode.Diagnose : DocumentationMode.Parse); } if (options.LanguageVersion != null) { var languageVersion = CompilationOptionsConversion.GetLanguageVersion(options.LanguageVersion); if (languageVersion.HasValue) { parseOptions = parseOptions.WithLanguageVersion(languageVersion.Value); } } if (!string.IsNullOrEmpty(options.PlatformWith32BitPreference)) { Platform platform; if (Enum.TryParse<Platform>(options.PlatformWith32BitPreference, true, out platform)) { if (platform == Platform.AnyCpu && compilationOptions.OutputKind != OutputKind.DynamicallyLinkedLibrary && compilationOptions.OutputKind != OutputKind.NetModule && compilationOptions.OutputKind != OutputKind.WindowsRuntimeMetadata) { platform = Platform.AnyCpu32BitPreferred; } compilationOptions = compilationOptions.WithPlatform(platform); } } if (options.AllowUnsafeBlocks.HasValue) { compilationOptions = compilationOptions.WithAllowUnsafe(options.AllowUnsafeBlocks.Value); } if (options.CheckForOverflowUnderflow.HasValue) { compilationOptions = compilationOptions.WithOverflowChecks(options.CheckForOverflowUnderflow.Value); } if (options.DelaySign != null) { bool delaySignExplicitlySet = options.DelaySign.Item1; bool delaySign = options.DelaySign.Item2; compilationOptions = compilationOptions.WithDelaySign(delaySignExplicitlySet ? delaySign : (bool?)null); } if (!string.IsNullOrEmpty(options.ApplicationConfiguration)) { var appConfigPath = FileUtilities.ResolveRelativePath(options.ApplicationConfiguration, options.ProjectDirectory); try { using (var appConfigStream = PortableShim.FileStream.Create(appConfigPath, PortableShim.FileMode.Open, PortableShim.FileAccess.Read)) { compilationOptions = compilationOptions.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream)); } } catch (Exception) { } } if (!string.IsNullOrEmpty(options.KeyContainer)) { compilationOptions = compilationOptions.WithCryptoKeyContainer(options.KeyContainer); } if (!string.IsNullOrEmpty(options.KeyFile)) { var fullPath = FileUtilities.ResolveRelativePath(options.KeyFile, options.ProjectDirectory); compilationOptions = compilationOptions.WithCryptoKeyFile(fullPath); } if (!string.IsNullOrEmpty(options.MainEntryPoint)) { compilationOptions = compilationOptions.WithMainTypeName(options.MainEntryPoint); } if (!string.IsNullOrEmpty(options.ModuleAssemblyName)) { compilationOptions = compilationOptions.WithModuleName(options.ModuleAssemblyName); } if (options.Optimize.HasValue) { compilationOptions = compilationOptions.WithOptimizationLevel(options.Optimize.Value ? OptimizationLevel.Release : OptimizationLevel.Debug); } if (!string.IsNullOrEmpty(options.Platform)) { Platform plat; if (Enum.TryParse<Platform>(options.Platform, ignoreCase: true, result: out plat)) { compilationOptions = compilationOptions.WithPlatform(plat); } } // Get options from the ruleset file, if any. if (!string.IsNullOrEmpty(options.RuleSetFile)) { var fullPath = FileUtilities.ResolveRelativePath(options.RuleSetFile, options.ProjectDirectory); Dictionary<string, ReportDiagnostic> specificDiagnosticOptions; var generalDiagnosticOption = RuleSet.GetDiagnosticOptionsFromRulesetFile(fullPath, out specificDiagnosticOptions); compilationOptions = compilationOptions.WithGeneralDiagnosticOption(generalDiagnosticOption); warnings.AddRange(specificDiagnosticOptions); } if (options.WarningsAsErrors.HasValue) { compilationOptions = compilationOptions.WithGeneralDiagnosticOption(options.WarningsAsErrors.Value ? ReportDiagnostic.Error : ReportDiagnostic.Default); } if (options.WarningLevel.HasValue) { compilationOptions = compilationOptions.WithWarningLevel(options.WarningLevel.Value); } compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(warnings); return new HostBuildData( parseOptions, compilationOptions); }
public static AssemblyDefinition GenerateSerializationAssembly(PlatformType platformType, BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, string serializationAssemblyLocation, string signKeyFile, List<string> serializatonProjectReferencePaths) { // Make sure all assemblies in serializatonProjectReferencePaths are referenced (sometimes they might be optimized out if no direct references) foreach (var serializatonProjectReferencePath in serializatonProjectReferencePaths) { var shortAssemblyName = Path.GetFileNameWithoutExtension(serializatonProjectReferencePath); // Still in references (not optimized) if (assembly.MainModule.AssemblyReferences.Any(x => x.Name == shortAssemblyName)) continue; // For now, use AssemblyDefinition.ReadAssembly to compute full name -- maybe not very efficient but it shouldn't happen often anyway) var referencedAssembly = AssemblyDefinition.ReadAssembly(serializatonProjectReferencePath); assembly.MainModule.AssemblyReferences.Add(AssemblyNameReference.Parse(referencedAssembly.FullName)); } // Create the serializer code generator var serializerGenerator = new ComplexSerializerCodeGenerator(assemblyResolver, assembly); // Register default serialization profile (to help AOT generic instantiation of serializers) RegisterDefaultSerializationProfile(assemblyResolver, assembly, serializerGenerator); // Generate serializer code var serializerGeneratedCode = serializerGenerator.TransformText(); var syntaxTree = CSharpSyntaxTree.ParseText(serializerGeneratedCode); // Add reference from source assembly // Use a hash set because it seems including twice mscorlib (2.0 and 4.0) seems to be a problem. var skipWindows = "Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null"; var compilerOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true, assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default); // Sign the serialization assembly the same way the source was signed // TODO: Transmit over command line if (assembly.Name.HasPublicKey) { // TODO: If delay signed, we could actually extract the public key and apply it ourself maybe? if (signKeyFile == null) throw new InvalidOperationException("Generating serialization code for signed assembly, but no key was specified."); compilerOptions = compilerOptions.WithCryptoKeyFile(signKeyFile).WithStrongNameProvider(new DesktopStrongNameProvider()); if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) != ModuleAttributes.StrongNameSigned) { // Delay signed compilerOptions = compilerOptions.WithDelaySign(true); } } var metadataReferences = new List<MetadataReference>(); var assemblyLocations = new HashSet<string>(); foreach (var referencedAssemblyName in assembly.MainModule.AssemblyReferences) { // We skip both Windows, and current assembly (AssemblyProcessor.Common, which might be added with an alias) if (referencedAssemblyName.FullName != skipWindows && referencedAssemblyName.FullName != typeof(ComplexSerializerGenerator).Assembly.FullName && referencedAssemblyName.FullName != "SiliconStudio.AssemblyProcessor") { if (assemblyLocations.Add(referencedAssemblyName.Name)) { //Console.WriteLine("Resolve Assembly for serialization [{0}]", referencedAssemblyName.FullName); metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve(referencedAssemblyName))); } } } // typeof(Dictionary<,>) // Special case for 4.5: Because Dictionary<,> is forwarded, we need to add a reference to the actual assembly var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly); metadataReferences.Add(CreateMetadataReference(assemblyResolver, mscorlibAssembly)); var collectionType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Dictionary<,>).FullName); metadataReferences.Add(CreateMetadataReference(assemblyResolver, collectionType.Module.Assembly)); // Make sure System and System.Reflection are added // TODO: Maybe we should do that for .NETCore and PCL too? (instead of WinRT only) if (platformType == PlatformType.WindowsStore || platformType == PlatformType.WindowsPhone) { if (assemblyLocations.Add("System")) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("System"))); } if (assemblyLocations.Add("System.Reflection")) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("System.Reflection"))); } } metadataReferences.Add(CreateMetadataReference(assemblyResolver, assembly)); assemblyLocations.Add(assembly.Name.Name); // In case Paradox.Framework.Serialization was not referenced, let's add it. if (!assemblyLocations.Contains("SiliconStudio.Core")) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("SiliconStudio.Core"))); assemblyLocations.Add("SiliconStudio.Core"); } // Create roslyn compilation object var assemblyName = Path.GetFileNameWithoutExtension(serializationAssemblyLocation); var compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, metadataReferences, compilerOptions); // Do the actual compilation, and check errors using (var peStream = new FileStream(serializationAssemblyLocation, FileMode.Create, FileAccess.Write)) { var compilationResult = compilation.Emit(peStream); if (!compilationResult.Success) { var errors = new StringBuilder(); errors.AppendLine(string.Format("Serialization assembly compilation: {0} error(s)", compilationResult.Diagnostics.Count(x => x.Severity >= DiagnosticSeverity.Error))); foreach (var error in compilationResult.Diagnostics) { if (error.Severity >= DiagnosticSeverity.Warning) errors.AppendLine(error.ToString()); } throw new InvalidOperationException(errors.ToString()); } } // Run ILMerge var merge = new ILRepacking.ILRepack() { OutputFile = assembly.MainModule.FullyQualifiedName, DebugInfo = true, CopyAttributes = true, AllowMultipleAssemblyLevelAttributes = true, XmlDocumentation = false, NoRepackRes = true, PrimaryAssemblyDefinition = assembly, WriteToDisk = false, //KeepFirstOfMultipleAssemblyLevelAttributes = true, //Log = true, //LogFile = "ilmerge.log", }; merge.SetInputAssemblies(new string[] { serializationAssemblyLocation }); // Force to use the correct framework //merge.SetTargetPlatform("v4", frameworkFolder); merge.SetSearchDirectories(assemblyResolver.GetSearchDirectories()); merge.Merge(); // Copy name merge.TargetAssemblyDefinition.Name.Name = assembly.Name.Name; merge.TargetAssemblyDefinition.Name.Version = assembly.Name.Version; // Add assembly signing info if (assembly.Name.HasPublicKey) { merge.TargetAssemblyDefinition.Name.PublicKey = assembly.Name.PublicKey; merge.TargetAssemblyDefinition.Name.PublicKeyToken = assembly.Name.PublicKeyToken; merge.TargetAssemblyDefinition.Name.Attributes |= AssemblyAttributes.PublicKey; if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned) merge.TargetAssemblyMainModule.Attributes |= ModuleAttributes.StrongNameSigned; } try { // Delete serializer dll File.Delete(serializationAssemblyLocation); var serializationAssemblyPdbFilePath = Path.ChangeExtension(serializationAssemblyLocation, "pdb"); if (File.Exists(serializationAssemblyPdbFilePath)) { File.Delete(serializationAssemblyPdbFilePath); } } catch (IOException) { // Mute IOException } return merge.TargetAssemblyDefinition; }
private static CSharpCompilationOptions AddSigningOptions(CSharpCompilationOptions options, CommonCompilerOptions compilerOptions, string projectDirectory) { var useOssSigning = compilerOptions.PublicSign == true; var keyFile = compilerOptions.KeyFile; if (!string.IsNullOrEmpty(keyFile)) { keyFile = Path.GetFullPath(Path.Combine(projectDirectory, compilerOptions.KeyFile)); if (RuntimeEnvironment.OperatingSystemPlatform != InternalAbstractions.Platform.Windows || useOssSigning) { return options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile))); } options = options.WithCryptoKeyFile(keyFile); return options.WithDelaySign(compilerOptions.DelaySign); } return options; }
public static AssemblyDefinition GenerateRoslynAssembly(CustomAssemblyResolver assemblyResolver, AssemblyDefinition assembly, string serializationAssemblyLocation, string signKeyFile, List <string> references, List <AssemblyDefinition> memoryReferences, TextWriter log, IEnumerable <SourceCode> sourceCodes) { var sourceFolder = Path.GetDirectoryName(serializationAssemblyLocation); var syntaxTrees = sourceCodes.Select(x => { // It has a name, let's save it as a file string sourcePath = null; if (x.Name != null) { sourcePath = Path.Combine(sourceFolder, $"{x.Name}.cs"); File.WriteAllText(sourcePath, x.Code); } var result = CSharpSyntaxTree.ParseText(x.Code, null, sourcePath, Encoding.UTF8); return(result); }).ToArray(); var compilerOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true, assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default); // Sign the serialization assembly the same way the source was signed // TODO: Transmit over command line if (assembly.Name.HasPublicKey) { // TODO: If delay signed, we could actually extract the public key and apply it ourself maybe? if (signKeyFile == null) { throw new InvalidOperationException("Generating serialization code for signed assembly, but no key was specified."); } compilerOptions = compilerOptions.WithCryptoKeyFile(signKeyFile).WithStrongNameProvider(new DesktopStrongNameProvider()); if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) != ModuleAttributes.StrongNameSigned) { // Delay signed compilerOptions = compilerOptions.WithDelaySign(true); } } // Add references (files and in-memory PE data) var metadataReferences = new List <MetadataReference>(); foreach (var reference in assemblyResolver.References) { metadataReferences.Add(MetadataReference.CreateFromFile(reference)); } foreach (var reference in memoryReferences) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, reference)); } // typeof(Dictionary<,>) // Special case for 4.5: Because Dictionary<,> is forwarded, we need to add a reference to the actual assembly var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly); metadataReferences.Add(CreateMetadataReference(assemblyResolver, mscorlibAssembly)); var collectionAssembly = CecilExtensions.FindCollectionsAssembly(assembly); metadataReferences.Add(CreateMetadataReference(assemblyResolver, collectionAssembly)); metadataReferences.Add(CreateMetadataReference(assemblyResolver, assembly)); // In case SiliconStudio.Core was not referenced, let's add it. if (assembly.Name.Name != "SiliconStudio.Core" && !references.Any(x => string.Compare(Path.GetFileNameWithoutExtension(x), "SiliconStudio.Core", StringComparison.OrdinalIgnoreCase) == 0)) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("SiliconStudio.Core"))); } // Create roslyn compilation object var assemblyName = assembly.Name.Name + ".Serializers"; var compilation = CSharpCompilation.Create(assemblyName, syntaxTrees, metadataReferences, compilerOptions); // Do the actual compilation, and check errors using (var peStream = new FileStream(serializationAssemblyLocation, FileMode.Create, FileAccess.Write)) using (var pdbStream = new FileStream(Path.ChangeExtension(serializationAssemblyLocation, ".pdb"), FileMode.Create, FileAccess.Write)) { var compilationResult = compilation.Emit(peStream, pdbStream); if (!compilationResult.Success) { var errors = new StringBuilder(); errors.AppendLine(string.Format("Serialization assembly compilation: {0} error(s)", compilationResult.Diagnostics.Count(x => x.Severity >= DiagnosticSeverity.Error))); foreach (var error in compilationResult.Diagnostics) { if (error.Severity >= DiagnosticSeverity.Warning) { errors.AppendLine(error.ToString()); } } throw new InvalidOperationException(errors.ToString()); } } var repackOptions = new ILRepacking.RepackOptions(new string[0]) { OutputFile = assembly.MainModule.FullyQualifiedName, DebugInfo = true, CopyAttributes = true, AllowMultipleAssemblyLevelAttributes = true, XmlDocumentation = false, NoRepackRes = true, InputAssemblies = new[] { serializationAssemblyLocation }, SearchDirectories = assemblyResolver.GetSearchDirectories(), SearchAssemblies = references, }; // Run ILMerge var merge = new ILRepacking.ILRepack(repackOptions) { PrimaryAssemblyDefinition = assembly, MemoryOnly = true, //KeepFirstOfMultipleAssemblyLevelAttributes = true, //Log = true, //LogFile = "ilmerge.log", }; try { var consoleWriter = Console.Out; Console.SetOut(TextWriter.Null); try { merge.Repack(); } finally { Console.SetOut(consoleWriter); } } catch (Exception) { log.WriteLine($"Error while ILRepacking {assembly.Name.Name}"); throw; } // Copy name merge.TargetAssemblyDefinition.Name.Name = assembly.Name.Name; merge.TargetAssemblyDefinition.Name.Version = assembly.Name.Version; // Copy assembly characterics. This is necessary especially when targeting a windows app merge.TargetAssemblyMainModule.Characteristics = assembly.MainModule.Characteristics; // Add assembly signing info if (assembly.Name.HasPublicKey) { merge.TargetAssemblyDefinition.Name.PublicKey = assembly.Name.PublicKey; merge.TargetAssemblyDefinition.Name.PublicKeyToken = assembly.Name.PublicKeyToken; merge.TargetAssemblyDefinition.Name.Attributes |= AssemblyAttributes.PublicKey; if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned) { merge.TargetAssemblyMainModule.Attributes |= ModuleAttributes.StrongNameSigned; } } try { // Delete serializer dll File.Delete(serializationAssemblyLocation); var serializationAssemblyPdbFilePath = Path.ChangeExtension(serializationAssemblyLocation, "pdb"); if (File.Exists(serializationAssemblyPdbFilePath)) { File.Delete(serializationAssemblyPdbFilePath); } } catch (IOException) { // Mute IOException } return(merge.TargetAssemblyDefinition); }
public static AssemblyDefinition GenerateRoslynAssembly(BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, string serializationAssemblyLocation, string signKeyFile, List<string> references, List<AssemblyDefinition> memoryReferences, ILogger log, IEnumerable<string> sourceCodes) { var syntaxTrees = sourceCodes.Select(x => CSharpSyntaxTree.ParseText(x)); var compilerOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true, assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default); // Sign the serialization assembly the same way the source was signed // TODO: Transmit over command line if (assembly.Name.HasPublicKey) { // TODO: If delay signed, we could actually extract the public key and apply it ourself maybe? if (signKeyFile == null) throw new InvalidOperationException("Generating serialization code for signed assembly, but no key was specified."); compilerOptions = compilerOptions.WithCryptoKeyFile(signKeyFile).WithStrongNameProvider(new DesktopStrongNameProvider()); if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) != ModuleAttributes.StrongNameSigned) { // Delay signed compilerOptions = compilerOptions.WithDelaySign(true); } } // Add references (files and in-memory PE data) var metadataReferences = new List<MetadataReference>(); foreach (var reference in references) { metadataReferences.Add(MetadataReference.CreateFromFile(reference)); } foreach (var reference in memoryReferences) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, reference)); } // typeof(Dictionary<,>) // Special case for 4.5: Because Dictionary<,> is forwarded, we need to add a reference to the actual assembly var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly); metadataReferences.Add(CreateMetadataReference(assemblyResolver, mscorlibAssembly)); var collectionType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Dictionary<,>).FullName); metadataReferences.Add(CreateMetadataReference(assemblyResolver, collectionType.Module.Assembly)); metadataReferences.Add(CreateMetadataReference(assemblyResolver, assembly)); // In case SiliconStudio.Core was not referenced, let's add it. if (assembly.Name.Name != "SiliconStudio.Core" && !references.Any(x => string.Compare(Path.GetFileNameWithoutExtension(x), "SiliconStudio.Core", StringComparison.OrdinalIgnoreCase) == 0)) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("SiliconStudio.Core"))); } // Create roslyn compilation object var assemblyName = assembly.Name.Name + ".Serializers"; var compilation = CSharpCompilation.Create(assemblyName, syntaxTrees, metadataReferences, compilerOptions); // Do the actual compilation, and check errors using (var peStream = new FileStream(serializationAssemblyLocation, FileMode.Create, FileAccess.Write)) { var compilationResult = compilation.Emit(peStream); if (!compilationResult.Success) { var errors = new StringBuilder(); errors.AppendLine(string.Format("Serialization assembly compilation: {0} error(s)", compilationResult.Diagnostics.Count(x => x.Severity >= DiagnosticSeverity.Error))); foreach (var error in compilationResult.Diagnostics) { if (error.Severity >= DiagnosticSeverity.Warning) errors.AppendLine(error.ToString()); } throw new InvalidOperationException(errors.ToString()); } } var repackOptions = new ILRepacking.RepackOptions(new string[0]) { OutputFile = assembly.MainModule.FullyQualifiedName, DebugInfo = true, CopyAttributes = true, AllowMultipleAssemblyLevelAttributes = true, XmlDocumentation = false, NoRepackRes = true, InputAssemblies = new[] { serializationAssemblyLocation }, SearchDirectories = assemblyResolver.GetSearchDirectories(), SearchAssemblies = references, }; // Run ILMerge var merge = new ILRepacking.ILRepack(repackOptions) { PrimaryAssemblyDefinition = assembly, MemoryOnly = true, //KeepFirstOfMultipleAssemblyLevelAttributes = true, //Log = true, //LogFile = "ilmerge.log", }; try { var consoleWriter = Console.Out; Console.SetOut(TextWriter.Null); try { merge.Repack(); } finally { Console.SetOut(consoleWriter); } } catch (Exception) { log.Log(new LogMessage("ILRepack", LogMessageType.Error, string.Format("Error while ILRepacking {0}", assembly.Name.Name))); throw; } // Copy name merge.TargetAssemblyDefinition.Name.Name = assembly.Name.Name; merge.TargetAssemblyDefinition.Name.Version = assembly.Name.Version; // Add assembly signing info if (assembly.Name.HasPublicKey) { merge.TargetAssemblyDefinition.Name.PublicKey = assembly.Name.PublicKey; merge.TargetAssemblyDefinition.Name.PublicKeyToken = assembly.Name.PublicKeyToken; merge.TargetAssemblyDefinition.Name.Attributes |= AssemblyAttributes.PublicKey; if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned) merge.TargetAssemblyMainModule.Attributes |= ModuleAttributes.StrongNameSigned; } try { // Delete serializer dll File.Delete(serializationAssemblyLocation); var serializationAssemblyPdbFilePath = Path.ChangeExtension(serializationAssemblyLocation, "pdb"); if (File.Exists(serializationAssemblyPdbFilePath)) { File.Delete(serializationAssemblyPdbFilePath); } } catch (IOException) { // Mute IOException } return merge.TargetAssemblyDefinition; }
public static AssemblyDefinition GenerateSerializationAssembly(PlatformType platformType, BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, string serializationAssemblyLocation, string signKeyFile, List <string> serializatonProjectReferencePaths) { // Make sure all assemblies in serializatonProjectReferencePaths are referenced (sometimes they might be optimized out if no direct references) foreach (var serializatonProjectReferencePath in serializatonProjectReferencePaths) { var shortAssemblyName = Path.GetFileNameWithoutExtension(serializatonProjectReferencePath); // Still in references (not optimized) if (assembly.MainModule.AssemblyReferences.Any(x => x.Name == shortAssemblyName)) { continue; } // For now, use AssemblyDefinition.ReadAssembly to compute full name -- maybe not very efficient but it shouldn't happen often anyway) var referencedAssembly = AssemblyDefinition.ReadAssembly(serializatonProjectReferencePath); assembly.MainModule.AssemblyReferences.Add(AssemblyNameReference.Parse(referencedAssembly.FullName)); } // Create the serializer code generator var serializerGenerator = new ComplexSerializerCodeGenerator(assemblyResolver, assembly); // Register default serialization profile (to help AOT generic instantiation of serializers) RegisterDefaultSerializationProfile(assemblyResolver, assembly, serializerGenerator); // Generate serializer code var serializerGeneratedCode = serializerGenerator.TransformText(); var syntaxTree = CSharpSyntaxTree.ParseText(serializerGeneratedCode); // Add reference from source assembly // Use a hash set because it seems including twice mscorlib (2.0 and 4.0) seems to be a problem. var skipWindows = "Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null"; var compilerOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true); // Sign the serialization assembly the same way the source was signed // TODO: Transmit over command line if (assembly.Name.HasPublicKey) { // TODO: If delay signed, we could actually extract the public key and apply it ourself maybe? if (signKeyFile == null) { throw new InvalidOperationException("Generating serialization code for signed assembly, but no key was specified."); } compilerOptions = compilerOptions.WithCryptoKeyFile(signKeyFile).WithStrongNameProvider(new DesktopStrongNameProvider()); if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) != ModuleAttributes.StrongNameSigned) { // Delay signed compilerOptions = compilerOptions.WithDelaySign(true); } } var metadataReferences = new List <MetadataReference>(); var assemblyLocations = new HashSet <string>(); foreach (var referencedAssemblyName in assembly.MainModule.AssemblyReferences) { // We skip both Windows, and current assembly (AssemblyProcessor.Common, which might be added with an alias) if (referencedAssemblyName.FullName != skipWindows && referencedAssemblyName.FullName != typeof(ComplexSerializerGenerator).Assembly.FullName && referencedAssemblyName.FullName != "SiliconStudio.AssemblyProcessor") { if (assemblyLocations.Add(referencedAssemblyName.Name)) { //Console.WriteLine("Resolve Assembly for serialization [{0}]", referencedAssemblyName.FullName); metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve(referencedAssemblyName))); } } } // typeof(Dictionary<,>) // Special case for 4.5: Because Dictionary<,> is forwarded, we need to add a reference to the actual assembly var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly); metadataReferences.Add(CreateMetadataReference(assemblyResolver, mscorlibAssembly)); var collectionType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Dictionary <,>).FullName); metadataReferences.Add(CreateMetadataReference(assemblyResolver, collectionType.Module.Assembly)); // Make sure System and System.Reflection are added // TODO: Maybe we should do that for .NETCore and PCL too? (instead of WinRT only) if (platformType == PlatformType.WindowsStore || platformType == PlatformType.WindowsPhone) { if (assemblyLocations.Add("System")) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("System"))); } if (assemblyLocations.Add("System.Reflection")) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("System.Reflection"))); } } metadataReferences.Add(CreateMetadataReference(assemblyResolver, assembly)); assemblyLocations.Add(assembly.Name.Name); // In case Paradox.Framework.Serialization was not referenced, let's add it. if (!assemblyLocations.Contains("SiliconStudio.Core")) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("SiliconStudio.Core"))); assemblyLocations.Add("SiliconStudio.Core"); } // Create roslyn compilation object var assemblyName = Path.GetFileNameWithoutExtension(serializationAssemblyLocation); var compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, metadataReferences, compilerOptions); // Do the actual compilation, and check errors using (var peStream = new FileStream(serializationAssemblyLocation, FileMode.Create, FileAccess.Write)) { var compilationResult = compilation.Emit(peStream); if (!compilationResult.Success) { var errors = new StringBuilder(); errors.AppendLine(string.Format("Serialization assembly compilation: {0} error(s)", compilationResult.Diagnostics.Count(x => x.Severity >= DiagnosticSeverity.Error))); foreach (var error in compilationResult.Diagnostics) { if (error.Severity >= DiagnosticSeverity.Warning) { errors.AppendLine(error.ToString()); } } throw new InvalidOperationException(errors.ToString()); } } // Run ILMerge var merge = new ILRepacking.ILRepack() { OutputFile = assembly.MainModule.FullyQualifiedName, DebugInfo = true, CopyAttributes = true, AllowMultipleAssemblyLevelAttributes = true, XmlDocumentation = false, NoRepackRes = true, PrimaryAssemblyDefinition = assembly, WriteToDisk = false, //KeepFirstOfMultipleAssemblyLevelAttributes = true, //Log = true, //LogFile = "ilmerge.log", }; merge.SetInputAssemblies(new string[] { serializationAssemblyLocation }); // Force to use the correct framework //merge.SetTargetPlatform("v4", frameworkFolder); merge.SetSearchDirectories(assemblyResolver.GetSearchDirectories()); merge.Merge(); // Copy name merge.TargetAssemblyDefinition.Name.Name = assembly.Name.Name; merge.TargetAssemblyDefinition.Name.Version = assembly.Name.Version; // Add assembly signing info if (assembly.Name.HasPublicKey) { merge.TargetAssemblyDefinition.Name.PublicKey = assembly.Name.PublicKey; merge.TargetAssemblyDefinition.Name.PublicKeyToken = assembly.Name.PublicKeyToken; merge.TargetAssemblyDefinition.Name.Attributes |= AssemblyAttributes.PublicKey; if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned) { merge.TargetAssemblyMainModule.Attributes |= ModuleAttributes.StrongNameSigned; } } try { // Delete serializer dll File.Delete(serializationAssemblyLocation); var serializationAssemblyPdbFilePath = Path.ChangeExtension(serializationAssemblyLocation, "pdb"); if (File.Exists(serializationAssemblyPdbFilePath)) { File.Delete(serializationAssemblyPdbFilePath); } } catch (IOException) { // Mute IOException } return(merge.TargetAssemblyDefinition); }
private static CSharpCompilationOptions AddSigningOptions(CSharpCompilationOptions options, ICompilerOptions compilerOptions, string projectDirectory) { var useOssSigning = compilerOptions.UseOssSigning == true; var keyFile = Environment.GetEnvironmentVariable(EnvironmentNames.BuildKeyFile) ?? GetKeyFileFullPath(projectDirectory, compilerOptions.KeyFile); if (!string.IsNullOrWhiteSpace(keyFile)) { #if DOTNET5_4 return options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile))); #else if (RuntimeEnvironmentHelper.IsMono || useOssSigning) { return options.WithCryptoPublicKey( SnkUtils.ExtractPublicKey(File.ReadAllBytes(keyFile))); } options = options.WithCryptoKeyFile(keyFile); var delaySignString = Environment.GetEnvironmentVariable(EnvironmentNames.BuildDelaySign); var delaySign = delaySignString == null ? compilerOptions.DelaySign : string.Equals(delaySignString, "true", StringComparison.OrdinalIgnoreCase) || string.Equals(delaySignString, "1", StringComparison.Ordinal); return options.WithDelaySign(delaySign); #endif } return useOssSigning ? options.WithCryptoPublicKey(StrongNameKey) : options; }
public static AssemblyDefinition GenerateSerializationAssembly(PlatformType platformType, BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, string serializationAssemblyLocation, string signKeyFile, List <string> references, List <AssemblyDefinition> memoryReferences, ILogger log) { // Create the serializer code generator var serializerGenerator = new ComplexSerializerCodeGenerator(assemblyResolver, assembly, log); // Register default serialization profile (to help AOT generic instantiation of serializers) RegisterDefaultSerializationProfile(assemblyResolver, assembly, serializerGenerator); // Generate serializer code var serializerGeneratedCode = serializerGenerator.TransformText(); var syntaxTree = CSharpSyntaxTree.ParseText(serializerGeneratedCode); // Add reference from source assembly // Use a hash set because it seems including twice mscorlib (2.0 and 4.0) seems to be a problem. var skipWindows = "Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null"; var compilerOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true, assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default); // Sign the serialization assembly the same way the source was signed // TODO: Transmit over command line if (assembly.Name.HasPublicKey) { // TODO: If delay signed, we could actually extract the public key and apply it ourself maybe? if (signKeyFile == null) { throw new InvalidOperationException("Generating serialization code for signed assembly, but no key was specified."); } compilerOptions = compilerOptions.WithCryptoKeyFile(signKeyFile).WithStrongNameProvider(new DesktopStrongNameProvider()); if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) != ModuleAttributes.StrongNameSigned) { // Delay signed compilerOptions = compilerOptions.WithDelaySign(true); } } // Add references (files and in-memory PE data) var metadataReferences = new List <MetadataReference>(); foreach (var reference in references) { metadataReferences.Add(MetadataReference.CreateFromFile(reference)); } foreach (var reference in memoryReferences) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, reference)); } // typeof(Dictionary<,>) // Special case for 4.5: Because Dictionary<,> is forwarded, we need to add a reference to the actual assembly var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assembly); metadataReferences.Add(CreateMetadataReference(assemblyResolver, mscorlibAssembly)); var collectionType = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Dictionary <,>).FullName); metadataReferences.Add(CreateMetadataReference(assemblyResolver, collectionType.Module.Assembly)); metadataReferences.Add(CreateMetadataReference(assemblyResolver, assembly)); // In case SiliconStudio.Core was not referenced, let's add it. if (assembly.Name.Name != "SiliconStudio.Core" && !references.Any(x => string.Compare(Path.GetFileNameWithoutExtension(x), "SiliconStudio.Core", StringComparison.OrdinalIgnoreCase) == 0)) { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve("SiliconStudio.Core"))); } // Create roslyn compilation object var assemblyName = assembly.Name.Name + ".Serializers"; var compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, metadataReferences, compilerOptions); // Do the actual compilation, and check errors using (var peStream = new FileStream(serializationAssemblyLocation, FileMode.Create, FileAccess.Write)) { var compilationResult = compilation.Emit(peStream); if (!compilationResult.Success) { var errors = new StringBuilder(); errors.AppendLine(string.Format("Serialization assembly compilation: {0} error(s)", compilationResult.Diagnostics.Count(x => x.Severity >= DiagnosticSeverity.Error))); foreach (var error in compilationResult.Diagnostics) { if (error.Severity >= DiagnosticSeverity.Warning) { errors.AppendLine(error.ToString()); } } throw new InvalidOperationException(errors.ToString()); } } var repackOptions = new ILRepacking.RepackOptions(new string[0]) { OutputFile = assembly.MainModule.FullyQualifiedName, DebugInfo = true, CopyAttributes = true, AllowMultipleAssemblyLevelAttributes = true, XmlDocumentation = false, NoRepackRes = true, InputAssemblies = new[] { serializationAssemblyLocation }, SearchDirectories = assemblyResolver.GetSearchDirectories(), SearchAssemblies = references, }; // Run ILMerge var merge = new ILRepacking.ILRepack(repackOptions) { PrimaryAssemblyDefinition = assembly, MemoryOnly = true, //KeepFirstOfMultipleAssemblyLevelAttributes = true, //Log = true, //LogFile = "ilmerge.log", }; try { merge.Repack(); } catch (Exception) { log.Log(new LogMessage("ILRepack", LogMessageType.Error, string.Format("Error while ILRepacking {0}", assembly.Name.Name))); throw; } // Copy name merge.TargetAssemblyDefinition.Name.Name = assembly.Name.Name; merge.TargetAssemblyDefinition.Name.Version = assembly.Name.Version; // Add assembly signing info if (assembly.Name.HasPublicKey) { merge.TargetAssemblyDefinition.Name.PublicKey = assembly.Name.PublicKey; merge.TargetAssemblyDefinition.Name.PublicKeyToken = assembly.Name.PublicKeyToken; merge.TargetAssemblyDefinition.Name.Attributes |= AssemblyAttributes.PublicKey; if ((assembly.MainModule.Attributes & ModuleAttributes.StrongNameSigned) == ModuleAttributes.StrongNameSigned) { merge.TargetAssemblyMainModule.Attributes |= ModuleAttributes.StrongNameSigned; } } try { // Delete serializer dll File.Delete(serializationAssemblyLocation); var serializationAssemblyPdbFilePath = Path.ChangeExtension(serializationAssemblyLocation, "pdb"); if (File.Exists(serializationAssemblyPdbFilePath)) { File.Delete(serializationAssemblyPdbFilePath); } } catch (IOException) { // Mute IOException } return(merge.TargetAssemblyDefinition); }