Example #1
0
        protected override async Task ExecuteAsync()
        {
            // always show the native linker warnings since many of them turn out to be very important
            // and very hard to diagnose otherwise when hidden from the build output. Ref: bug #2430
            var linker_errors = new List <Exception> ();
            var output        = new StringBuilder();
            var code          = await Driver.RunCommandAsync(Target.App.CompilerPath, CompilerFlags.ToString(), null, output);

            Application.ProcessNativeLinkerOutput(Target, output.ToString(), CompilerFlags.AllLibraries, linker_errors, code != 0);

            if (code != 0)
            {
                // if the build failed - it could be because of missing frameworks / libraries we identified earlier
                foreach (var assembly in Target.Assemblies)
                {
                    if (assembly.UnresolvedModuleReferences == null)
                    {
                        continue;
                    }

                    foreach (var mr in assembly.UnresolvedModuleReferences)
                    {
                        // TODO: add more diagnose information on the warnings
                        var name = Path.GetFileNameWithoutExtension(mr.Name);
                        linker_errors.Add(new MonoTouchException(5215, false, "References to '{0}' might require additional -framework=XXX or -lXXX instructions to the native linker", name));
                    }
                }
                // mtouch does not validate extra parameters given to GCC when linking (--gcc_flags)
                if (!String.IsNullOrEmpty(Target.App.UserGccFlags))
                {
                    linker_errors.Add(new MonoTouchException(5201, true, "Native linking failed. Please review the build log and the user flags provided to gcc: {0}", Target.App.UserGccFlags));
                }
                linker_errors.Add(new MonoTouchException(5202, true, "Native linking failed. Please review the build log.", Target.App.UserGccFlags));
            }
            ErrorHelper.Show(linker_errors);

            // the native linker can prefer private (and existing) over public (but non-existing) framework when weak_framework are used
            // on an iOS target version where the framework does not exists, e.g. targeting iOS6 for JavaScriptCore added in iOS7 results in
            // /System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore instead of
            // /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
            // more details in https://bugzilla.xamarin.com/show_bug.cgi?id=31036
            if (Target.WeakFrameworks.Count > 0)
            {
                Target.AdjustDylibs();
            }
            Driver.Watch("Native Link", 1);
        }
Example #2
0
        protected override async Task ExecuteAsync()
        {
            // always show the native linker warnings since many of them turn out to be very important
            // and very hard to diagnose otherwise when hidden from the build output. Ref: bug #2430
            var linker_errors = new List <Exception> ();
            var output        = new StringBuilder();
            var cmd_length    = Target.App.CompilerPath.Length + 1 + CompilerFlags.ToString().Length;

            try {
                var code = await Driver.RunCommandAsync(Target.App.CompilerPath, CompilerFlags.ToArray(), null, output, suppressPrintOnErrors : true);

                Application.ProcessNativeLinkerOutput(Target, output.ToString(), CompilerFlags.AllLibraries, linker_errors, code != 0);

                if (code != 0)
                {
                    Console.WriteLine($"Process exited with code {code}, command:\n{Target.App.CompilerPath} {CompilerFlags.ToString ()}\n{output} ");
                    // if the build failed - it could be because of missing frameworks / libraries we identified earlier
                    foreach (var assembly in Target.Assemblies)
                    {
                        if (assembly.UnresolvedModuleReferences == null)
                        {
                            continue;
                        }

                        foreach (var mr in assembly.UnresolvedModuleReferences)
                        {
                            // TODO: add more diagnose information on the warnings
                            var name = Path.GetFileNameWithoutExtension(mr.Name);
                            linker_errors.Add(new MonoTouchException(5215, false, Errors.MT5215, name));
                        }
                    }
                    // mtouch does not validate extra parameters given to GCC when linking (--gcc_flags)
                    if (Target.App.UserGccFlags?.Count > 0)
                    {
                        linker_errors.Add(new MonoTouchException(5201, true, Errors.MT5201, StringUtils.FormatArguments(Target.App.UserGccFlags)));
                    }
                    else
                    {
                        linker_errors.Add(new MonoTouchException(5202, true, Errors.MT5202));
                    }

                    if (code == 255)
                    {
                        // check command length
                        // getconf ARG_MAX
                        StringBuilder getconf_output = new StringBuilder();
                        if (Driver.RunCommand("getconf", new [] { "ARG_MAX" }, output: getconf_output, suppressPrintOnErrors: true) == 0)
                        {
                            int arg_max;
                            if (int.TryParse(getconf_output.ToString().Trim(' ', '\t', '\n', '\r'), out arg_max))
                            {
                                if (cmd_length > arg_max)
                                {
                                    linker_errors.Add(ErrorHelper.CreateError(5217, Errors.MT5217, cmd_length));
                                }
                                else
                                {
                                    Driver.Log(3, $"Linker failure is probably not due to command-line length (actual: {cmd_length} limit: {arg_max}");
                                }
                            }
                            else
                            {
                                Driver.Log(3, "Failed to parse 'getconf ARG_MAX' output: {0}", getconf_output);
                            }
                        }
                        else
                        {
                            Driver.Log(3, "Failed to execute 'getconf ARG_MAX'\n{0}", getconf_output);
                        }
                    }
                }
            } catch (System.ComponentModel.Win32Exception wex) {
                /* This means we failed to execute the linker, not that the linker itself returned with a failure */
                if (wex.NativeErrorCode == 7 /* E2BIG = Too many arguments */)
                {
                    linker_errors.Add(ErrorHelper.CreateError(5217, wex, Errors.MT5217, cmd_length));
                }
                else
                {
                    linker_errors.Add(ErrorHelper.CreateError(5222, wex, Errors.MX5222, wex.Message));
                }
            }

            ErrorHelper.Show(linker_errors);

            // the native linker can prefer private (and existing) over public (but non-existing) framework when weak_framework are used
            // on an iOS target version where the framework does not exists, e.g. targeting iOS6 for JavaScriptCore added in iOS7 results in
            // /System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore instead of
            // /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
            // more details in https://bugzilla.xamarin.com/show_bug.cgi?id=31036
            if (CompilerFlags.WeakFrameworks.Count > 0)
            {
                Target.AdjustDylibs(OutputFile);
            }
            Driver.Watch("Native Link", 1);
        }
