public override bool Execute() { TraceLogger logger = new TraceLogger(Log); try { Trace.Listeners.Add(logger); ErrorTreatment seedLoadErrorTreatment = ErrorTreatment.Default; ErrorTreatment contractLoadErrorTreatment = ErrorTreatment.Default; if (SeedLoadErrorTreatment != null) { seedLoadErrorTreatment = (ErrorTreatment)Enum.Parse(typeof(ErrorTreatment), SeedLoadErrorTreatment); } if (ContractLoadErrorTreatment != null) { contractLoadErrorTreatment = (ErrorTreatment)Enum.Parse(typeof(ErrorTreatment), ContractLoadErrorTreatment); } string[] seedTypePreferencesUnsplit = null; if (SeedTypePreferencesUnsplit != null) { seedTypePreferencesUnsplit = SeedTypePreferencesUnsplit.Select(iti => $"{iti.ItemSpec}={iti.GetMetadata("Assembly")}").ToArray(); Trace.WriteLine("seedTypePreferencesUnsplit: " + string.Join(" || ", seedTypePreferencesUnsplit)); } bool result = Generator.Execute( Seeds, Contracts, FacadePath, AssemblyFileVersion, ClearBuildAndRevision, IgnoreMissingTypes, IgnoreBuildAndRevisionMismatch, BuildDesignTimeFacades, InclusionContracts, seedLoadErrorTreatment, contractLoadErrorTreatment, seedTypePreferencesUnsplit, ForceZeroVersionSeeds, ProducePdb, PartialFacadeAssemblyPath); if (!result) { Log.LogError("Errors were encountered when generating facade(s)."); } return(result); } catch (Exception e) { Log.LogErrorFromException(e, showStackTrace: false); return(false); } finally { Trace.Listeners.Remove(logger); } }
public void TraceErrorWithLevel(ErrorTreatment level, string format, params object[] arguments) { switch (level) { case ErrorTreatment.Default: default: Trace.TraceError(format, arguments); break; case ErrorTreatment.TreatAsWarning: Trace.TraceWarning(format, arguments); break; case ErrorTreatment.Ignore: break; } }
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 } }
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); } }
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(); Generator.Execute( seeds, contracts, facadePath, assemblyFileVersion, clearBuildAndRevision, ignoreMissingTypes, ignoreBuildAndRevisionMismatch, buildDesignTimeFacades, inclusionContracts, seedLoadErrorTreatment, contractLoadErrorTreatment, seedTypePreferencesUnsplit, forceZeroVersionSeeds, producePdb, partialFacadeAssemblyPath); }