예제 #1
0
        public static bool Execute(
            string seeds,
            string contracts,
            string facadePath,
            Version assemblyFileVersion               = null,
            bool clearBuildAndRevision                = false,
            bool ignoreMissingTypes                   = false,
            bool ignoreBuildAndRevisionMismatch       = false,
            bool buildDesignTimeFacades               = false,
            string inclusionContracts                 = null,
            ErrorTreatment seedLoadErrorTreatment     = ErrorTreatment.Default,
            ErrorTreatment contractLoadErrorTreatment = ErrorTreatment.Default,
            string[] seedTypePreferencesUnsplit       = null,
            bool forceZeroVersionSeeds                = false,
            bool producePdb = true,
            string partialFacadeAssemblyPath = null)
        {
            if (!Directory.Exists(facadePath))
            {
                Directory.CreateDirectory(facadePath);
            }

            var nameTable     = new NameTable();
            var internFactory = new InternFactory();

            try
            {
                Dictionary <string, string> seedTypePreferences = ParseSeedTypePreferences(seedTypePreferencesUnsplit);

                using (var contractHost = new HostEnvironment(nameTable, internFactory))
                    using (var seedHost = new HostEnvironment(nameTable, internFactory))
                    {
                        contractHost.LoadErrorTreatment = contractLoadErrorTreatment;
                        seedHost.LoadErrorTreatment     = seedLoadErrorTreatment;

                        var contractAssemblies = LoadAssemblies(contractHost, contracts);
                        IReadOnlyDictionary <string, IEnumerable <string> > docIdTable = GenerateDocIdTable(contractAssemblies, inclusionContracts);

                        IAssembly[] seedAssemblies = LoadAssemblies(seedHost, seeds).ToArray();

                        IAssemblyReference seedCoreAssemblyRef = ((Microsoft.Cci.Immutable.PlatformType)seedHost.PlatformType).CoreAssemblyRef;

                        if (forceZeroVersionSeeds)
                        {
                            // Create a deep copier, copy the seed assemblies, and zero out their versions.
                            var copier = new MetadataDeepCopier(seedHost);

                            for (int i = 0; i < seedAssemblies.Length; i++)
                            {
                                var mutableSeed = copier.Copy(seedAssemblies[i]);
                                mutableSeed.Version = new Version(0, 0, 0, 0);
                                // Copy the modified seed assembly back.
                                seedAssemblies[i] = mutableSeed;

                                if (mutableSeed.Name.UniqueKey == seedCoreAssemblyRef.Name.UniqueKey)
                                {
                                    seedCoreAssemblyRef = mutableSeed;
                                }
                            }
                        }

                        var typeTable       = GenerateTypeTable(seedAssemblies);
                        var facadeGenerator = new FacadeGenerator(seedHost, contractHost, docIdTable, typeTable, seedTypePreferences, clearBuildAndRevision, buildDesignTimeFacades, assemblyFileVersion);

                        if (partialFacadeAssemblyPath != null)
                        {
                            if (contractAssemblies.Count() != 1)
                            {
                                throw new FacadeGenerationException(
                                          "When partialFacadeAssemblyPath is specified, only exactly one corresponding contract assembly can be specified.");
                            }

                            IAssembly contractAssembly      = contractAssemblies.First();
                            IAssembly partialFacadeAssembly = seedHost.LoadAssembly(partialFacadeAssemblyPath);
                            if (contractAssembly.Name != partialFacadeAssembly.Name ||
                                contractAssembly.Version.Major != partialFacadeAssembly.Version.Major ||
                                contractAssembly.Version.Minor != partialFacadeAssembly.Version.Minor ||
                                (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Build != partialFacadeAssembly.Version.Build) ||
                                (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Revision != partialFacadeAssembly.Version.Revision) ||
                                contractAssembly.GetPublicKeyToken() != partialFacadeAssembly.GetPublicKeyToken())
                            {
                                throw new FacadeGenerationException(
                                          string.Format("The partial facade assembly's name, version, and public key token must exactly match the contract to be filled. Contract: {0}, Facade: {1}",
                                                        contractAssembly.AssemblyIdentity,
                                                        partialFacadeAssembly.AssemblyIdentity));
                            }

                            Assembly filledPartialFacade = facadeGenerator.GenerateFacade(contractAssembly, seedCoreAssemblyRef, ignoreMissingTypes, overrideContractAssembly: partialFacadeAssembly);

                            if (filledPartialFacade == null)
                            {
                                Trace.TraceError("Errors were encountered while generating the facade.");
                                return(false);
                            }

                            string pdbLocation = null;

                            if (producePdb)
                            {
                                string pdbFolder = Path.GetDirectoryName(partialFacadeAssemblyPath);
                                pdbLocation = Path.Combine(pdbFolder, contractAssembly.Name + ".pdb");
                                if (producePdb && !File.Exists(pdbLocation))
                                {
                                    pdbLocation = null;
                                    Trace.TraceWarning("No PDB file present for un-transformed partial facade. No PDB will be generated.");
                                }
                            }

                            OutputFacadeToFile(facadePath, seedHost, filledPartialFacade, contractAssembly, pdbLocation);
                        }
                        else
                        {
                            foreach (var contract in contractAssemblies)
                            {
                                Assembly facade = facadeGenerator.GenerateFacade(contract, seedCoreAssemblyRef, ignoreMissingTypes);
                                if (facade == null)
                                {
#if !COREFX
                                    Debug.Assert(Environment.ExitCode != 0);
#endif
                                    return(false);
                                }

                                OutputFacadeToFile(facadePath, seedHost, facade, contract);
                            }
                        }
                    }

                return(true);
            }
            catch (FacadeGenerationException ex)
            {
                Trace.TraceError(ex.Message);
#if !COREFX
                Debug.Assert(Environment.ExitCode != 0);
#endif
                return(false);
            }
        }
