Exemplo n.º 1
0
        // The input file is either a .s or a .bc file
        BuildTask CreateCompileTask(string assembly_name, string infile_path, Abi abi)
        {
            var ext = App.FastDev ? "dylib" : "o";
            var ofile = Path.ChangeExtension (infile_path, ext);
            var install_name = string.Empty;

            if (App.FastDev) {
                if (dylibs == null)
                    dylibs = new List<string> ();
                dylibs.Add (ofile);
                install_name = "lib" + Path.GetFileName (assembly_name) + ".dylib";
            } else {
                Target.LinkWith (ofile);
            }

            if (Application.IsUptodate (new string [] { infile_path, Driver.CompilerPath }, new string [] { ofile })) {
                Driver.Log (3, "Target {0} is up-to-date.", ofile);
                return null;
            } else {
                Application.TryDelete (ofile); // otherwise the next task might not detect that it will have to rebuild.
                Driver.Log (3, "Target {0} needs to be rebuilt.", ofile);
            }

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

            BuildTask bitcode_task = null;
            BuildTask link_task = null;
            string link_task_input, link_language = "";

            if (App.EnableAsmOnlyBitCode) {
                link_task_input = infile_path + ".ll";
                link_language = "";
                // linker_flags.Add (" -fembed-bitcode");

                bitcode_task = new BitCodeify () {
                    Input = infile_path,
                    OutputFile = link_task_input,
                    Platform = App.Platform,
                    Abi = abi,
                    DeploymentTarget = App.DeploymentTarget,
                };
            } else {
                link_task_input = infile_path;
                if (infile_path.EndsWith (".s"))
                    link_language = "assembler";
            }

            if (App.FastDev) {
                compiler_flags.AddFrameworks (Frameworks, WeakFrameworks);
                compiler_flags.AddLinkWith (LinkWith, ForceLoad);
                compiler_flags.LinkWithMono ();
                compiler_flags.LinkWithXamarin ();
                compiler_flags.AddOtherFlags (LinkerFlags);
                if (Target.GetEntryPoints ().ContainsKey ("UIApplicationMain"))
                    compiler_flags.AddFramework ("UIKit");
            }

            link_task = new LinkTask ()
            {
                Target = Target,
                AssemblyName = assembly_name,
                Abi = abi,
                InputFile = link_task_input,
                OutputFile = ofile,
                InstallName = install_name,
                CompilerFlags = compiler_flags,
                SharedLibrary = App.FastDev,
                Language = link_language,
            };

            if (bitcode_task != null) {
                bitcode_task.NextTasks = new BuildTask[] { link_task };
                return bitcode_task;
            }
            return link_task;
        }
Exemplo n.º 2
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);
                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.TargetMinSdkName}-version-min={App.DeploymentTarget}");
                compiler_flags.AddOtherFlag ($"-isysroot {Driver.Quote (Driver.FrameworkDirectory)}");
            } 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");

            if (App.EnableBitCode)
                compiler_flags.AddOtherFlag ("-lc++");

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

            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.ProductSdkDirectory, "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.FrameworkDirectory, "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 (Driver.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);
        }