Example #3
0
        public void NativeLink()
        {
            if (!string.IsNullOrEmpty(App.UserGccFlags))
            {
                App.DeadStrip = false;
            }
            if (App.EnableLLVMOnlyBitCode)
            {
                App.DeadStrip = false;
            }

            var compiler_flags = new CompilerFlags()
            {
                Target = this
            };

            // Get global frameworks
            compiler_flags.AddFrameworks(App.Frameworks, App.WeakFrameworks);
            compiler_flags.AddFrameworks(Frameworks, WeakFrameworks);

            // Collect all LinkWith flags and frameworks from all assemblies.
            foreach (var a in Assemblies)
            {
                compiler_flags.AddFrameworks(a.Frameworks, a.WeakFrameworks);
                if (!App.FastDev || App.IsSimulatorBuild)
                {
                    compiler_flags.AddLinkWith(a.LinkWith, a.ForceLoad);
                }
                compiler_flags.AddOtherFlags(a.LinkerFlags);
            }

            var bitcode = App.EnableBitCode;

            if (bitcode)
            {
                compiler_flags.AddOtherFlag(App.EnableMarkerOnlyBitCode ? "-fembed-bitcode-marker" : "-fembed-bitcode");
            }

            if (App.EnablePie.HasValue && App.EnablePie.Value && (App.DeploymentTarget < new Version(4, 2)))
            {
                ErrorHelper.Error(28, "Cannot enable PIE (-pie) when targeting iOS 4.1 or earlier. Please disable PIE (-pie:false) or set the deployment target to at least iOS 4.2");
            }

            if (!App.EnablePie.HasValue)
            {
                App.EnablePie = true;
            }

            if (App.Platform == ApplePlatform.iOS)
            {
                if (App.EnablePie.Value && (App.DeploymentTarget >= new Version(4, 2)))
                {
                    compiler_flags.AddOtherFlag("-Wl,-pie");
                }
                else
                {
                    compiler_flags.AddOtherFlag("-Wl,-no_pie");
                }
            }

            CompileTask.GetArchFlags(compiler_flags, Abis);
            if (App.IsDeviceBuild)
            {
                compiler_flags.AddOtherFlag($"-m{Driver.GetTargetMinSdkName (App)}-version-min={App.DeploymentTarget}");
                compiler_flags.AddOtherFlag($"-isysroot {Driver.Quote (Driver.GetFrameworkDirectory (App))}");
            }
            else
            {
                CompileTask.GetSimulatorCompilerFlags(compiler_flags, null, App);
            }
            compiler_flags.LinkWithMono();
            compiler_flags.LinkWithXamarin();

            compiler_flags.AddLinkWith(link_with);
            compiler_flags.AddOtherFlag($"-o {Driver.Quote (Executable)}");

            compiler_flags.AddOtherFlag("-lz");
            compiler_flags.AddOtherFlag("-liconv");

            bool need_libcpp = false;

            if (App.EnableBitCode)
            {
                need_libcpp = true;
            }
#if ENABLE_BITCODE_ON_IOS
            need_libcpp = true;
#endif
            if (need_libcpp)
            {
                compiler_flags.AddOtherFlag("-lc++");
            }

            // allow the native linker to remove unused symbols (if the caller was removed by the managed linker)
            if (!bitcode)
            {
                // Note that we include *all* (__Internal) p/invoked symbols here
                // We also include any fields from [Field] attributes.
                compiler_flags.ReferenceSymbols(GetRequiredSymbols());
            }

            string mainlib;
            if (App.IsWatchExtension)
            {
                mainlib = "libwatchextension.a";
                compiler_flags.AddOtherFlag(" -e _xamarin_watchextension_main");
            }
            else if (App.IsTVExtension)
            {
                mainlib = "libtvextension.a";
            }
            else if (App.IsExtension)
            {
                mainlib = "libextension.a";
            }
            else
            {
                mainlib = "libapp.a";
            }
            var libdir  = Path.Combine(Driver.GetProductSdkDirectory(App), "usr", "lib");
            var libmain = Path.Combine(libdir, mainlib);
            compiler_flags.AddLinkWith(libmain, true);

            if (App.EnableProfiling)
            {
                string libprofiler;
                if (App.FastDev)
                {
                    libprofiler = Path.Combine(libdir, "libmono-profiler-log.dylib");
                    compiler_flags.AddLinkWith(libprofiler);
                }
                else
                {
                    libprofiler = Path.Combine(libdir, "libmono-profiler-log.a");
                    compiler_flags.AddLinkWith(libprofiler);
                    if (!App.EnableBitCode)
                    {
                        compiler_flags.ReferenceSymbol("mono_profiler_startup_log");
                    }
                }
            }

            if (!string.IsNullOrEmpty(App.UserGccFlags))
            {
                compiler_flags.AddOtherFlag(App.UserGccFlags);
            }

            if (App.DeadStrip)
            {
                compiler_flags.AddOtherFlag("-dead_strip");
            }

            if (App.IsExtension)
            {
                if (App.Platform == ApplePlatform.iOS && Driver.XcodeVersion.Major < 7)
                {
                    compiler_flags.AddOtherFlag("-lpkstart");
                    compiler_flags.AddOtherFlag($"-F {Driver.Quote (Path.Combine (Driver.GetFrameworkDirectory (App), "System/Library/PrivateFrameworks"))} -framework PlugInKit");
                }
                compiler_flags.AddOtherFlag("-fapplication-extension");
            }

            compiler_flags.Inputs = new List <string> ();
            var flags = compiler_flags.ToString();              // This will populate Inputs.

            if (!Application.IsUptodate(compiler_flags.Inputs, new string [] { Executable }))
            {
                // always show the native linker warnings since many of them turn out to be very important
                // and very hard to diagnose otherwise when hidden from the build output. Ref: bug #2430
                var linker_errors = new List <Exception> ();
                var output        = new StringBuilder();
                var code          = Driver.RunCommand(App.CompilerPath, flags, null, output);

                Application.ProcessNativeLinkerOutput(this, output.ToString(), link_with, linker_errors, code != 0);

                if (code != 0)
                {
                    // if the build failed - it could be because of missing frameworks / libraries we identified earlier
                    foreach (var assembly in Assemblies)
                    {
                        if (assembly.UnresolvedModuleReferences == null)
                        {
                            continue;
                        }

                        foreach (var mr in assembly.UnresolvedModuleReferences)
                        {
                            // TODO: add more diagnose information on the warnings
                            var name = Path.GetFileNameWithoutExtension(mr.Name);
                            linker_errors.Add(new MonoTouchException(5215, false, "References to '{0}' might require additional -framework=XXX or -lXXX instructions to the native linker", name));
                        }
                    }
                    // mtouch does not validate extra parameters given to GCC when linking (--gcc_flags)
                    if (!String.IsNullOrEmpty(App.UserGccFlags))
                    {
                        linker_errors.Add(new MonoTouchException(5201, true, "Native linking failed. Please review the build log and the user flags provided to gcc: {0}", App.UserGccFlags));
                    }
                    linker_errors.Add(new MonoTouchException(5202, true, "Native linking failed. Please review the build log.", App.UserGccFlags));
                }
                ErrorHelper.Show(linker_errors);
            }
            else
            {
                cached_executable = true;
                Driver.Log(3, "Target '{0}' is up-to-date.", Executable);
            }
            // the native linker can prefer private (and existing) over public (but non-existing) framework when weak_framework are used
            // on an iOS target version where the framework does not exists, e.g. targeting iOS6 for JavaScriptCore added in iOS7 results in
            // /System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore instead of
            // /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
            // more details in https://bugzilla.xamarin.com/show_bug.cgi?id=31036
            if (WeakFrameworks.Count > 0)
            {
                AdjustDylibs();
            }
            Driver.Watch("Native Link", 1);
        }