예제 #2
0
        public static void Main(string[] args)
        {
            string         seeds                          = null;
            string         contracts                      = null;
            string         facadePath                     = null;
            Version        assemblyFileVersion            = null;
            bool           clearBuildAndRevision          = false;
            bool           ignoreMissingTypes             = false;
            bool           ignoreBuildAndRevisionMismatch = false;
            bool           buildDesignTimeFacades         = false;
            string         inclusionContracts             = null;
            ErrorTreatment seedLoadErrorTreatment         = ErrorTreatment.Default;
            ErrorTreatment contractLoadErrorTreatment     = ErrorTreatment.Default;

            string[] seedTypePreferencesUnsplit = null;
            bool     forceZeroVersionSeeds      = false;
            bool     producePdb = true;
            string   partialFacadeAssemblyPath = null;

            bool parsingSucceeded = CommandLineParser.ParseForConsoleApplication((parser) =>
            {
                parser.DefineQualifier("facadePath", ref facadePath, "Path to output the facades.");
                parser.DefineQualifier("seeds", ref seeds, "Path to the seed assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'.");
                parser.DefineQualifier("contracts", ref contracts, "Path to the contract assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'.");
                parser.DefineOptionalQualifier("assemblyFileVersion", ref assemblyFileVersion, "Override the AssemblyFileVersion attribute from the contract with the given version for the generated facade.");
                parser.DefineOptionalQualifier("clearBuildAndRevision", ref clearBuildAndRevision, "Generate facade assembly version x.y.0.0 for contract version x.y.z.w");
                parser.DefineOptionalQualifier("ignoreBuildAndRevisionMismatch", ref ignoreBuildAndRevisionMismatch, "Ignore a mismatch in revision and build for partial facade.");
                parser.DefineOptionalQualifier("ignoreMissingTypes", ref ignoreMissingTypes, "Ignore types that cannot be found in the seed assemblies. This is not recommended but is sometimes helpful while hacking around or trying to produce partial facades.");
                parser.DefineOptionalQualifier("designTime", ref buildDesignTimeFacades, "Enable design-time facade generation (marks facades with reference assembly flag and attribute).");
                parser.DefineOptionalQualifier("include", ref inclusionContracts, "Add types from these contracts to the facades. Can contain multiple assemblies or directories delimited by ',' or ';'.");
                parser.DefineOptionalQualifier("seedError", ref seedLoadErrorTreatment, "Error handling for seed assembly load failure.");
                parser.DefineOptionalQualifier("contractError", ref seedLoadErrorTreatment, "Error handling for contract assembly load failure.");
                parser.DefineOptionalQualifier("preferSeedType", ref seedTypePreferencesUnsplit, "Set which seed assembly to choose for a given type when it is defined in more than one assembly. Format: FullTypeName=PreferredSeedAssemblyName");
                parser.DefineOptionalQualifier("forceZeroVersionSeeds", ref forceZeroVersionSeeds, "Forces all seed assembly versions to 0.0.0.0, regardless of their true version.");
                parser.DefineOptionalQualifier("partialFacadeAssemblyPath", ref partialFacadeAssemblyPath, "Specifies the path to a single partial facade assembly, into which appropriate type forwards will be added to satisfy the given contract. If this option is specified, only a single partial assembly and a single contract may be given.");
                parser.DefineOptionalQualifier("producePdb", ref producePdb, "Specifices if a PDB file should be produced for the resulting partial facade.");
            }, args);

            if (!parsingSucceeded)
            {
                return;
            }

            CommandLineTraceHandler.Enable();

            if (!Directory.Exists(facadePath))
            {
                Directory.CreateDirectory(facadePath);
            }

            var nameTable     = new NameTable();
            var internFactory = new InternFactory();

            try
            {
                Dictionary <string, string> seedTypePreferences = ParseSeedTypePreferences(seedTypePreferencesUnsplit);

                using (var contractHost = new HostEnvironment(nameTable, internFactory))
                    using (var seedHost = new HostEnvironment(nameTable, internFactory))
                    {
                        contractHost.LoadErrorTreatment = contractLoadErrorTreatment;
                        seedHost.LoadErrorTreatment     = seedLoadErrorTreatment;

                        var contractAssemblies = LoadAssemblies(contractHost, contracts);
                        IReadOnlyDictionary <string, IEnumerable <string> > docIdTable = GenerateDocIdTable(contractAssemblies, inclusionContracts);

                        IAssembly[] seedAssemblies = LoadAssemblies(seedHost, seeds).ToArray();

                        IAssemblyReference seedCoreAssemblyRef = ((Microsoft.Cci.Immutable.PlatformType)seedHost.PlatformType).CoreAssemblyRef;

                        if (forceZeroVersionSeeds)
                        {
                            // Create a deep copier, copy the seed assemblies, and zero out their versions.
                            var copier = new MetadataDeepCopier(seedHost);

                            for (int i = 0; i < seedAssemblies.Length; i++)
                            {
                                var mutableSeed = copier.Copy(seedAssemblies[i]);
                                mutableSeed.Version = new Version(0, 0, 0, 0);
                                // Copy the modified seed assembly back.
                                seedAssemblies[i] = mutableSeed;

                                if (mutableSeed.Name.UniqueKey == seedCoreAssemblyRef.Name.UniqueKey)
                                {
                                    seedCoreAssemblyRef = mutableSeed;
                                }
                            }
                        }

                        var typeTable       = GenerateTypeTable(seedAssemblies);
                        var facadeGenerator = new FacadeGenerator(seedHost, contractHost, docIdTable, typeTable, seedTypePreferences, clearBuildAndRevision, buildDesignTimeFacades, assemblyFileVersion);

                        if (partialFacadeAssemblyPath != null)
                        {
                            if (contractAssemblies.Count() != 1)
                            {
                                throw new FacadeGenerationException(
                                          "When partialFacadeAssemblyPath is specified, only exactly one corresponding contract assembly can be specified.");
                            }

                            IAssembly contractAssembly      = contractAssemblies.First();
                            IAssembly partialFacadeAssembly = seedHost.LoadAssembly(partialFacadeAssemblyPath);
                            if (contractAssembly.Name != partialFacadeAssembly.Name ||
                                contractAssembly.Version.Major != partialFacadeAssembly.Version.Major ||
                                contractAssembly.Version.Minor != partialFacadeAssembly.Version.Minor ||
                                (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Build != partialFacadeAssembly.Version.Build) ||
                                (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Revision != partialFacadeAssembly.Version.Revision) ||
                                contractAssembly.GetPublicKeyToken() != partialFacadeAssembly.GetPublicKeyToken())
                            {
                                throw new FacadeGenerationException(
                                          string.Format("The partial facade assembly's name, version, and public key token must exactly match the contract to be filled. Contract: {0}, Facade: {1}",
                                                        contractAssembly.AssemblyIdentity,
                                                        partialFacadeAssembly.AssemblyIdentity));
                            }

                            Assembly filledPartialFacade = facadeGenerator.GenerateFacade(contractAssembly, seedCoreAssemblyRef, ignoreMissingTypes, overrideContractAssembly: partialFacadeAssembly);

                            string pdbLocation = null;

                            if (producePdb)
                            {
                                string pdbFolder = Path.GetDirectoryName(partialFacadeAssemblyPath);
                                pdbLocation = Path.Combine(pdbFolder, contractAssembly.Name + ".pdb");
                                if (producePdb && !File.Exists(pdbLocation))
                                {
                                    pdbLocation = null;
                                    Trace.TraceWarning("No PDB file present for un-transformed partial facade. No PDB will be generated.");
                                }
                            }

                            OutputFacadeToFile(facadePath, seedHost, filledPartialFacade, contractAssembly, pdbLocation);
                        }
                        else
                        {
                            foreach (var contract in contractAssemblies)
                            {
                                Assembly facade = facadeGenerator.GenerateFacade(contract, seedCoreAssemblyRef, ignoreMissingTypes);
                                if (facade == null)
                                {
#if !COREFX
                                    Debug.Assert(Environment.ExitCode != 0);
#endif
                                    continue;
                                }

                                OutputFacadeToFile(facadePath, seedHost, facade, contract);
                            }
                        }
                    }
            }
            catch (FacadeGenerationException ex)
            {
                Trace.TraceError(ex.Message);
#if !COREFX
                Debug.Assert(Environment.ExitCode != 0);
#endif
            }
        }
