private static Collection <string> GetDefaultMonoGacPaths() { Collection <string> strs = new Collection <string>(1); string currentMonoGac = BaseAssemblyResolver.GetCurrentMonoGac(); if (currentMonoGac != null) { strs.Add(currentMonoGac); } string environmentVariable = Environment.GetEnvironmentVariable("MONO_GAC_PREFIX"); if (string.IsNullOrEmpty(environmentVariable)) { return(strs); } string[] strArrays = environmentVariable.Split(new char[] { Path.PathSeparator }); for (int i = 0; i < (int)strArrays.Length; i++) { string str = strArrays[i]; if (!string.IsNullOrEmpty(str)) { string str1 = Path.Combine(Path.Combine(Path.Combine(str, "lib"), "mono"), "gac"); if (Directory.Exists(str1) && !strs.Contains(currentMonoGac)) { strs.Add(str1); } } } return(strs); }
public AssemblyProcessorContext(BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, PlatformType platform, TextWriter log) { AssemblyResolver = assemblyResolver; Assembly = assembly; Platform = platform; Log = log; }
public static string GenerateSerializationAssembly(BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, 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 return serializerGenerator.TransformText(); }
private AssemblyDefinition GetAssemblyInMonoGac(AssemblyNameReference reference, ReaderParameters parameters) { for (int i = 0; i < this.gac_paths.Count; i++) { string item = this.gac_paths[i]; string assemblyFile = BaseAssemblyResolver.GetAssemblyFile(reference, string.Empty, item); if (File.Exists(assemblyFile)) { return(this.GetAssembly(assemblyFile, parameters)); } } return(null); }
private AssemblyDefinition GetAssemblyInGac(AssemblyNameReference reference, ReaderParameters parameters) { if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0) { return(null); } if (this.gac_paths == null) { this.gac_paths = BaseAssemblyResolver.GetGacPaths(); } if (BaseAssemblyResolver.on_mono) { return(this.GetAssemblyInMonoGac(reference, parameters)); } return(this.GetAssemblyInNetGac(reference, parameters)); }
private static Collection <string> GetGacPaths() { if (BaseAssemblyResolver.on_mono) { return(BaseAssemblyResolver.GetDefaultMonoGacPaths()); } Collection <string> strs = new Collection <string>(2); string environmentVariable = Environment.GetEnvironmentVariable("WINDIR"); if (environmentVariable == null) { return(strs); } strs.Add(Path.Combine(environmentVariable, "assembly")); strs.Add(Path.Combine(environmentVariable, Path.Combine("Microsoft.NET", "assembly"))); return(strs); }
private AssemblyDefinition GetAssemblyInNetGac(AssemblyNameReference reference, ReaderParameters parameters) { string[] strArrays = new string[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" }; string[] empty = new string[] { string.Empty, "v4.0_" }; for (int i = 0; i < 2; i++) { for (int j = 0; j < (int)strArrays.Length; j++) { string str = Path.Combine(this.gac_paths[i], strArrays[j]); string assemblyFile = BaseAssemblyResolver.GetAssemblyFile(reference, empty[i], str); if (Directory.Exists(str) && File.Exists(assemblyFile)) { return(this.GetAssembly(assemblyFile, parameters)); } } } return(null); }
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; }
/// <summary> /// Generates the Mono.Cecil TypeReference from its .NET <see cref="Type"/> counterpart. /// </summary> /// <param name="type">The type.</param> /// <param name="assemblyResolver">The assembly resolver.</param> /// <returns></returns> public static TypeReference GenerateTypeCecil(this Type type, BaseAssemblyResolver assemblyResolver) { var assemblyDefinition = assemblyResolver.Resolve(type.Assembly.FullName); TypeReference typeReference; if (type.IsNested) { var declaringType = GenerateTypeCecil(type.DeclaringType, assemblyResolver); typeReference = declaringType.Resolve().NestedTypes.FirstOrDefault(x => x.Name == type.Name); } else if (type.IsArray) { var elementType = GenerateTypeCecil(type.GetElementType(), assemblyResolver); typeReference = new ArrayType(elementType, type.GetArrayRank()); } else { typeReference = assemblyDefinition.MainModule.GetTypeResolved(type.IsGenericType ? type.GetGenericTypeDefinition().FullName : type.FullName); } if (typeReference == null) throw new InvalidOperationException("Could not resolve cecil type."); if (type.IsGenericType) { var genericInstanceType = new GenericInstanceType(typeReference); foreach (var argType in type.GetGenericArguments()) { TypeReference argTypeReference; if (argType.IsGenericParameter) { argTypeReference = new GenericParameter(argType.Name, typeReference); } else { argTypeReference = GenerateTypeCecil(argType, assemblyResolver); } genericInstanceType.GenericArguments.Add(argTypeReference); } typeReference = genericInstanceType; } return typeReference; }
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; }
private static void TryAddReference(BaseAssemblyResolver assemblyResolver, HashSet<string> assemblyLocations, List<MetadataReference> metadataReferences, string referenceName) { if (assemblyLocations.Add(referenceName)) { try { metadataReferences.Add(CreateMetadataReference(assemblyResolver, assemblyResolver.Resolve(referenceName))); } catch (AssemblyResolutionException) { } } }
public AssemblyProcessorContext(BaseAssemblyResolver assemblyResolver, AssemblyDefinition assembly, PlatformType platform) { AssemblyResolver = assemblyResolver; Assembly = assembly; Platform = platform; }
public virtual AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) { if (name == null) { throw new ArgumentNullException("name"); } if (parameters == null) { parameters = new ReaderParameters(); } AssemblyDefinition corlib = this.SearchDirectory(name, this.directories, parameters); if (corlib != null) { return(corlib); } if (name.IsRetargetable) { name = new AssemblyNameReference(name.Name, new Version(0, 0, 0, 0)) { PublicKeyToken = Empty <byte> .Array }; } string directoryName = Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName); if (BaseAssemblyResolver.IsZero(name.Version)) { corlib = this.SearchDirectory(name, new string[] { directoryName }, parameters); if (corlib != null) { return(corlib); } } if (name.Name == "mscorlib") { corlib = this.GetCorlib(name, parameters); if (corlib != null) { return(corlib); } } corlib = this.GetAssemblyInGac(name, parameters); if (corlib != null) { return(corlib); } corlib = this.SearchDirectory(name, new string[] { directoryName }, parameters); if (corlib != null) { return(corlib); } if (this.ResolveFailure != null) { corlib = this.ResolveFailure(this, name); if (corlib != null) { return(corlib); } } throw new AssemblyResolutionException(name); }
private AssemblyDefinition GetCorlib(AssemblyNameReference reference, ReaderParameters parameters) { Version version = reference.Version; if (typeof(object).Assembly.GetName().Version == version || BaseAssemblyResolver.IsZero(version)) { return(this.GetAssembly(typeof(object).Module.FullyQualifiedName, parameters)); } string fullName = Directory.GetParent(Directory.GetParent(typeof(object).Module.FullyQualifiedName).FullName).FullName; if (!BaseAssemblyResolver.on_mono) { switch (version.Major) { case 1: { if (version.MajorRevision != 3300) { fullName = Path.Combine(fullName, "v1.0.5000.0"); break; } else { fullName = Path.Combine(fullName, "v1.0.3705"); break; } } case 2: { fullName = Path.Combine(fullName, "v2.0.50727"); break; } case 3: { throw new NotSupportedException(string.Concat("Version not supported: ", version)); } case 4: { fullName = Path.Combine(fullName, "v4.0.30319"); break; } default: { throw new NotSupportedException(string.Concat("Version not supported: ", version)); } } } else if (version.Major == 1) { fullName = Path.Combine(fullName, "1.0"); } else if (version.Major != 2) { if (version.Major != 4) { throw new NotSupportedException(string.Concat("Version not supported: ", version)); } fullName = Path.Combine(fullName, "4.0"); } else { fullName = (version.MajorRevision != 5 ? Path.Combine(fullName, "2.0") : Path.Combine(fullName, "2.1")); } string str = Path.Combine(fullName, "mscorlib.dll"); if (!File.Exists(str)) { return(null); } return(this.GetAssembly(str, parameters)); }