// 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; }
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); }