예제 #1
0
        public bool Run(ref AssemblyDefinition assemblyDefinition, ref bool readWriteSymbols, out bool modified)
        {
            modified = false;

            try
            {
                var assemblyResolver = (CustomAssemblyResolver)assemblyDefinition.MainModule.AssemblyResolver;

                // Register self
                assemblyResolver.Register(assemblyDefinition);

                var processors = new List <IAssemblyDefinitionProcessor>();

                // We are no longer using it so we are deactivating it for now to avoid processing
                //if (AutoNotifyProperty)
                //{
                //    processors.Add(new NotifyPropertyProcessor());
                //}

                processors.Add(new AddReferenceProcessor(ReferencesToAdd));

                if (ParameterKey)
                {
                    processors.Add(new ParameterKeyProcessor());
                }

                if (NewAssemblyName != null)
                {
                    processors.Add(new RenameAssemblyProcessor(NewAssemblyName));
                }

                //processors.Add(new AsyncBridgeProcessor());

                // Always applies the interop processor
                processors.Add(new InteropProcessor());

                processors.Add(new AssemblyVersionProcessor());

                if (DocumentationFile != null)
                {
                    processors.Add(new GenerateUserDocumentationProcessor(DocumentationFile));
                }

                var roslynExtraCodeProcessor = new RoslynExtraCodeProcessor(SignKeyFile, References, MemoryReferences, log);

                if (SerializationAssembly)
                {
                    processors.Add(new SerializationProcessor(roslynExtraCodeProcessor.SourceCodes.Add));
                }

                processors.Add(roslynExtraCodeProcessor);

                if (ModuleInitializer)
                {
                    processors.Add(new ModuleInitializerProcessor());
                }

                processors.Add(new InitLocalsProcessor());
                processors.Add(new OpenSourceSignProcessor());

                // Check if pdb was actually read
                readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;

                // Check if there is already a AssemblyProcessedAttribute (in which case we can skip processing, it has already been done).
                // Note that we should probably also match the command line as well so that we throw an error if processing is different (need to rebuild).
                if (assemblyDefinition.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.AssemblyProcessedAttribute"))
                {
                    OnInfoAction($"Assembly [{assemblyDefinition.Name}] has already been processed, skip it.");
                    return(true);
                }

                // Register references so that our assembly resolver can use them
                foreach (var reference in References)
                {
                    assemblyResolver.RegisterReference(reference);
                }

                if (SerializationAssembly)
                {
                    // Resave a first version of assembly with [InteralsVisibleTo] for future serialization assembly.
                    // It will be used by serialization assembly compilation.
                    // It's recommended to do it in the original code to avoid this extra step.

                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing reference to mscorlib.dll or System.Runtime.dll in assembly!");
                        return(false);
                    }

                    var  internalsVisibleToAttribute    = mscorlibAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                    var  serializationAssemblyName      = assemblyDefinition.Name.Name + ".Serializers";
                    bool internalsVisibleAlreadyApplied = false;

                    // Check if already applied
                    foreach (var customAttribute in assemblyDefinition.CustomAttributes.Where(x => x.AttributeType.FullName == internalsVisibleToAttribute.FullName))
                    {
                        var assemblyName = (string)customAttribute.ConstructorArguments[0].Value;

                        int publicKeyIndex;
                        if ((publicKeyIndex = assemblyName.IndexOf(", PublicKey=", StringComparison.InvariantCulture)) != -1 || (publicKeyIndex = assemblyName.IndexOf(",PublicKey=", StringComparison.InvariantCulture)) != -1)
                        {
                            assemblyName = assemblyName.Substring(0, publicKeyIndex);
                        }

                        if (assemblyName == serializationAssemblyName)
                        {
                            internalsVisibleAlreadyApplied = true;
                            break;
                        }
                    }

                    if (!internalsVisibleAlreadyApplied)
                    {
                        // Apply public key
                        if (assemblyDefinition.Name.HasPublicKey)
                        {
                            serializationAssemblyName += ", PublicKey=" + ByteArrayToString(assemblyDefinition.Name.PublicKey);
                        }

                        // Add [InteralsVisibleTo] attribute
                        var internalsVisibleToAttributeCtor = assemblyDefinition.MainModule.ImportReference(internalsVisibleToAttribute.GetConstructors().Single());
                        var internalsVisibleAttribute       = new CustomAttribute(internalsVisibleToAttributeCtor)
                        {
                            ConstructorArguments =
                            {
                                new CustomAttributeArgument(assemblyDefinition.MainModule.TypeSystem.String, serializationAssemblyName)
                            }
                        };
                        assemblyDefinition.CustomAttributes.Add(internalsVisibleAttribute);

                        var assemblyFilePath = assemblyDefinition.MainModule.FullyQualifiedName;
                        if (string.IsNullOrEmpty(assemblyFilePath))
                        {
                            assemblyFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".dll");
                        }

                        // Save updated file
                        assemblyDefinition.Write(assemblyFilePath, new WriterParameters()
                        {
                            WriteSymbols = readWriteSymbols
                        });

                        // Reread file (otherwise it seems Mono Cecil is buggy and generate invalid PDB)
                        assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyFilePath, new ReaderParameters {
                            AssemblyResolver = assemblyResolver, ReadSymbols = readWriteSymbols
                        });

                        // Check if pdb was actually read
                        readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;
                    }
                }

                var assemblyProcessorContext = new AssemblyProcessorContext(assemblyResolver, assemblyDefinition, Platform, log);

                foreach (var processor in processors)
                {
                    modified = processor.Process(assemblyProcessorContext) || modified;
                }

                // Assembly might have been recreated (i.e. il-repack), so let's use it from now on
                assemblyDefinition = assemblyProcessorContext.Assembly;

                if (modified)
                {
                    // In case assembly has been modified,
                    // add AssemblyProcessedAttribute to assembly so that it doesn't get processed again
                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing reference to mscorlib.dll or System.Runtime.dll in assembly!");
                        return(false);
                    }

                    var attributeType    = mscorlibAssembly.MainModule.GetTypeResolved(typeof(Attribute).FullName);
                    var attributeTypeRef = assemblyDefinition.MainModule.ImportReference(attributeType);
                    var attributeCtorRef = assemblyDefinition.MainModule.ImportReference(attributeType.GetConstructors().Single(x => x.Parameters.Count == 0));
                    var voidType         = assemblyDefinition.MainModule.TypeSystem.Void;

                    // Create custom attribute
                    var assemblyProcessedAttributeType = new TypeDefinition("SiliconStudio.Core", "AssemblyProcessedAttribute", TypeAttributes.BeforeFieldInit | TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Public, attributeTypeRef);

                    // Add constructor (call parent constructor)
                    var assemblyProcessedAttributeConstructor = new MethodDefinition(".ctor", MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, voidType);
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, attributeCtorRef));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                    assemblyProcessedAttributeType.Methods.Add(assemblyProcessedAttributeConstructor);

                    // Add AssemblyProcessedAttribute to assembly
                    assemblyDefinition.MainModule.Types.Add(assemblyProcessedAttributeType);
                    assemblyDefinition.CustomAttributes.Add(new CustomAttribute(assemblyProcessedAttributeConstructor));
                }
            }
            catch (Exception e)
            {
                OnErrorAction(null, e);
                return(false);
            }

            return(true);
        }
