예제 #1
0
        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");
            }
        }
예제 #2
0
        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");
        }
예제 #3
0
        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);
            }
        }