public void ParseRegistrar(string v) { var split = v.Split('='); var name = split [0]; var value = split.Length > 1 ? split [1] : string.Empty; switch (name) { case "static": Registrar = RegistrarMode.Static; break; case "dynamic": Registrar = RegistrarMode.Dynamic; break; case "default": Registrar = RegistrarMode.Default; break; #if !MTOUCH case "partial": case "partial-static": Registrar = RegistrarMode.PartialStatic; break; #endif default: throw ErrorHelper.CreateError(20, Errors.MX0020, "--registrar", "static, dynamic or default"); } switch (value) { case "trace": RegistrarOptions = RegistrarOptions.Trace; break; case "default": case "": RegistrarOptions = RegistrarOptions.Default; break; default: throw ErrorHelper.CreateError(20, Errors.MX0020, "--registrar", "static, dynamic or default"); } }
static void Main2(string [] args) { var os = new OptionSet () { { "h|?|help", "Displays the help", v => show_help = true }, { "version", "Output version information and exit.", v => show_version = true }, { "f|force", "Forces the recompilation of code, regardless of timestamps", v=> Force = true }, { "cache=", "Specify the directory where temporary build files will be cached", v => Cache.Location = v }, { "a|assembly=", "Add an assembly to be processed", v => references.Add (v) }, { "r|resource=", "Add a resource to be included", v => resources.Add (v) }, { "o|output=", "Specify the output path", v => output_dir = v }, { "n|name=", "Specify the application name", v => app_name = v }, { "d|debug", "Build a debug bundle", v => App.EnableDebug = true }, { "s|sgen:", "Use the SGen Garbage Collector", v => { if (!ParseBool (v, "sgen")) ErrorHelper.Warning (43, "The Boehm garbage collector is not supported. The SGen garbage collector has been selected instead."); }, true // do not show the option anymore }, { "boehm:", "Enable the Boehm garbage collector", v => { if (ParseBool (v, "boehm")) ErrorHelper.Warning (43, "The Boehm garbage collector is not supported. The SGen garbage collector has been selected instead."); }, true // do not show the option anymore }, { "new-refcount:", "Enable new refcounting logic", v => { if (!ParseBool (v, "new-refcount")) ErrorHelper.Warning (80, "Disabling the new refcount logic is deprecated."); }, true // do not show this option anymore }, { "nolink", "Do not link the assemblies", v => App.LinkMode = LinkMode.None }, { "mapinject", "Inject a fast method map [deprecated]", v => { ErrorHelper.Show (new MonoMacException (16, false, "The option '{0}' has been deprecated.", "--mapinject")); } }, { "minos=", "Minimum supported version of Mac OS X", v => { try { minos = Version.Parse (v); } catch (Exception ex) { ErrorHelper.Error (26, ex, "Could not parse the command line argument '{0}': {1}", "-minos", ex.Message); } } }, { "linksdkonly", "Link only the SDK assemblies", v => App.LinkMode = LinkMode.SDKOnly }, { "linkskip=", "Skip linking of the specified assembly", v => App.LinkSkipped.Add (v) }, { "i18n=", "List of i18n assemblies to copy to the output directory, separated by commas (none,all,cjk,mideast,other,rare,west)", v => App.I18n = LinkerOptions.ParseI18nAssemblies (v) }, { "c|certificate=", "The Code Signing certificate for the application", v => { certificate_name = v; }}, { "p", "Generate a plist for the application", v => { generate_plist = true; }}, { "v|verbose", "Verbose output", v => { verbose++; }}, { "q", "Quiet", v => verbose-- }, { "i|icon=", "Use the specified file as the bundle icon", v => { icon = v; }}, { "xml=", "Provide an extra XML definition file to the linker", v => App.Definitions.Add (v) }, { "time", v => watch_level++ }, { "sdkroot=", "Specify the location of Apple SDKs", v => sdk_root = v }, { "arch=", "Specify the architecture ('i386' or 'x86_64') of the native runtime (default to 'i386')", v => { arch = v; arch_set = true; } }, { "profile=", "(Obsoleted in favor of --target-framework) Specify the .NET profile to use (defaults to '" + Xamarin.Utils.TargetFramework.Default + "')", v => SetTargetFramework (v) }, { "target-framework=", "Specify the .NET target framework to use (defaults to '" + Xamarin.Utils.TargetFramework.Default + "')", v => SetTargetFramework (v) }, { "force-thread-check", "Keep UI thread checks inside (even release) builds", v => { thread_check = true; }}, { "disable-thread-check", "Remove UI thread checks inside (even debug) builds", v => { thread_check = false; }}, { "registrar:", "Specify the registrar to use (dynamic [default], IL or static)", v => { switch (v) { case "static": registrar = RegistrarMode.Static; break; case "dynamic": registrar = RegistrarMode.Dynamic; break; case "il": registrar = RegistrarMode.IL; break; case "default": registrar = RegistrarMode.Default; break; default: throw new MonoMacException (20, true, "The valid options for '{0}' are '{1}'.", "--registrar", "il, dynamic, static or default"); } }, true /* hidden for now */ }, { "sdk=", "Specifies the SDK version to compile against (version, for example \"10.9\")", v => { try { sdk_version = Version.Parse (v); } catch (Exception ex) { ErrorHelper.Error (26, ex, "Could not parse the command line argument '{0}': {1}", "-sdk", ex.Message); } } }, { "no-root-assembly", "Specifies that mmp will not process a root assembly. This is if the app needs to be packaged with a different directory structure than what mmp supports.", v => no_executable = true }, { "embed-mono:", "Specifies whether the app will embed the Mono runtime, or if it will use the system Mono found at runtime (default: true).", v => { embed_mono = ParseBool (v, "embed-mono"); } }, { "link_flags=", "Specifies additional arguments to the native linker.", v => { link_flags = v; } }, { "ignore-native-library=", "Add a native library to be ignored during assembly scanning and packaging", v => ignored_assemblies.Add (v) }, { "native-reference=", "Add a native (static, dynamic, or framework) library to be included in the bundle. Can be specified multiple times.", v => { native_references.Add (v); if (v.EndsWith (".framework", true, CultureInfo.InvariantCulture)) App.Frameworks.Add (v); } }, { "profiling:", "Enable profiling", v => profiling = ParseBool (v, "profiling") }, { "custom_bundle_name=", "Specify a custom name for the MonoBundle folder.", v => custom_bundle_name = v, true }, // Hidden hack for "universal binaries" { "tls-provider=", "Specify the default TLS provider", v => { tls_provider = v; }}, { "http-message-handler=", "Specify the default HTTP Message Handler", v => { http_message_provider = v; }}, }; IList<string> unprocessed; try { unprocessed = os.Parse (args); } catch (MonoMacException) { throw; } catch (Exception e) { throw new MonoMacException (10, true, "Could not parse the command line arguments: {0}", e.Message); } App.RuntimeOptions = RuntimeOptions.Create (http_message_provider, tls_provider); ErrorHelper.Verbosity = verbose; if (watch_level > 0) { watch = new Stopwatch (); watch.Start (); } if (show_help || (args.Length == 0)) { ShowHelp (os); return; } else if (show_version) { Console.Write ("mmp {0}.{1}", Constants.Version, Constants.Revision); Console.WriteLine (); return; } bool force45From40UnifiedSystemFull = false; if (!targetFramework.HasValue) targetFramework = TargetFramework.Default; if (TargetFramework.Identifier == TargetFramework.Xamarin_Mac_2_0.Identifier) { IsUnifiedMobile = true; } else { foreach (var asm in references) { if (asm.EndsWith ("reference/full/Xamarin.Mac.dll")) { IsUnifiedFullSystemFramework = true; force45From40UnifiedSystemFull = targetFramework == TargetFramework.Net_4_0; break; } if (asm.EndsWith ("mono/4.5/Xamarin.Mac.dll")) { IsUnifiedFullXamMacFramework = true; break; } } } if (IsUnifiedFullXamMacFramework) { if (TargetFramework.Identifier != TargetFramework.Net_4_5.Identifier) throw new MonoMacException (1405, true, "useFullXamMacFramework must always target framework .NET 4.5, not '{0}' which is invalid.", userTargetFramework); } if (IsUnifiedFullSystemFramework) { if (force45From40UnifiedSystemFull) { Console.WriteLine ("Xamarin.Mac Unified Full System profile requires .NET 4.5, not .NET 4.0."); FixReferences (x => x.Contains ("lib/mono/4.0"), x => x.Replace("lib/mono/4.0", "lib/mono/4.5")); targetFramework = TargetFramework.Net_4_5; } } if (IsUnifiedFullSystemFramework || IsClassic) { // With newer Mono builds, the system assemblies passed to us by msbuild are // no longer safe to copy into the bundle. They are stripped "fake" BCL // copies. So we redirect to the "real" ones. Thanks TargetFrameworkDirectories :( Regex monoAPIRegex = new Regex("lib/mono/.*-api/", RegexOptions.IgnoreCase); Regex monoAPIFacadesRegex = new Regex("lib/mono/.*-api/Facades/", RegexOptions.IgnoreCase); FixReferences (x => monoAPIRegex.IsMatch (x) && !monoAPIFacadesRegex.IsMatch (x), x => x.Replace(monoAPIRegex.Match(x).Value, "lib/mono/4.5/")); } if (targetFramework == TargetFramework.Empty) throw new MonoMacException (1404, true, "Target framework '{0}' is invalid.", userTargetFramework); // sanity check as this should never happen: we start out by not setting any // Unified/Classic properties, and only IsUnifiedMobile if we are are on the // XM framework. If we are not, we set IsUnifiedFull to true iff we detect // an explicit reference to the full unified Xamarin.Mac assembly; that is // only one of IsUnifiedMobile or IsUnifiedFull should ever be true. IsUnified // is true if one of IsUnifiedMobile or IsUnifiedFull is true; IsClassic is // implied if IsUnified is not true; int IsUnifiedCount = IsUnifiedMobile ? 1 : 0; if (IsUnifiedFullSystemFramework) IsUnifiedCount++; if (IsUnifiedFullXamMacFramework) IsUnifiedCount++; if (IsUnified == IsClassic || (IsUnified && IsUnifiedCount != 1)) throw new Exception ("IsClassic/IsUnified/IsUnifiedMobile/IsUnifiedFullSystemFramework/IsUnifiedFullXamMacFramework logic regression"); if ((IsUnifiedFullSystemFramework || IsUnifiedFullXamMacFramework) && (App.LinkMode != LinkMode.None)) throw new MonoMacException (2007, true, "Xamarin.Mac Unified API against a full .NET framework does not support linking. Pass the -nolink flag."); if (!IsUnifiedMobile && tls_provider != null) throw new MonoMacException (2011, true, "Selecting a TLS Provider is only supported in the Unified Mobile profile"); Log ("Xamarin.Mac {0}{1}", Constants.Version, verbose > 0 ? "." + Constants.Revision : string.Empty); if (verbose > 0) Console.WriteLine ("Selected target framework: {0}; API: {1}", targetFramework, IsClassic ? "Classic" : "Unified"); try { Pack (unprocessed); } finally { if (Cache.IsCacheTemporary) { // If we used a temporary directory we created ourselves for the cache // (in which case it's more a temporary location where we store the // temporary build products than a cache), it will not be used again, // so just delete it. try { Directory.Delete (Cache.Location, true); } catch { // Don't care. } } else { // Write the cache data as the last step, so there is no half-done/incomplete (but yet detected as valid) cache. Cache.ValidateCache (); } } Log ("bundling complete"); }
static void Pack(IList<string> unprocessed) { string fx_dir = null; string root_assembly = null; var native_libs = new Dictionary<string, List<MethodDefinition>> (); HashSet<string> internalSymbols = new HashSet<string> (); if (registrar == RegistrarMode.Default) registrar = RegistrarMode.Dynamic; if (no_executable) { if (unprocessed.Count != 0) { var exceptions = new List<Exception> (); CheckForUnknownCommandLineArguments (exceptions, unprocessed); exceptions.Add (new MonoMacException (50, true, "You cannot provide a root assembly if --no-root-assembly is passed, found {0} assemblies: '{1}'", unprocessed.Count, string.Join ("', '", unprocessed.ToArray ()))); throw new AggregateException (exceptions); } if (string.IsNullOrEmpty (output_dir)) throw new MonoMacException (51, true, "An output directory (--output) is required if --no-root-assembly is passed."); if (string.IsNullOrEmpty (app_name)) app_name = Path.GetFileNameWithoutExtension (output_dir); } else { if (unprocessed.Count != 1) { var exceptions = new List<Exception> (); CheckForUnknownCommandLineArguments (exceptions, unprocessed); if (unprocessed.Count > 1) { exceptions.Add (ErrorHelper.CreateError (8, "You should provide one root assembly only, found {0} assemblies: '{1}'", unprocessed.Count, string.Join ("', '", unprocessed.ToArray ()))); } else if (unprocessed.Count == 0) { exceptions.Add (ErrorHelper.CreateError (17, "You should provide a root assembly.")); } throw new AggregateException (exceptions); } root_assembly = unprocessed [0]; if (!File.Exists (root_assembly)) throw new MonoMacException (7, true, "The root assembly '{0}' does not exist", root_assembly); string root_wo_ext = Path.GetFileNameWithoutExtension (root_assembly); if (Profile.IsSdkAssembly (root_wo_ext) || Profile.IsProductAssembly (root_wo_ext)) throw new MonoMacException (3, true, "Application name '{0}.exe' conflicts with an SDK or product assembly (.dll) name.", root_wo_ext); if (references.Exists (a => Path.GetFileNameWithoutExtension (a).Equals (root_wo_ext))) throw new MonoMacException (23, true, "Application name '{0}.exe' conflicts with another user assembly.", root_wo_ext); string monoFrameworkDirectory = TargetFramework.MonoFrameworkDirectory; if (IsUnifiedFullSystemFramework || IsClassic) monoFrameworkDirectory = "4.5"; fx_dir = Path.Combine (MonoDirectory, "lib", "mono", monoFrameworkDirectory); if (!Directory.Exists (fx_dir)) throw new MonoMacException (1403, true, "{0} {1} could not be found. Target framework '{2}' is unusable to package the application.", "Directory", fx_dir, userTargetFramework); references.Add (root_assembly); BuildTarget.Resolver.CommandLineAssemblies = references; if (string.IsNullOrEmpty (app_name)) app_name = root_wo_ext; if (string.IsNullOrEmpty (output_dir)) output_dir = Environment.CurrentDirectory; } CreateDirectoriesIfNeeded (); Watch ("Setup", 1); if (!no_executable) { BuildTarget.Resolver.FrameworkDirectory = fx_dir; BuildTarget.Resolver.RootDirectory = Path.GetDirectoryName (Path.GetFullPath (root_assembly)); GatherAssemblies (); CheckReferences (); if (!resolved_assemblies.Exists (f => Path.GetExtension (f).ToLower () == ".exe")) throw new MonoMacException (79, true, "No executable was copied into the app bundle. Please contact '*****@*****.**'", ""); // i18n must be dealed outside linking too (e.g. bug 11448) if (App.LinkMode == LinkMode.None) CopyI18nAssemblies (App.I18n); CopyAssemblies (); Watch ("Copy Assemblies", 1); } CopyResources (); Watch ("Copy Resources", 1); CopyConfiguration (); Watch ("Copy Configuration", 1); ExtractNativeLinkInfo (); if (!no_executable) { foreach (var nr in native_references) { if (!native_libs.ContainsKey (nr)) native_libs.Add (nr, null); } // warn if we ask to remove thread checks but the linker is not enabled if (App.LinkMode == LinkMode.None && thread_check.HasValue && !thread_check.Value) ErrorHelper.Warning (2003, "Option '{0}' will be ignored since linking is disabled", "-disable-thread-check"); var linked_native_libs = Link (); foreach (var kvp in linked_native_libs) { List<MethodDefinition> methods; if (native_libs.TryGetValue (kvp.Key, out methods)) methods.AddRange (kvp.Value); else native_libs.Add (kvp.Key, kvp.Value); } internalSymbols.UnionWith (BuildTarget.LinkContext.RequiredSymbols.Keys); Watch (string.Format ("Linking (mode: '{0}')", App.LinkMode), 1); } CopyDependencies (native_libs); Watch ("Copy Dependencies", 1); // MDK check var ret = Compile (internalSymbols); Watch ("Compile", 1); if (ret != 0) { if (ret == 1) throw new MonoMacException (5109, true, "Native linking failed with error code 1. Check build log for details."); if (ret == 69) throw new MonoMacException (5308, true, "Xcode license agreement may not have been accepted. Please launch Xcode."); // if not then the compilation really failed throw new MonoMacException (5103, true, String.Format ("Failed to compile. Error code - {0}. Please file a bug report at http://bugzilla.xamarin.com", ret)); } if (generate_plist) GeneratePList (); if (App.LinkMode != LinkMode.All && App.RuntimeOptions != null) App.RuntimeOptions.Write (App.AppDirectory); if (!string.IsNullOrEmpty (certificate_name)) { CodeSign (); Watch ("Code Sign", 1); } }