예제 #2
0
        public bool Run(ref AssemblyDefinition assemblyDefinition, ref bool readWriteSymbols, out bool modified)
        {
            modified = false;

            try
            {
                var assemblyResolver = (CustomAssemblyResolver)assemblyDefinition.MainModule.AssemblyResolver;

                // Register self
                assemblyResolver.Register(assemblyDefinition);

                var processors = new List<IAssemblyDefinitionProcessor>();

                // We are no longer using it so we are deactivating it for now to avoid processing
                //if (AutoNotifyProperty)
                //{
                //    processors.Add(new NotifyPropertyProcessor());
                //}

                processors.Add(new AddReferenceProcessor(ReferencesToAdd));

                if (ParameterKey)
                {
                    processors.Add(new ParameterKeyProcessor());
                }

                if (NewAssemblyName != null)
                {
                    processors.Add(new RenameAssemblyProcessor(NewAssemblyName));
                }

                //processors.Add(new AsyncBridgeProcessor());

                // Always applies the interop processor
                processors.Add(new InteropProcessor());

                processors.Add(new AssemblyVersionProcessor());

                if (DocumentationFile != null)
                {
                    processors.Add(new GenerateUserDocumentationProcessor(DocumentationFile));
                }

                var roslynExtraCodeProcessor = new RoslynExtraCodeProcessor(SignKeyFile, References, MemoryReferences, log);

                if (SerializationAssembly)
                {
                    processors.Add(new SerializationProcessor(roslynExtraCodeProcessor.SourceCodes.Add));
                }

                processors.Add(roslynExtraCodeProcessor);

                if (ModuleInitializer)
                {
                    processors.Add(new ModuleInitializerProcessor());
                }

                processors.Add(new OpenSourceSignProcessor());

                // Check if pdb was actually read
                readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;

                // Check if there is already a AssemblyProcessedAttribute (in which case we can skip processing, it has already been done).
                // Note that we should probably also match the command line as well so that we throw an error if processing is different (need to rebuild).
                if (assemblyDefinition.CustomAttributes.Any(x => x.AttributeType.FullName == "SiliconStudio.Core.AssemblyProcessedAttribute"))
                {
                    OnInfoAction($"Assembly [{assemblyDefinition.Name}] has already been processed, skip it.");
                    return true;
                }

                // Register references so that our assembly resolver can use them
                foreach (var reference in References)
                {
                    assemblyResolver.RegisterReference(reference);
                }

                if (SerializationAssembly)
                {
                    // Resave a first version of assembly with [InteralsVisibleTo] for future serialization assembly.
                    // It will be used by serialization assembly compilation.
                    // It's recommended to do it in the original code to avoid this extra step.

                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing reference to mscorlib.dll or System.Runtime.dll in assembly!");
                        return false;
                    }

                    var internalsVisibleToAttribute = mscorlibAssembly.MainModule.GetTypeResolved(typeof(InternalsVisibleToAttribute).FullName);
                    var serializationAssemblyName = assemblyDefinition.Name.Name + ".Serializers";
                    bool internalsVisibleAlreadyApplied = false;

                    // Check if already applied
                    foreach (var customAttribute in assemblyDefinition.CustomAttributes.Where(x => x.AttributeType.FullName == internalsVisibleToAttribute.FullName))
                    {
                        var assemblyName = (string)customAttribute.ConstructorArguments[0].Value;

                        int publicKeyIndex;
                        if ((publicKeyIndex = assemblyName.IndexOf(", PublicKey=", StringComparison.InvariantCulture)) != -1 || (publicKeyIndex = assemblyName.IndexOf(",PublicKey=", StringComparison.InvariantCulture)) != -1)
                        {
                            assemblyName = assemblyName.Substring(0, publicKeyIndex);
                        }

                        if (assemblyName == serializationAssemblyName)
                        {
                            internalsVisibleAlreadyApplied = true;
                            break;
                        }
                    }

                    if (!internalsVisibleAlreadyApplied)
                    {
                        // Apply public key
                        if (assemblyDefinition.Name.HasPublicKey)
                            serializationAssemblyName += ", PublicKey=" + ByteArrayToString(assemblyDefinition.Name.PublicKey);

                        // Add [InteralsVisibleTo] attribute
                        var internalsVisibleToAttributeCtor = assemblyDefinition.MainModule.ImportReference(internalsVisibleToAttribute.GetConstructors().Single());
                        var internalsVisibleAttribute = new CustomAttribute(internalsVisibleToAttributeCtor)
                        {
                            ConstructorArguments =
                            {
                                new CustomAttributeArgument(assemblyDefinition.MainModule.TypeSystem.String, serializationAssemblyName)
                            }
                        };
                        assemblyDefinition.CustomAttributes.Add(internalsVisibleAttribute);

                        var assemblyFilePath = assemblyDefinition.MainModule.FullyQualifiedName;
                        if (string.IsNullOrEmpty(assemblyFilePath))
                        {
                            assemblyFilePath = Path.ChangeExtension(Path.GetTempFileName(), ".dll");
                        }

                        // Save updated file
                        assemblyDefinition.Write(assemblyFilePath, new WriterParameters() { WriteSymbols = readWriteSymbols });

                        // Reread file (otherwise it seems Mono Cecil is buggy and generate invalid PDB)
                        assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyFilePath, new ReaderParameters { AssemblyResolver = assemblyResolver, ReadSymbols = readWriteSymbols });

                        // Check if pdb was actually read
                        readWriteSymbols = assemblyDefinition.MainModule.HasDebugHeader;
                    }
                }

                var assemblyProcessorContext = new AssemblyProcessorContext(assemblyResolver, assemblyDefinition, Platform, log);

                foreach (var processor in processors)
                    modified = processor.Process(assemblyProcessorContext) || modified;

                // Assembly might have been recreated (i.e. il-repack), so let's use it from now on
                assemblyDefinition = assemblyProcessorContext.Assembly;

                if (modified)
                {
                    // In case assembly has been modified,
                    // add AssemblyProcessedAttribute to assembly so that it doesn't get processed again
                    var mscorlibAssembly = CecilExtensions.FindCorlibAssembly(assemblyDefinition);
                    if (mscorlibAssembly == null)
                    {
                        OnErrorAction("Missing reference to mscorlib.dll or System.Runtime.dll in assembly!");
                        return false;
                    }

                    var attributeType = mscorlibAssembly.MainModule.GetTypeResolved(typeof (Attribute).FullName);
                    var attributeTypeRef = assemblyDefinition.MainModule.ImportReference(attributeType);
                    var attributeCtorRef = assemblyDefinition.MainModule.ImportReference(attributeType.GetConstructors().Single(x => x.Parameters.Count == 0));
                    var voidType = assemblyDefinition.MainModule.TypeSystem.Void;

                    // Create custom attribute
                    var assemblyProcessedAttributeType = new TypeDefinition("SiliconStudio.Core", "AssemblyProcessedAttribute", TypeAttributes.BeforeFieldInit | TypeAttributes.AnsiClass | TypeAttributes.AutoClass | TypeAttributes.Public, attributeTypeRef);

                    // Add constructor (call parent constructor)
                    var assemblyProcessedAttributeConstructor = new MethodDefinition(".ctor", MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, voidType);
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Call, attributeCtorRef));
                    assemblyProcessedAttributeConstructor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                    assemblyProcessedAttributeType.Methods.Add(assemblyProcessedAttributeConstructor);

                    // Add AssemblyProcessedAttribute to assembly
                    assemblyDefinition.MainModule.Types.Add(assemblyProcessedAttributeType);
                    assemblyDefinition.CustomAttributes.Add(new CustomAttribute(assemblyProcessedAttributeConstructor));
                }
            }
            catch (Exception e)
            {
                OnErrorAction(null, e);
                return false;
            }

            return true;
        }