protected static void AddCustomStep(Pipeline pipeline, string arg) { int pos = arg.IndexOf(":"); if (pos == -1) { pipeline.AppendStep(ResolveStep(arg)); return; } string [] parts = arg.Split(':'); if (parts.Length != 2) { Usage("Step is specified as TYPE:STEP"); } if (parts [0].IndexOf(",") > -1) { pipeline.AddStepBefore(FindStep(pipeline, parts [1]), ResolveStep(parts [0])); } else if (parts [1].IndexOf(",") > -1) { pipeline.AddStepAfter(FindStep(pipeline, parts [0]), ResolveStep(parts [1])); } else { Usage("No comma separator in TYPE or STEP"); } }
protected static bool AddCustomStep(Pipeline pipeline, string arg) { int pos = arg.IndexOf(":"); if (pos == -1) { var step = ResolveStep(arg); if (step == null) { return(false); } pipeline.AppendStep(step); return(true); } string[] parts = arg.Split(':'); if (parts.Length != 2) { Console.WriteLine($"Invalid value '{arg}' specified for '--custom-step' option"); return(false); } if (!parts[0].StartsWith("-") && !parts [0].StartsWith("+")) { Console.WriteLine($"Expected '+' or '-' to control new step insertion"); return(false); } bool before = parts [0][0] == '-'; string name = parts [0].Substring(1); IStep target = FindStep(pipeline, name); if (target == null) { Console.WriteLine($"Pipeline step '{name}' could not be found"); return(false); } IStep newStep = ResolveStep(parts [1]); if (newStep == null) { return(false); } if (before) { pipeline.AddStepBefore(target, newStep); } else { pipeline.AddStepAfter(target, newStep); } return(true); }
void Run() { Pipeline p = GetStandardPipeline(); LinkContext context = GetDefaultContext(p); I18nAssemblies assemblies = I18nAssemblies.All; var custom_steps = new List <string> (); bool resolver = false; while (HaveMoreTokens()) { string token = GetParam(); if (token.Length < 2) { Usage("Option is too short"); } if (!(token [0] == '-' || token [1] == '/')) { Usage("Expecting an option, got instead: " + token); } if (token [0] == '-' && token [1] == '-') { if (token.Length < 3) { Usage("Option is too short"); } switch (token [2]) { case 'v': Version(); break; case 'a': About(); break; default: Usage(null); break; } } switch (token [1]) { case 'd': { DirectoryInfo info = new DirectoryInfo(GetParam()); context.Resolver.AddSearchDirectory(info.FullName); break; } case 'o': context.OutputDirectory = GetParam(); break; case 'c': context.CoreAction = ParseAssemblyAction(GetParam()); break; case 'p': AssemblyAction action = ParseAssemblyAction(GetParam()); context.Actions [GetParam()] = action; break; case 's': custom_steps.Add(GetParam()); break; case 't': context.KeepTypeForwarderOnlyAssemblies = true; break; case 'x': foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromXmlStep(new XPathDocument(file))); } resolver = true; break; case 'r': case 'a': var rootVisibility = (token[1] == 'r') ? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily : ResolveFromAssemblyStep.RootVisibility.Any; foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromAssemblyStep(file, rootVisibility)); } resolver = true; break; case 'i': foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromXApiStep(new XPathDocument(file))); } resolver = true; break; case 'l': assemblies = ParseI18n(GetParam()); break; case 'm': context.SetParameter(GetParam(), GetParam()); break; case 'b': context.LinkSymbols = bool.Parse(GetParam()); break; case 'g': if (!bool.Parse(GetParam())) { p.RemoveStep(typeof(RegenerateGuidStep)); } break; case 'v': context.KeepMembersForDebuggerAttributes = bool.Parse(GetParam()); break; default: Usage("Unknown option: `" + token [1] + "'"); break; } } if (!resolver) { Usage("No resolver was created (use -x, -a or -i)"); } foreach (string custom_step in custom_steps) { AddCustomStep(p, custom_step); } p.AddStepAfter(typeof(LoadReferencesStep), new LoadI18nAssemblies(assemblies)); p.Process(context); }
public void Run(ILogger customLogger = null) { Pipeline p = GetStandardPipeline(); using (LinkContext context = GetDefaultContext(p)) { if (customLogger != null) { context.Logger = customLogger; } I18nAssemblies assemblies = I18nAssemblies.All; var custom_steps = new List <string> (); var excluded_features = new HashSet <string> (StringComparer.Ordinal); var disabled_optimizations = new HashSet <string> (StringComparer.Ordinal); bool dumpDependencies = false; bool ignoreDescriptors = false; bool removeCAS = true; bool resolver = false; while (HaveMoreTokens()) { string token = GetParam(); if (token.Length < 2) { Usage("Option is too short"); } if (!(token [0] == '-' || token [1] == '/')) { Usage("Expecting an option, got instead: " + token); } if (token [0] == '-' && token [1] == '-') { if (token.Length < 3) { Usage("Option is too short"); } switch (token) { case "--skip-unresolved": bool ignoreUnresolved = bool.Parse(GetParam()); context.IgnoreUnresolved = ignoreUnresolved; context.Resolver.IgnoreUnresolved = ignoreUnresolved; continue; case "--verbose": context.LogMessages = true; continue; case "--dependencies-file": context.Tracer.DependenciesFileName = GetParam(); continue; case "--dump-dependencies": dumpDependencies = true; continue; case "--reduced-tracing": context.EnableReducedTracing = bool.Parse(GetParam()); continue; case "--used-attrs-only": context.KeepUsedAttributeTypesOnly = bool.Parse(GetParam()); continue; case "--strip-security": removeCAS = bool.Parse(GetParam()); continue; case "--strip-resources": context.StripResources = bool.Parse(GetParam()); continue; case "--exclude-feature": var name = GetParam(); foreach (var feature in name.Split(',')) { if (!excluded_features.Contains(feature)) { excluded_features.Add(feature); } } continue; case "--custom-step": custom_steps.Add(GetParam()); continue; case "--keep-facades": context.KeepTypeForwarderOnlyAssemblies = bool.Parse(GetParam()); continue; case "--ignore-descriptors": ignoreDescriptors = bool.Parse(GetParam()); continue; case "--disable-opt": var opt = GetParam().ToLower(); if (!disabled_optimizations.Contains(opt)) { disabled_optimizations.Add(opt); } continue; } switch (token [2]) { case 'v': Version(); break; case 'a': About(); break; default: Usage(null); break; } } switch (token [1]) { case 'd': DirectoryInfo info = new DirectoryInfo(GetParam()); context.Resolver.AddSearchDirectory(info.FullName); break; case 'o': context.OutputDirectory = GetParam(); break; case 'c': context.CoreAction = ParseAssemblyAction(GetParam()); break; case 'u': context.UserAction = ParseAssemblyAction(GetParam()); break; case 'p': AssemblyAction action = ParseAssemblyAction(GetParam()); context.Actions [GetParam()] = action; break; case 't': context.KeepTypeForwarderOnlyAssemblies = true; break; case 'x': foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromXmlStep(new XPathDocument(file))); } resolver = true; break; case 'r': case 'a': var rootVisibility = (token [1] == 'r') ? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily : ResolveFromAssemblyStep.RootVisibility.Any; foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromAssemblyStep(file, rootVisibility)); } resolver = true; break; case 'i': foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromXApiStep(new XPathDocument(file))); } resolver = true; break; case 'l': assemblies = ParseI18n(GetParam()); break; case 'm': context.SetParameter(GetParam(), GetParam()); break; case 'b': context.LinkSymbols = bool.Parse(GetParam()); break; case 'g': if (!bool.Parse(GetParam())) { p.RemoveStep(typeof(RegenerateGuidStep)); } break; case 'z': ignoreDescriptors = !bool.Parse(GetParam()); break; case 'v': context.KeepMembersForDebugger = bool.Parse(GetParam()); break; default: Usage("Unknown option: `" + token [1] + "'"); break; } } if (!resolver) { Usage("No resolver was created (use -x, -a or -i)"); } if (ignoreDescriptors) { p.RemoveStep(typeof(BlacklistStep)); } if (dumpDependencies) { context.Tracer.Start(); } foreach (string custom_step in custom_steps) { AddCustomStep(p, custom_step); } p.AddStepAfter(typeof(LoadReferencesStep), new LoadI18nAssemblies(assemblies)); if (_needAddBypassNGenStep) { p.AddStepAfter(typeof(SweepStep), new AddBypassNGenStep()); } if (assemblies != I18nAssemblies.None) { p.AddStepAfter(typeof(PreserveDependencyLookupStep), new PreserveCalendarsStep(assemblies)); } if (removeCAS) { p.AddStepBefore(typeof(MarkStep), new RemoveSecurityStep()); } if (excluded_features.Count > 0) { p.AddStepBefore(typeof(MarkStep), new RemoveFeaturesStep() { FeatureCOM = excluded_features.Contains("com"), FeatureETW = excluded_features.Contains("etw"), FeatureGlobalization = excluded_features.Contains("globalization") }); var excluded = new string [excluded_features.Count]; excluded_features.CopyTo(excluded); context.ExcludedFeatures = excluded; } if (disabled_optimizations.Count > 0) { foreach (var item in disabled_optimizations) { switch (item) { case "beforefieldinit": context.DisabledOptimizations |= CodeOptimizations.BeforeFieldInit; break; case "overrideremoval": context.DisabledOptimizations |= CodeOptimizations.OverrideRemoval; break; } } } PreProcessPipeline(p); try { p.Process(context); } finally { if (dumpDependencies) { context.Tracer.Finish(); } } } }
public bool Run(ILogger customLogger = null) { Pipeline p = GetStandardPipeline(); using (LinkContext context = GetDefaultContext(p)) { if (customLogger != null) { context.Logger = customLogger; } #if !FEATURE_ILLINK I18nAssemblies assemblies = I18nAssemblies.All; #endif var custom_steps = new List <string> (); var excluded_features = new HashSet <string> (StringComparer.Ordinal); var disabled_optimizations = new HashSet <string> (StringComparer.Ordinal); var enabled_optimizations = new HashSet <string> (StringComparer.Ordinal); bool dumpDependencies = false; string dependenciesFileName = null; bool ignoreDescriptors = false; bool removeCAS = true; bool new_mvid_used = false; bool deterministic_used = false; bool resolver = false; while (arguments.Count > 0) { string token = arguments.Dequeue(); if (token.Length < 2) { ErrorUnrecognizedOption(token); return(false); } // // Handling of --value like options // if (token [0] == '-' && token [1] == '-') { switch (token) { case "--skip-unresolved": if (!GetBoolParam(token, l => context.IgnoreUnresolved = context.Resolver.IgnoreUnresolved = l)) { return(false); } continue; case "--verbose": context.LogMessages = true; continue; case "--dependencies-file": if (!GetStringParam(token, l => dependenciesFileName = l)) { return(false); } continue; case "--dump-dependencies": dumpDependencies = true; continue; case "--reduced-tracing": if (!GetBoolParam(token, l => context.EnableReducedTracing = l)) { return(false); } continue; case "--used-attrs-only": if (!GetBoolParam(token, l => context.KeepUsedAttributeTypesOnly = l)) { return(false); } continue; case "--strip-security": if (!GetBoolParam(token, l => removeCAS = l)) { return(false); } continue; case "--strip-resources": if (!GetBoolParam(token, l => context.StripResources = l)) { return(false); } continue; case "--substitutions": if (arguments.Count < 1) { ErrorMissingArgument(token); return(false); } if (!GetStringParam(token, l => context.AddSubstitutionFile(l))) { return(false); } continue; case "--exclude-feature": if (arguments.Count < 1) { ErrorMissingArgument(token); return(false); } if (!GetStringParam(token, l => { foreach (var feature in l.Split(',')) { if (!excluded_features.Contains(feature)) { excluded_features.Add(feature); } } })) { return(false); } continue; case "--explicit-reflection": if (!GetBoolParam(token, l => context.AddReflectionAnnotations = l)) { return(false); } continue; case "--custom-step": if (!GetStringParam(token, l => custom_steps.Add(l))) { return(false); } continue; case "--keep-facades": if (!GetBoolParam(token, l => context.KeepTypeForwarderOnlyAssemblies = l)) { return(false); } continue; case "--keep-dep-attributes": if (!GetBoolParam(token, l => context.KeepDependencyAttributes = l)) { return(false); } continue; case "--ignore-descriptors": if (!GetBoolParam(token, l => ignoreDescriptors = l)) { return(false); } continue; case "--disable-opt": if (!GetStringParam(token, l => { var opt = l.ToLowerInvariant(); if (!disabled_optimizations.Contains(opt)) { disabled_optimizations.Add(opt); } })) { return(false); } continue; case "--enable-opt": if (!GetStringParam(token, l => { var opt = l.ToLowerInvariant(); if (!enabled_optimizations.Contains(opt)) { enabled_optimizations.Add(opt); } })) { return(false); } continue; case "--new-mvid": // // This is not same as --deterministic which calculates MVID // from stable assembly content. This option creates a new random // mvid or uses mvid of the source assembly. // if (!GetBoolParam(token, l => { if (!l) { p.RemoveStep(typeof(RegenerateGuidStep)); } })) { return(false); } new_mvid_used = true; continue; case "--deterministic": if (!GetBoolParam(token, l => context.DeterministicOutput = l)) { return(false); } deterministic_used = true; continue; case "--output-assemblylist": if (!GetStringParam(token, l => context.AssemblyListFile = l)) { return(false); } continue; case "--version": Version(); return(true); case "--about": About(); return(true); } } if (token [0] == '-' || token [1] == '/') { switch (token.Substring(1)) { case "d": if (!GetStringParam(token, l => { DirectoryInfo info = new DirectoryInfo(l); context.Resolver.AddSearchDirectory(info.FullName); })) { return(false); } continue; case "o": case "out": if (!GetStringParam(token, l => context.OutputDirectory = l)) { return(false); } continue; case "c": if (!GetStringParam(token, l => context.CoreAction = ParseAssemblyAction(l))) { return(false); } continue; case "u": if (!GetStringParam(token, l => context.UserAction = ParseAssemblyAction(l))) { return(false); } continue; case "p": if (arguments.Count < 2) { ErrorMissingArgument(token); return(false); } AssemblyAction action = ParseAssemblyAction(arguments.Dequeue()); context.Actions [arguments.Dequeue()] = action; continue; case "t": context.KeepTypeForwarderOnlyAssemblies = true; continue; case "x": if (!GetStringParam(token, l => { foreach (string file in GetFiles(l)) { p.PrependStep(new ResolveFromXmlStep(new XPathDocument(file))); } })) { return(false); } resolver = true; continue; case "r": case "a": if (!GetStringParam(token, l => { var rootVisibility = (token [1] == 'r') ? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily : ResolveFromAssemblyStep.RootVisibility.Any; foreach (string file in GetFiles(l)) { p.PrependStep(new ResolveFromAssemblyStep(file, rootVisibility)); } })) { return(false); } resolver = true; continue; #if !FEATURE_ILLINK case "i": if (!GetStringParam(token, l => { foreach (string file in GetFiles(l)) { p.PrependStep(new ResolveFromXApiStep(new XPathDocument(file))); } })) { return(false); } resolver = true; continue; case "l": if (!GetStringParam(token, l => assemblies = ParseI18n(l))) { return(false); } continue; #endif case "m": if (arguments.Count < 2) { ErrorMissingArgument(token); return(false); } context.SetParameter(arguments.Dequeue(), arguments.Dequeue()); continue; case "b": if (!GetBoolParam(token, l => context.LinkSymbols = l)) { return(false); } continue; case "g": if (!GetBoolParam(token, l => context.DeterministicOutput = !l)) { return(false); } continue; case "z": if (!GetBoolParam(token, l => ignoreDescriptors = !l)) { return(false); } continue; case "v": if (!GetBoolParam(token, l => context.KeepMembersForDebugger = l)) { return(false); } continue; case "?": case "help": Usage(); return(true); case "reference": if (!GetStringParam(token, l => context.Resolver.AddReferenceAssembly(l))) { return(false); } continue; } } ErrorUnrecognizedOption(token); return(false); } if (!resolver) { Console.WriteLine($"No files to link were specified. Use one of '{resolvers}' options"); return(false); } if (new_mvid_used && deterministic_used) { Console.WriteLine($"Options '--new-mvid' and '--deterministic' cannot be used at the same time"); return(false); } if (dumpDependencies) { context.Tracer.AddRecorder(new XmlDependencyRecorder(context, dependenciesFileName)); } if (disabled_optimizations.Count > 0) { foreach (var item in disabled_optimizations) { switch (item) { case "beforefieldinit": context.DisabledOptimizations |= CodeOptimizations.BeforeFieldInit; break; case "overrideremoval": context.DisabledOptimizations |= CodeOptimizations.OverrideRemoval; break; case "unreachablebodies": context.DisabledOptimizations |= CodeOptimizations.UnreachableBodies; break; case "unusedinterfaces": context.DisabledOptimizations |= CodeOptimizations.UnusedInterfaces; break; case "ipconstprop": context.DisabledOptimizations |= CodeOptimizations.IPConstantPropagation; break; } } } if (enabled_optimizations.Count > 0) { foreach (var item in enabled_optimizations) { switch (item) { case "unreachablebodies": context.DisabledOptimizations &= ~CodeOptimizations.UnreachableBodies; break; case "clearinitlocals": context.DisabledOptimizations &= ~CodeOptimizations.ClearInitLocals; break; case "ipconstprop": context.DisabledOptimizations &= ~CodeOptimizations.IPConstantPropagation; break; } } } // // Modify the default pipeline // if (ignoreDescriptors) { p.RemoveStep(typeof(BlacklistStep)); } if (context.DeterministicOutput) { p.RemoveStep(typeof(RegenerateGuidStep)); } if (context.AddReflectionAnnotations) { p.AddStepAfter(typeof(MarkStep), new ReflectionBlockedStep()); } #if !FEATURE_ILLINK p.AddStepAfter(typeof(LoadReferencesStep), new LoadI18nAssemblies(assemblies)); if (assemblies != I18nAssemblies.None) { p.AddStepAfter(typeof(PreserveDependencyLookupStep), new PreserveCalendarsStep(assemblies)); } #endif if (_needAddBypassNGenStep) { p.AddStepAfter(typeof(SweepStep), new AddBypassNGenStep()); } p.AddStepBefore(typeof(MarkStep), new BodySubstituterStep()); if (removeCAS) { p.AddStepBefore(typeof(MarkStep), new RemoveSecurityStep()); } if (excluded_features.Count > 0) { p.AddStepBefore(typeof(MarkStep), new RemoveFeaturesStep() { FeatureCOM = excluded_features.Contains("com"), FeatureETW = excluded_features.Contains("etw"), FeatureSRE = excluded_features.Contains("sre"), FeatureGlobalization = excluded_features.Contains("globalization") }); var excluded = new string [excluded_features.Count]; excluded_features.CopyTo(excluded); context.ExcludedFeatures = excluded; } p.AddStepBefore(typeof(MarkStep), new RemoveUnreachableBlocksStep()); if (context.IsOptimizationEnabled(CodeOptimizations.ClearInitLocals)) { p.AddStepBefore(typeof(OutputStep), new ClearInitLocalsStep()); } // // Pipeline setup with all steps enabled // // LoadReferencesStep // BlacklistStep [optional] // PreserveDependencyLookupStep // TypeMapStep // BodySubstituterStep [optional] // RemoveSecurityStep [optional] // RemoveFeaturesStep [optional] // RemoveUnreachableBlocksStep [optional] // MarkStep // ReflectionBlockedStep [optional] // SweepStep // AddBypassNGenStep [optional] // CodeRewriterStep // CleanStep // RegenerateGuidStep [optional] // ClearInitLocalsStep [optional] // OutputStep // foreach (string custom_step in custom_steps) { if (!AddCustomStep(p, custom_step)) { return(false); } } PreProcessPipeline(p); try { p.Process(context); } finally { context.Tracer.Finish(); } return(true); } }
// Perform setup of the LinkContext and parse the arguments. // Return values: // 0 => successfully set up context with all arguments // 1 => argument processing stopped early without errors // -1 => error setting up context protected int SetupContext(ILogger customLogger = null) { Pipeline p = GetStandardPipeline(); context = GetDefaultContext(p); if (customLogger != null) { context.Logger = customLogger; } #if !FEATURE_ILLINK I18nAssemblies assemblies = I18nAssemblies.All; var excluded_features = new HashSet <string> (StringComparer.Ordinal); var resolve_from_xapi_steps = new Stack <string> (); #endif var resolve_from_assembly_steps = new Stack <(string, ResolveFromAssemblyStep.RootVisibility)> (); var resolve_from_xml_steps = new Stack <string> (); var body_substituter_steps = new Stack <string> (); var custom_steps = new Stack <string> (); var set_optimizations = new List <(CodeOptimizations, string, bool)> (); bool dumpDependencies = false; string dependenciesFileName = null; bool removeCAS = true; bool new_mvid_used = false; bool deterministic_used = false; bool resolver = false; while (arguments.Count > 0) { string token = arguments.Dequeue(); if (token.Length < 2) { ErrorUnrecognizedOption(token); return(-1); } // // Handling of --value like options // if (token[0] == '-' && token[1] == '-') { switch (token) { case "--skip-unresolved": if (!GetBoolParam(token, l => context.IgnoreUnresolved = context.Resolver.IgnoreUnresolved = l)) { return(-1); } continue; case "--verbose": context.LogMessages = true; continue; case "--dependencies-file": if (!GetStringParam(token, l => dependenciesFileName = l)) { return(-1); } continue; case "--dump-dependencies": dumpDependencies = true; continue; case "--reduced-tracing": if (!GetBoolParam(token, l => context.EnableReducedTracing = l)) { return(-1); } continue; case "--used-attrs-only": if (!GetBoolParam(token, l => context.KeepUsedAttributeTypesOnly = l)) { return(-1); } continue; case "--strip-security": if (!GetBoolParam(token, l => removeCAS = l)) { return(-1); } continue; case "--strip-descriptors": if (!GetBoolParam(token, l => context.StripDescriptors = l)) { return(-1); } continue; case "--strip-substitutions": if (!GetBoolParam(token, l => context.StripSubstitutions = l)) { return(-1); } continue; case "--substitutions": if (arguments.Count < 1) { ErrorMissingArgument(token); return(-1); } if (!GetStringParam(token, l => body_substituter_steps.Push(l))) { return(-1); } continue; #if !FEATURE_ILLINK case "--exclude-feature": if (arguments.Count < 1) { ErrorMissingArgument(token); return(-1); } if (!GetStringParam(token, l => { foreach (var feature in l.Split(',')) { if (!excluded_features.Contains(feature)) { excluded_features.Add(feature); } } })) { return(-1); } continue; #endif case "--explicit-reflection": if (!GetBoolParam(token, l => context.AddReflectionAnnotations = l)) { return(-1); } continue; case "--custom-step": if (!GetStringParam(token, l => custom_steps.Push(l))) { return(-1); } continue; case "--custom-data": if (arguments.Count < 1) { ErrorMissingArgument(token); return(-1); } var arg = arguments.Dequeue(); string[] values = arg.Split('='); if (values?.Length != 2) { Console.WriteLine($"Value used with '--custom-data' has to be in the KEY=VALUE format"); return(-1); } context.SetCustomData(values[0], values[1]); continue; case "--keep-facades": if (!GetBoolParam(token, l => context.KeepTypeForwarderOnlyAssemblies = l)) { return(-1); } continue; case "--keep-dep-attributes": if (!GetBoolParam(token, l => context.KeepDependencyAttributes = l)) { return(-1); } continue; case "--ignore-descriptors": if (!GetBoolParam(token, l => context.IgnoreDescriptors = l)) { return(-1); } continue; case "--ignore-substitutions": if (!GetBoolParam(token, l => context.IgnoreSubstitutions = l)) { return(-1); } continue; case "--disable-opt": { string optName = null; if (!GetStringParam(token, l => optName = l)) { return(-1); } if (!GetOptimizationName(optName, out var opt)) { return(-1); } string assemblyName = GetNextStringValue(); set_optimizations.Add((opt, assemblyName, false)); continue; } case "--enable-opt": { string optName = null; if (!GetStringParam(token, l => optName = l)) { return(-1); } if (!GetOptimizationName(optName, out var opt)) { return(-1); } string assemblyName = GetNextStringValue(); set_optimizations.Add((opt, assemblyName, true)); continue; } case "--feature": { string featureName = null; if (!GetStringParam(token, l => featureName = l)) { return(-1); } if (!GetBoolParam(token, value => { context.SetFeatureValue(featureName, value); })) { return(-1); } continue; } case "--new-mvid": // // This is not same as --deterministic which calculates MVID // from stable assembly content. This option creates a new random // mvid or uses mvid of the source assembly. // if (!GetBoolParam(token, l => { if (!l) { p.RemoveStep(typeof(RegenerateGuidStep)); } })) { return(-1); } new_mvid_used = true; continue; case "--deterministic": if (!GetBoolParam(token, l => context.DeterministicOutput = l)) { return(-1); } deterministic_used = true; continue; case "--output-assemblylist": if (!GetStringParam(token, l => context.AssemblyListFile = l)) { return(-1); } continue; case "--output-pinvokes": if (!GetStringParam(token, l => context.PInvokesListFile = l)) { return(-1); } continue; case "--attribute-defs": if (arguments.Count < 1) { ErrorMissingArgument(token); return(-1); } if (!GetStringParam(token, l => context.AddAttributeDefinitionFile(l))) { return(-1); } continue; case "--version": Version(); return(1); case "--about": About(); return(1); } } if (token[0] == '-' || token[1] == '/') { switch (token.Substring(1)) { case "d": if (!GetStringParam(token, l => { DirectoryInfo info = new DirectoryInfo(l); context.Resolver.AddSearchDirectory(info.FullName); })) { return(-1); } continue; case "o": case "out": if (!GetStringParam(token, l => context.OutputDirectory = l)) { return(-1); } continue; case "c": if (!GetStringParam(token, l => context.CoreAction = ParseAssemblyAction(l))) { return(-1); } continue; case "u": if (!GetStringParam(token, l => context.UserAction = ParseAssemblyAction(l))) { return(-1); } continue; case "p": if (arguments.Count < 2) { ErrorMissingArgument(token); return(-1); } AssemblyAction action = ParseAssemblyAction(arguments.Dequeue()); context.Actions[arguments.Dequeue()] = action; continue; case "t": context.KeepTypeForwarderOnlyAssemblies = true; continue; case "x": if (!GetStringParam(token, l => { foreach (string file in GetFiles(l)) { resolve_from_xml_steps.Push(file); } })) { return(-1); } resolver = true; continue; case "r": case "a": if (!GetStringParam(token, l => { var rootVisibility = (token[1] == 'r') ? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily : ResolveFromAssemblyStep.RootVisibility.Any; foreach (string file in GetFiles(l)) { resolve_from_assembly_steps.Push((file, rootVisibility)); } })) { return(-1); } resolver = true; continue; #if !FEATURE_ILLINK case "i": if (!GetStringParam(token, l => { foreach (string file in GetFiles(l)) { resolve_from_xapi_steps.Push(file); } })) { return(-1); } resolver = true; continue; case "l": if (!GetStringParam(token, l => assemblies = ParseI18n(l))) { return(-1); } continue; #endif case "b": if (!GetBoolParam(token, l => context.LinkSymbols = l)) { return(-1); } continue; case "g": if (!GetBoolParam(token, l => context.DeterministicOutput = !l)) { return(-1); } continue; case "z": if (!GetBoolParam(token, l => context.IgnoreDescriptors = !l)) { return(-1); } continue; case "v": if (!GetBoolParam(token, l => context.KeepMembersForDebugger = l)) { return(-1); } continue; case "?": case "help": Usage(); return(1); case "reference": if (!GetStringParam(token, l => context.Resolver.AddReferenceAssembly(l))) { return(-1); } continue; } } ErrorUnrecognizedOption(token); return(-1); } if (!resolver) { Console.WriteLine($"No files to link were specified. Use one of '{resolvers}' options"); return(-1); } if (new_mvid_used && deterministic_used) { Console.WriteLine($"Options '--new-mvid' and '--deterministic' cannot be used at the same time"); return(-1); } if (dumpDependencies) { AddXmlDependencyRecorder(context, dependenciesFileName); } if (set_optimizations.Count > 0) { foreach (var(opt, assemblyName, enable) in set_optimizations) { if (enable) { context.Optimizations.Enable(opt, assemblyName); } else { context.Optimizations.Disable(opt, assemblyName); } } } // // Modify the default pipeline // #if !FEATURE_ILLINK foreach (var file in resolve_from_xapi_steps) { p.PrependStep(new ResolveFromXApiStep(new XPathDocument(file))); } #endif foreach (var file in resolve_from_xml_steps) { AddResolveFromXmlStep(p, file); } foreach (var(file, rootVisibility) in resolve_from_assembly_steps) { p.PrependStep(new ResolveFromAssemblyStep(file, rootVisibility)); } foreach (var file in body_substituter_steps) { AddBodySubstituterStep(p, file); } if (context.DeterministicOutput) { p.RemoveStep(typeof(RegenerateGuidStep)); } if (context.AddReflectionAnnotations) { p.AddStepAfter(typeof(MarkStep), new ReflectionBlockedStep()); } #if !FEATURE_ILLINK p.AddStepAfter(typeof(LoadReferencesStep), new LoadI18nAssemblies(assemblies)); if (assemblies != I18nAssemblies.None) { p.AddStepAfter(typeof(PreserveDependencyLookupStep), new PreserveCalendarsStep(assemblies)); } #endif if (_needAddBypassNGenStep) { p.AddStepAfter(typeof(SweepStep), new AddBypassNGenStep()); } if (removeCAS) { p.AddStepBefore(typeof(MarkStep), new RemoveSecurityStep()); } #if !FEATURE_ILLINK if (excluded_features.Count > 0) { p.AddStepBefore(typeof(MarkStep), new RemoveFeaturesStep() { FeatureCOM = excluded_features.Contains("com"), FeatureETW = excluded_features.Contains("etw"), FeatureSRE = excluded_features.Contains("sre"), FeatureGlobalization = excluded_features.Contains("globalization") }); var excluded = new string[excluded_features.Count]; excluded_features.CopyTo(excluded); context.ExcludedFeatures = excluded; } #endif p.AddStepBefore(typeof(MarkStep), new RemoveUnreachableBlocksStep()); p.AddStepBefore(typeof(OutputStep), new ClearInitLocalsStep()); p.AddStepBefore(typeof(OutputStep), new SealerStep()); // // Pipeline setup with all steps enabled // // ResolveFromAssemblyStep [optional, possibly many] // ResolveFromXmlStep [optional, possibly many] // [mono only] ResolveFromXApiStep [optional, possibly many] // LoadReferencesStep // [mono only] LoadI18nAssemblies // BlacklistStep // dynamically adds steps: // ResolveFromXmlStep [optional, possibly many] // BodySubstituterStep [optional, possibly many] // PreserveDependencyLookupStep // [mono only] PreselveCalendarsStep [optional] // TypeMapStep // BodySubstituterStep [optional] // RemoveSecurityStep [optional] // [mono only] RemoveFeaturesStep [optional] // RemoveUnreachableBlocksStep [optional] // MarkStep // ReflectionBlockedStep [optional] // SweepStep // AddBypassNGenStep [optional] // CodeRewriterStep // CleanStep // RegenerateGuidStep [optional] // ClearInitLocalsStep // SealerStep // OutputStep // foreach (string custom_step in custom_steps) { if (!AddCustomStep(p, custom_step)) { return(-1); } } return(0); }
public void Run(ILogger customLogger = null) { Pipeline p = GetStandardPipeline(); using (LinkContext context = GetDefaultContext(p)) { if (customLogger != null) { context.Logger = customLogger; } I18nAssemblies assemblies = I18nAssemblies.All; var custom_steps = new List <string> (); bool dumpDependencies = false; bool resolver = false; while (HaveMoreTokens()) { string token = GetParam(); if (token.Length < 2) { Usage("Option is too short"); } if (!(token [0] == '-' || token [1] == '/')) { Usage("Expecting an option, got instead: " + token); } if (token [0] == '-' && token [1] == '-') { if (token.Length < 3) { Usage("Option is too short"); } if (token == "--skip-unresolved") { bool ignoreUnresolved = bool.Parse(GetParam()); context.IgnoreUnresolved = ignoreUnresolved; context.Resolver.IgnoreUnresolved = ignoreUnresolved; continue; } if (token == "--verbose") { context.LogMessages = true; continue; } if (token == "--dependencies-file") { context.Tracer.DependenciesFileName = GetParam(); continue; } if (token == "--dump-dependencies") { dumpDependencies = true; continue; } if (token == "--reduced-tracing") { context.EnableReducedTracing = bool.Parse(GetParam()); continue; } if (token == "--used-attrs-only") { context.KeepUsedAttributeTypesOnly = bool.Parse(GetParam()); continue; } if (token == "--strip-security") { if (bool.Parse(GetParam())) { p.AddStepBefore(typeof(MarkStep), new RemoveSecurityStep()); } continue; } if (token == "--strip-resources") { context.StripResources = bool.Parse(GetParam()); continue; } switch (token [2]) { case 'v': Version(); break; case 'a': About(); break; default: Usage(null); break; } } switch (token [1]) { case 'd': { DirectoryInfo info = new DirectoryInfo(GetParam()); context.Resolver.AddSearchDirectory(info.FullName); break; } case 'o': context.OutputDirectory = GetParam(); break; case 'c': context.CoreAction = ParseAssemblyAction(GetParam()); break; case 'u': context.UserAction = ParseAssemblyAction(GetParam()); break; case 'p': AssemblyAction action = ParseAssemblyAction(GetParam()); context.Actions [GetParam()] = action; break; case 's': custom_steps.Add(GetParam()); break; case 't': context.KeepTypeForwarderOnlyAssemblies = true; break; case 'x': foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromXmlStep(new XPathDocument(file))); } resolver = true; break; case 'r': case 'a': var rootVisibility = (token [1] == 'r') ? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily : ResolveFromAssemblyStep.RootVisibility.Any; foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromAssemblyStep(file, rootVisibility)); } resolver = true; break; case 'i': foreach (string file in GetFiles(GetParam())) { p.PrependStep(new ResolveFromXApiStep(new XPathDocument(file))); } resolver = true; break; case 'l': assemblies = ParseI18n(GetParam()); break; case 'm': context.SetParameter(GetParam(), GetParam()); break; case 'b': context.LinkSymbols = bool.Parse(GetParam()); break; case 'g': if (!bool.Parse(GetParam())) { p.RemoveStep(typeof(RegenerateGuidStep)); } break; case 'z': if (!bool.Parse(GetParam())) { p.RemoveStep(typeof(BlacklistStep)); } break; case 'v': context.KeepMembersForDebuggerAttributes = bool.Parse(GetParam()); break; default: Usage("Unknown option: `" + token [1] + "'"); break; } } if (!resolver) { Usage("No resolver was created (use -x, -a or -i)"); } if (dumpDependencies) { context.Tracer.Start(); } foreach (string custom_step in custom_steps) { AddCustomStep(p, custom_step); } p.AddStepAfter(typeof(LoadReferencesStep), new LoadI18nAssemblies(assemblies)); if (_needAddBypassNGenStep) { p.AddStepAfter(typeof(SweepStep), new AddBypassNGenStep()); } p.Process(context); } }
static void AddCustomStep (Pipeline pipeline, string arg) { int pos = arg.IndexOf (":"); if (pos == -1) { pipeline.AppendStep (ResolveStep (arg)); return; } string [] parts = arg.Split (':'); if (parts.Length != 2) Usage ("Step is specified as TYPE:STEP"); if (parts [0].IndexOf (",") > -1) pipeline.AddStepBefore (FindStep (pipeline, parts [1]), ResolveStep (parts [0])); else if (parts [1].IndexOf (",") > -1) pipeline.AddStepAfter (FindStep (pipeline, parts [0]), ResolveStep (parts [1])); else Usage ("No comma separator in TYPE or STEP"); }