예제 #3
0
        public static void Main(string[] args)
        {
            string seeds = null;
            string contracts = null;
            string facadePath = null;
            Version assemblyFileVersion = null;
            bool clearBuildAndRevision = false;
            bool ignoreMissingTypes = false;
            bool buildDesignTimeFacades = false;
            string inclusionContracts = null;
            ErrorTreatment seedLoadErrorTreatment = ErrorTreatment.Default;
            ErrorTreatment contractLoadErrorTreatment = ErrorTreatment.Default;
            string[] seedTypePreferencesUnsplit = null;
            bool forceZeroVersionSeeds = false;
            bool producePdb = true;
            string partialFacadeAssemblyPath = null;

            bool parsingSucceeded = CommandLineParser.ParseForConsoleApplication((parser) =>
            {
                parser.DefineQualifier("facadePath", ref facadePath, "Path to output the facades.");
                parser.DefineQualifier("seeds", ref seeds, "Path to the seed assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'.");
                parser.DefineQualifier("contracts", ref contracts, "Path to the contract assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'.");
                parser.DefineOptionalQualifier("assemblyFileVersion", ref assemblyFileVersion, "Override the AssemblyFileVersion attribute from the contract with the given version for the generated facade.");
                parser.DefineOptionalQualifier("clearBuildAndRevision", ref clearBuildAndRevision, "Generate facade assembly version x.y.0.0 for contract version x.y.z.w");
                parser.DefineOptionalQualifier("ignoreMissingTypes", ref ignoreMissingTypes, "Ignore types that cannot be found in the seed assemblies. This is not recommended but is sometimes helpful while hacking around or trying to produce partial facades.");
                parser.DefineOptionalQualifier("designTime", ref buildDesignTimeFacades, "Enable design-time facade generation (marks facades with reference assembly flag and attribute).");
                parser.DefineOptionalQualifier("include", ref inclusionContracts, "Add types from these contracts to the facades. Can contain multiple assemblies or directories delimited by ',' or ';'.");
                parser.DefineOptionalQualifier("seedError", ref seedLoadErrorTreatment, "Error handling for seed assembly load failure.");
                parser.DefineOptionalQualifier("contractError", ref seedLoadErrorTreatment, "Error handling for contract assembly load failure.");
                parser.DefineOptionalQualifier("preferSeedType", ref seedTypePreferencesUnsplit, "Set which seed assembly to choose for a given type when it is defined in more than one assembly. Format: FullTypeName=PreferredSeedAssemblyName");
                parser.DefineOptionalQualifier("forceZeroVersionSeeds", ref forceZeroVersionSeeds, "Forces all seed assembly versions to 0.0.0.0, regardless of their true version.");
                parser.DefineOptionalQualifier("partialFacadeAssemblyPath", ref partialFacadeAssemblyPath, "Specifies the path to a single partial facade assembly, into which appropriate type forwards will be added to satisfy the given contract. If this option is specified, only a single partial assembly and a single contract may be given.");
                parser.DefineOptionalQualifier("producePdb", ref producePdb, "Specifices if a PDB file should be produced for the resulting partial facade.");
            }, args);

            if (!parsingSucceeded)
            {
                return;
            }

            CommandLineTraceHandler.Enable();

            if (!Directory.Exists(facadePath))
                Directory.CreateDirectory(facadePath);

            var nameTable = new NameTable();
            var internFactory = new InternFactory();

            try
            {
                Dictionary<string, string> seedTypePreferences = ParseSeedTypePreferences(seedTypePreferencesUnsplit);

                using (var contractHost = new HostEnvironment(nameTable, internFactory))
                using (var seedHost = new HostEnvironment(nameTable, internFactory))
                {
                    contractHost.LoadErrorTreatment = contractLoadErrorTreatment;
                    seedHost.LoadErrorTreatment = seedLoadErrorTreatment;

                    var contractAssemblies = LoadAssemblies(contractHost, contracts);
                    IReadOnlyDictionary<string, IEnumerable<string>> docIdTable = GenerateDocIdTable(contractAssemblies, inclusionContracts);

                    IAssembly[] seedAssemblies = LoadAssemblies(seedHost, seeds).ToArray();

                    IAssemblyReference seedCoreAssemblyRef = ((Microsoft.Cci.Immutable.PlatformType)seedHost.PlatformType).CoreAssemblyRef;

                    if (forceZeroVersionSeeds)
                    {
                        // Create a deep copier, copy the seed assemblies, and zero out their versions.
                        var copier = new MetadataDeepCopier(seedHost);

                        for (int i = 0; i < seedAssemblies.Length; i++)
                        {
                            var mutableSeed = copier.Copy(seedAssemblies[i]);
                            mutableSeed.Version = new Version(0, 0, 0, 0);
                            // Copy the modified seed assembly back.
                            seedAssemblies[i] = mutableSeed;

                            if (mutableSeed.Name.UniqueKey == seedCoreAssemblyRef.Name.UniqueKey)
                            {
                                seedCoreAssemblyRef = mutableSeed;
                            }
                        }
                    }

                    var typeTable = GenerateTypeTable(seedAssemblies);
                    var facadeGenerator = new FacadeGenerator(seedHost, contractHost, docIdTable, typeTable, seedTypePreferences, clearBuildAndRevision, buildDesignTimeFacades, assemblyFileVersion);

                    if (partialFacadeAssemblyPath != null)
                    {
                        if (contractAssemblies.Count() != 1)
                        {
                            throw new FacadeGenerationException(
                                "When partialFacadeAssemblyPath is specified, only exactly one corresponding contract assembly can be specified.");
                        }

                        IAssembly contractAssembly = contractAssemblies.First();
                        IAssembly partialFacadeAssembly = seedHost.LoadAssembly(partialFacadeAssemblyPath);
                        if (contractAssembly.Name != partialFacadeAssembly.Name
                            || contractAssembly.Version != partialFacadeAssembly.Version
                            || contractAssembly.GetPublicKeyToken() != partialFacadeAssembly.GetPublicKeyToken())
                        {
                            throw new FacadeGenerationException(
                                string.Format("The partial facade assembly's name, version, and public key token must exactly match the contract to be filled. Contract: {0}, Facade: {1}",
                                    contractAssembly.AssemblyIdentity,
                                    partialFacadeAssembly.AssemblyIdentity));
                        }

                        Assembly filledPartialFacade = facadeGenerator.GenerateFacade(contractAssembly, seedCoreAssemblyRef, ignoreMissingTypes, overrideContractAssembly: partialFacadeAssembly);

                        string pdbLocation = null;

                        if (producePdb)
                        {
                            string pdbFolder = Path.GetDirectoryName(partialFacadeAssemblyPath);
                            pdbLocation = Path.Combine(pdbFolder, contractAssembly.Name + ".pdb");
                            if (producePdb && !File.Exists(pdbLocation))
                            {
                                pdbLocation = null;
                                Trace.TraceWarning("No PDB file present for un-transformed partial facade. No PDB will be generated.");
                            }
                        }

                        OutputFacadeToFile(facadePath, seedHost, filledPartialFacade, contractAssembly, pdbLocation);
                    }
                    else
                    {
                        foreach (var contract in contractAssemblies)
                        {
                            Assembly facade = facadeGenerator.GenerateFacade(contract, seedCoreAssemblyRef, ignoreMissingTypes);
                            if (facade == null)
                            {
#if !COREFX
                                Debug.Assert(Environment.ExitCode != 0);
#endif
                                continue;
                            }

                            OutputFacadeToFile(facadePath, seedHost, facade, contract);
                        }
                    }
                }
            }
            catch (FacadeGenerationException ex)
            {
                Trace.TraceError(ex.Message);
#if !COREFX
                Debug.Assert(Environment.ExitCode != 0);
#endif
            }
        }