Example #4
0
        protected override async Task ExecuteAsync()
        {
            // always show the native linker warnings since many of them turn out to be very important
            // and very hard to diagnose otherwise when hidden from the build output. Ref: bug #2430
            var linker_errors = new List <Exception> ();
            var output        = new StringBuilder();
            var code          = await Driver.RunCommandAsync(Target.App.CompilerPath, CompilerFlags.ToString(), null, output);

            Application.ProcessNativeLinkerOutput(Target, output.ToString(), CompilerFlags.AllLibraries, linker_errors, code != 0);

            if (code != 0)
            {
                // if the build failed - it could be because of missing frameworks / libraries we identified earlier
                foreach (var assembly in Target.Assemblies)
                {
                    if (assembly.UnresolvedModuleReferences == null)
                    {
                        continue;
                    }

                    foreach (var mr in assembly.UnresolvedModuleReferences)
                    {
                        // TODO: add more diagnose information on the warnings
                        var name = Path.GetFileNameWithoutExtension(mr.Name);
                        linker_errors.Add(new MonoTouchException(5215, false, "References to '{0}' might require additional -framework=XXX or -lXXX instructions to the native linker", name));
                    }
                }
                // mtouch does not validate extra parameters given to GCC when linking (--gcc_flags)
                if (!String.IsNullOrEmpty(Target.App.UserGccFlags))
                {
                    linker_errors.Add(new MonoTouchException(5201, true, "Native linking failed. Please review the build log and the user flags provided to gcc: {0}", Target.App.UserGccFlags));
                }
                linker_errors.Add(new MonoTouchException(5202, true, "Native linking failed. Please review the build log.", Target.App.UserGccFlags));

                if (code == 255)
                {
                    // check command length
                    // getconf ARG_MAX
                    StringBuilder getconf_output = new StringBuilder();
                    if (Driver.RunCommand("getconf", "ARG_MAX", output: getconf_output, suppressPrintOnErrors: true) == 0)
                    {
                        int arg_max;
                        if (int.TryParse(getconf_output.ToString().Trim(' ', '\t', '\n', '\r'), out arg_max))
                        {
                            var cmd_length = Target.App.CompilerPath.Length + 1 + CompilerFlags.ToString().Length;
                            if (cmd_length > arg_max)
                            {
                                linker_errors.Add(ErrorHelper.CreateWarning(5217, $"Native linking possibly failed because the linker command line was too long ({cmd_length} characters)."));
                            }
                            else
                            {
                                Driver.Log(3, $"Linker failure is probably not due to command-line length (actual: {cmd_length} limit: {arg_max}");
                            }
                        }
                        else
                        {
                            Driver.Log(3, "Failed to parse 'getconf ARG_MAX' output: {0}", getconf_output);
                        }
                    }
                    else
                    {
                        Driver.Log(3, "Failed to execute 'getconf ARG_MAX'\n{0}", getconf_output);
                    }
                }
            }
            ErrorHelper.Show(linker_errors);

            // the native linker can prefer private (and existing) over public (but non-existing) framework when weak_framework are used
            // on an iOS target version where the framework does not exists, e.g. targeting iOS6 for JavaScriptCore added in iOS7 results in
            // /System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore instead of
            // /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
            // more details in https://bugzilla.xamarin.com/show_bug.cgi?id=31036
            if (CompilerFlags.WeakFrameworks.Count > 0)
            {
                Target.AdjustDylibs(OutputFile);
            }
            Driver.Watch("Native Link", 1);
        }