Exemple #1
0
        public static void Create(List <BuildTask> tasks, Abi abi, Target target, string ifile)
        {
            var app   = target.App;
            var arch  = abi.AsArchString();
            var ofile = Path.Combine(app.Cache.Location, Path.GetFileNameWithoutExtension(ifile) + "." + arch + ".o");

            if (!Application.IsUptodate(ifile, ofile))
            {
                tasks.Add(new RegistrarTask()
                {
                    Target        = target,
                    Abi           = abi,
                    InputFile     = ifile,
                    OutputFile    = ofile,
                    SharedLibrary = false,
                    Language      = "objective-c++",
                });
            }
            else
            {
                Driver.Log(3, "Target '{0}' is up-to-date.", ofile);
            }

            target.LinkWith(ofile);
        }
Exemple #2
0
        public static void Create(List <BuildTask> tasks, Abi abi, Target target, string ifile)
        {
            var arch  = abi.AsArchString();
            var ext   = target.App.FastDev ? ".dylib" : ".o";
            var ofile = Path.Combine(target.App.Cache.Location, "lib" + Path.GetFileNameWithoutExtension(ifile) + "." + arch + ext);

            if (!Application.IsUptodate(ifile, ofile))
            {
                var task = new PinvokesTask()
                {
                    Target        = target,
                    Abi           = abi,
                    InputFile     = ifile,
                    OutputFile    = ofile,
                    SharedLibrary = target.App.FastDev,
                    Language      = "objective-c++",
                };
                if (target.App.FastDev)
                {
                    task.InstallName = "lib" + Path.GetFileNameWithoutExtension(ifile) + ext;
                    task.CompilerFlags.AddFramework("Foundation");
                    task.CompilerFlags.LinkWithXamarin();
                }
                tasks.Add(task);
            }
            else
            {
                Driver.Log(3, "Target '{0}' is up-to-date.", ofile);
            }

            target.LinkWith(ofile);
            target.LinkWithAndShip(ofile);
        }
        public void LinkWithPInvokes(Abi abi)
        {
            if (!Driver.App.FastDev || !Driver.App.RequiresPInvokeWrappers)
            {
                return;
            }

            AddOtherFlag(Path.Combine(Cache.Location, "libpinvokes." + abi.AsArchString() + ".dylib"));
        }
        public static void GetCatalystCompilerFlags(CompilerFlags flags, Abi abi, Application app)
        {
            GetCompilerFlags(app, flags, false);
            flags.AddOtherFlag($"-target", $"{abi.AsArchString ()}-apple-ios{app.DeploymentTarget}-macabi");
            var isysroot = Driver.GetFrameworkDirectory(app);

            flags.AddOtherFlag($"-isystem", Path.Combine(isysroot, "System", "iOSSupport", "usr", "include"));
            flags.AddOtherFlag($"-iframework", Path.Combine(isysroot, "System", "iOSSupport", "System", "Library", "Frameworks"));
            flags.AddOtherFlag($"-L{Path.Combine (isysroot, "System", "iOSSupport", "usr", "lib")}");
        }
Exemple #5
0
        public static void Create(List <BuildTask> tasks, Target target, Abi abi, IEnumerable <Assembly> assemblies, string assemblyName, IList <string> registration_methods)
        {
            var app   = target.App;
            var arch  = abi.AsArchString();
            var ofile = Path.Combine(app.Cache.Location, "main." + arch + ".o");
            var ifile = Path.Combine(app.Cache.Location, "main." + arch + ".m");

            var files = assemblies.Select(v => v.FullPath);

            if (!Application.IsUptodate(files, new string [] { ifile }))
            {
                Driver.GenerateMain(target.App, assemblies, assemblyName, abi, ifile, registration_methods);
            }
            else
            {
                Driver.Log(3, "Target '{0}' is up-to-date.", ifile);
            }

            if (!Application.IsUptodate(ifile, ofile))
            {
                var main = new MainTask()
                {
                    Target        = target,
                    Abi           = abi,
                    AssemblyName  = assemblyName,
                    InputFile     = ifile,
                    OutputFile    = ofile,
                    SharedLibrary = false,
                    Language      = "objective-c++",
                };
                main.CompilerFlags.AddDefine("MONOTOUCH");
                tasks.Add(main);
            }
            else
            {
                Driver.Log(3, "Target '{0}' is up-to-date.", ofile);
            }

            target.LinkWith(ofile);
        }
Exemple #6
0
        // note: this is executed under Parallel.ForEach
        void GenerateIOSMain(StringWriter sw, Abi abi)
        {
            var app                     = App;
            var assemblies              = Assemblies;
            var assembly_name           = App.AssemblyName;
            var assembly_externs        = new StringBuilder();
            var assembly_aot_modules    = new StringBuilder();
            var register_assemblies     = new StringBuilder();
            var assembly_location       = new StringBuilder();
            var assembly_location_count = 0;
            var enable_llvm             = (abi & Abi.LLVM) != 0;

            register_assemblies.AppendLine("\tGCHandle exception_gchandle = INVALID_GCHANDLE;");
            foreach (var s in assemblies)
            {
                if (!s.IsAOTCompiled)
                {
                    continue;
                }

                var info = s.AssemblyDefinition.Name.Name;
                info = EncodeAotSymbol(info);
                assembly_externs.Append("extern void *mono_aot_module_").Append(info).AppendLine("_info;");
                assembly_aot_modules.Append("\tmono_aot_register_module (mono_aot_module_").Append(info).AppendLine("_info);");

                string sname = s.FileName;
                if (assembly_name != sname && IsBoundAssembly(s))
                {
                    register_assemblies.Append("\txamarin_open_and_register (\"").Append(sname).Append("\", &exception_gchandle);").AppendLine();
                    register_assemblies.AppendLine("\txamarin_process_managed_exception_gchandle (exception_gchandle);");
                }
            }

            var frameworks = assemblies.Where((a) => a.BuildTarget == AssemblyBuildTarget.Framework)
                             .OrderBy((a) => a.Identity, StringComparer.Ordinal);

            foreach (var asm_fw in frameworks)
            {
                var asm_name = asm_fw.Identity;
                if (asm_fw.BuildTargetName == asm_name)
                {
                    continue;                     // this is deduceable
                }
                var prefix = string.Empty;
                if (!app.HasFrameworksDirectory && asm_fw.IsCodeShared)
                {
                    prefix = "../../";
                }
                var suffix = string.Empty;
                if (app.IsSimulatorBuild)
                {
                    suffix = "/simulator";
                }
                assembly_location.AppendFormat("\t{{ \"{0}\", \"{2}Frameworks/{1}.framework/MonoBundle{3}\" }},\n", asm_name, asm_fw.BuildTargetName, prefix, suffix);
                assembly_location_count++;
            }

            sw.WriteLine("#include \"xamarin/xamarin.h\"");

            if (assembly_location.Length > 0)
            {
                sw.WriteLine();
                sw.WriteLine("struct AssemblyLocation assembly_location_entries [] = {");
                sw.WriteLine(assembly_location);
                sw.WriteLine("};");

                sw.WriteLine();
                sw.WriteLine("struct AssemblyLocations assembly_locations = {{ {0}, assembly_location_entries }};", assembly_location_count);
            }

            sw.WriteLine();
            sw.WriteLine(assembly_externs);

            sw.WriteLine("void xamarin_register_modules_impl ()");
            sw.WriteLine("{");
            sw.WriteLine(assembly_aot_modules);
            sw.WriteLine("}");
            sw.WriteLine();

            sw.WriteLine("void xamarin_register_assemblies_impl ()");
            sw.WriteLine("{");
            sw.WriteLine(register_assemblies);
            sw.WriteLine("}");
            sw.WriteLine();

            // Burn in a reference to the profiling symbol so that the native linker doesn't remove it
            // On iOS we can pass -u to the native linker, but that doesn't work on tvOS, where
            // we're building with bitcode (even when bitcode is disabled, we still build with the
            // bitcode marker, which makes the linker reject -u).
            if (app.EnableProfiling)
            {
                sw.WriteLine("extern \"C\" { void mono_profiler_init_log (); }");
                sw.WriteLine("typedef void (*xamarin_profiler_symbol_def)();");
                sw.WriteLine("extern xamarin_profiler_symbol_def xamarin_profiler_symbol;");
                sw.WriteLine("xamarin_profiler_symbol_def xamarin_profiler_symbol = NULL;");
            }

            if (app.UseInterpreter)
            {
                sw.WriteLine("extern \"C\" { void mono_ee_interp_init (const char *); }");
                sw.WriteLine("extern \"C\" { void mono_icall_table_init (void); }");
                sw.WriteLine("extern \"C\" { void mono_marshal_ilgen_init (void); }");
                sw.WriteLine("extern \"C\" { void mono_method_builder_ilgen_init (void); }");
                sw.WriteLine("extern \"C\" { void mono_sgen_mono_ilgen_init (void); }");
            }

#if NET
            if (app.MonoNativeMode != MonoNativeMode.None)
            {
                sw.WriteLine("static const char *xamarin_runtime_libraries_array[] = {");
                foreach (var lib in app.MonoLibraries)
                {
                    sw.WriteLine($"\t\"{Path.GetFileNameWithoutExtension (lib)}\",");
                }
                sw.WriteLine($"\tNULL");
                sw.WriteLine("};");
            }
#endif

            sw.WriteLine("void xamarin_setup_impl ()");
            sw.WriteLine("{");

            if (app.EnableProfiling)
            {
                sw.WriteLine("\txamarin_profiler_symbol = mono_profiler_init_log;");
            }

            if (app.EnableLLVMOnlyBitCode)
            {
                sw.WriteLine("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);");
            }
            else if (app.UseInterpreter)
            {
                sw.WriteLine("\tmono_icall_table_init ();");
                sw.WriteLine("\tmono_marshal_ilgen_init ();");
                sw.WriteLine("\tmono_method_builder_ilgen_init ();");
                sw.WriteLine("\tmono_sgen_mono_ilgen_init ();");
#if !NET
                sw.WriteLine("\tmono_ee_interp_init (NULL);");
#endif
                sw.WriteLine("\tmono_jit_set_aot_mode (MONO_AOT_MODE_INTERP);");
            }
            else if (app.IsDeviceBuild)
            {
                sw.WriteLine("\tmono_jit_set_aot_mode (MONO_AOT_MODE_FULL);");
            }
            else if (app.Platform == ApplePlatform.MacCatalyst && ((abi & Abi.ARM64) == Abi.ARM64))
            {
                sw.WriteLine("\tmono_jit_set_aot_mode (MONO_AOT_MODE_FULL);");
            }
            else if (app.IsSimulatorBuild && ((abi & Abi.ARM64) == Abi.ARM64))
            {
                sw.WriteLine("\tmono_jit_set_aot_mode (MONO_AOT_MODE_FULL);");
            }

            if (assembly_location.Length > 0)
            {
                sw.WriteLine("\txamarin_set_assembly_directories (&assembly_locations);");
            }

            sw.WriteLine("\txamarin_invoke_registration_methods ();");

            if (app.MonoNativeMode != MonoNativeMode.None)
            {
#if NET
                // Mono doesn't support dllmaps for Mac Catalyst / macOS in .NET, so we're using an alternative:
                // the PINVOKE_OVERRIDE runtime option. Since we have to use it for Mac Catalyst + macOS, let's
                // just use it everywhere to simplify code. This means that at runtime we need to know how we
                // linked to mono, so store that in the xamarin_libmono_native_link_mode variable.
                // Ref: https://github.com/dotnet/runtime/issues/43204 (macOS) https://github.com/dotnet/runtime/issues/48110 (Mac Catalyst)
                sw.WriteLine($"\txamarin_libmono_native_link_mode = XamarinNativeLinkMode{app.LibMonoNativeLinkMode};");
                sw.WriteLine($"\txamarin_runtime_libraries = xamarin_runtime_libraries_array;");
#else
                string mono_native_lib;
                if (app.LibMonoNativeLinkMode == AssemblyBuildTarget.StaticObject)
                {
                    mono_native_lib = "__Internal";
                }
                else
                {
                    mono_native_lib = app.GetLibNativeName() + ".dylib";
                }
                sw.WriteLine();
                sw.WriteLine($"\tmono_dllmap_insert (NULL, \"System.Native\", NULL, \"{mono_native_lib}\", NULL);");
                sw.WriteLine($"\tmono_dllmap_insert (NULL, \"System.Security.Cryptography.Native.Apple\", NULL, \"{mono_native_lib}\", NULL);");
                sw.WriteLine($"\tmono_dllmap_insert (NULL, \"System.Net.Security.Native\", NULL, \"{mono_native_lib}\", NULL);");
                sw.WriteLine();
#endif
            }

            if (app.EnableDebug)
            {
                sw.WriteLine("\txamarin_gc_pump = {0};", app.DebugTrack.Value ? "TRUE" : "FALSE");
            }
            sw.WriteLine("\txamarin_init_mono_debug = {0};", app.PackageManagedDebugSymbols ? "TRUE" : "FALSE");
            sw.WriteLine("\txamarin_executable_name = \"{0}\";", assembly_name);
            if (app.XamarinRuntime == XamarinRuntime.MonoVM)
            {
                sw.WriteLine("\tmono_use_llvm = {0};", enable_llvm ? "TRUE" : "FALSE");
            }
            sw.WriteLine("\txamarin_log_level = {0};", Driver.Verbosity.ToString(CultureInfo.InvariantCulture));
            sw.WriteLine("\txamarin_arch_name = \"{0}\";", abi.AsArchString());
            if (!app.IsDefaultMarshalManagedExceptionMode)
            {
                sw.WriteLine("\txamarin_marshal_managed_exception_mode = MarshalManagedExceptionMode{0};", app.MarshalManagedExceptions);
            }
            sw.WriteLine("\txamarin_marshal_objectivec_exception_mode = MarshalObjectiveCExceptionMode{0};", app.MarshalObjectiveCExceptions);
            if (app.EnableDebug)
            {
                sw.WriteLine("\txamarin_debug_mode = TRUE;");
            }
            if (!string.IsNullOrEmpty(app.MonoGCParams))
            {
                sw.WriteLine("\tsetenv (\"MONO_GC_PARAMS\", \"{0}\", 1);", app.MonoGCParams);
            }
            // Do this last, so that the app developer can override any other environment variable we set.
            foreach (var kvp in app.EnvironmentVariables)
            {
                sw.WriteLine("\tsetenv (\"{0}\", \"{1}\", 1);", kvp.Key.Replace("\"", "\\\""), kvp.Value.Replace("\"", "\\\""));
            }
            sw.WriteLine("\txamarin_supports_dynamic_registration = {0};", app.DynamicRegistrationSupported ? "TRUE" : "FALSE");
#if NET
            sw.WriteLine("\txamarin_runtime_configuration_name = {0};", string.IsNullOrEmpty(app.RuntimeConfigurationFile) ? "NULL" : $"\"{app.RuntimeConfigurationFile}\"");
#endif
            sw.WriteLine("}");
            sw.WriteLine();
            sw.Write("int ");
            sw.Write(app.IsWatchExtension ? "xamarin_watchextension_main" : "main");
            sw.WriteLine(" (int argc, char **argv)");
            sw.WriteLine("{");
            sw.WriteLine("\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];");
            if (app.IsExtension)
            {
                // the name of the executable must be the bundle id (reverse dns notation)
                // but we do not want to impose that (ugly) restriction to the managed .exe / project name / ...
                sw.WriteLine("\targv [0] = (char *) \"{0}\";", Path.GetFileNameWithoutExtension(app.RootAssemblies [0]));
                sw.WriteLine("\tint rv = xamarin_main (argc, argv, XamarinLaunchModeExtension);");
            }
            else
            {
                sw.WriteLine("\tint rv = xamarin_main (argc, argv, XamarinLaunchModeApp);");
            }
            sw.WriteLine("\t[pool drain];");
            sw.WriteLine("\treturn rv;");
            sw.WriteLine("}");

            string extension_main = null;
            if (app.Platform == ApplePlatform.WatchOS && app.IsWatchExtension)
            {
                // We're building a watch extension, and we have multiple scenarios, depending on the watchOS version we're executing on:
                //
                // * watchOS 2.0 -> 5.*: we must call a `main` function provided in the WatchKit framework.
                // * watchOS 6.0 -> *  : we must call a `WKExtensionMain` function provided in the WatchKit framework.
                // * watchOS 7.0 -> *  : The `WKExtensionMain` function uses dlsym to find any `main` functions in the
                //                       main executable, and calls that function (otherwise WKExtensionMain will call
                //                       UIApplicationMain and normal startup occurs)
                //
                // * We can't call our entry point "main", because we call WKExtensionMain, and then we run into an
                //   infinite loop on watchOS 7.0. So we call it xamarin_watch_extension_main.
                // * The watchOS 6+ SDK helpfully provides a static library (WKExtensionMainLegacy) that has a
                //   WKExtensionMain function, which we use when the deployment target is earlier than watchOS 6.0.
                //   This means that calling WKExtensionMain works everywhere (as long as we're using the
                //   watchOS 6+ SDK to build; otherwise we just call "main" directly and don't link with the
                //   WKExtensionMainLegacy library)

                if (app.SdkVersion.Major >= 6)
                {
                    extension_main = "WKExtensionMain";
                }
                else
                {
                    extension_main = "main";
                }
            }

            if (!string.IsNullOrEmpty(extension_main))
            {
                sw.WriteLine($"extern \"C\" {{ int {extension_main} (int argc, char* argv[]); }}");
                sw.WriteLine();
            }

            sw.WriteLine();
            sw.WriteLine("void xamarin_initialize_callbacks () __attribute__ ((constructor));");
            sw.WriteLine("void xamarin_initialize_callbacks ()");
            sw.WriteLine("{");
            sw.WriteLine("\txamarin_setup = xamarin_setup_impl;");
            sw.WriteLine("\txamarin_register_assemblies = xamarin_register_assemblies_impl;");
            sw.WriteLine("\txamarin_register_modules = xamarin_register_modules_impl;");
            if (!string.IsNullOrEmpty(extension_main))
            {
                sw.WriteLine($"\txamarin_extension_main = {extension_main};");
            }
            sw.WriteLine("}");
        }
        IEnumerable <BuildTask> CreateManagedToAssemblyTasks(string s, Abi abi, string build_dir)
        {
            var    arch = abi.AsArchString();
            var    asm_dir = Cache.Location;
            var    asm = Path.Combine(asm_dir, Path.GetFileName(s)) + "." + arch + ".s";
            var    llvm_asm = Path.Combine(asm_dir, Path.GetFileName(s)) + "." + arch + "-llvm.s";
            var    data = Path.Combine(asm_dir, Path.GetFileNameWithoutExtension(s)) + "." + arch + ".aotdata";
            string llvm_ofile, llvm_aot_ofile = "";
            var    is_llvm       = (abi & Abi.LLVM) == Abi.LLVM;
            bool   assemble_llvm = is_llvm && Driver.LLVMAsmWriter;

            if (!File.Exists(s))
            {
                throw new MonoTouchException(3004, true, "Could not AOT the assembly '{0}' because it doesn't exist.", s);
            }

            HashSet <string> dependencies = null;
            List <string>    deps         = null;
            List <string>    outputs      = new List <string> ();
            var warnings = new List <Exception> ();

            dependencies = ComputeDependencies(warnings);

            if (warnings.Count > 0)
            {
                ErrorHelper.Show(warnings);
                ErrorHelper.Warning(3006, "Could not compute a complete dependency map for the project. This will result in slower build times because Xamarin.iOS can't properly detect what needs to be rebuilt (and what does not need to be rebuilt). Please review previous warnings for more details.");
            }
            else
            {
                deps = new List <string> (dependencies.ToArray());
                deps.Add(s);
                deps.Add(Driver.GetAotCompiler(Target.Is64Build));
            }

            if (App.EnableLLVMOnlyBitCode)
            {
                //
                // In llvm-only mode, the AOT compiler emits a .bc file and no .s file for JITted code
                //
                llvm_ofile = Path.Combine(asm_dir, Path.GetFileName(s)) + "." + arch + ".bc";
                outputs.Add(llvm_ofile);
                llvm_aot_ofile = llvm_ofile;
            }
            else
            {
                llvm_ofile = Path.Combine(asm_dir, Path.GetFileName(s)) + "." + arch + "-llvm.o";
                outputs.Add(asm);

                if (is_llvm)
                {
                    if (assemble_llvm)
                    {
                        llvm_aot_ofile = llvm_asm;
                    }
                    else
                    {
                        llvm_aot_ofile = llvm_ofile;
                        Target.LinkWith(llvm_ofile);
                    }
                    outputs.Add(llvm_aot_ofile);
                }
            }

            if (deps != null && Application.IsUptodate(deps, outputs))
            {
                Driver.Log(3, "Target {0} is up-to-date.", asm);
                if (App.EnableLLVMOnlyBitCode)
                {
                    return(CreateCompileTasks(s, null, llvm_ofile, abi));
                }
                else
                {
                    return(CreateCompileTasks(s, asm, assemble_llvm ? llvm_asm : null, abi));
                }
            }
            else
            {
                Application.TryDelete(asm);                  // otherwise the next task might not detect that it will have to rebuild.
                Application.TryDelete(llvm_asm);
                Application.TryDelete(llvm_ofile);
                Driver.Log(3, "Target {0} needs to be rebuilt.", asm);
            }

            var aotCompiler = Driver.GetAotCompiler(Target.Is64Build);
            var aotArgs     = Driver.GetAotArguments(s, abi, build_dir, asm, llvm_aot_ofile, data);

            Driver.Log(3, "Aot compiler: {0} {1}", aotCompiler, aotArgs);

            AotDataFiles.Add(data);

            IEnumerable <BuildTask> nextTasks;

            if (App.EnableLLVMOnlyBitCode)
            {
                nextTasks = CreateCompileTasks(s, null, llvm_ofile, abi);
            }
            else
            {
                nextTasks = CreateCompileTasks(s, asm, assemble_llvm ? llvm_asm : null, abi);
            }

            return(new BuildTask [] { new AOTTask()
                                      {
                                          AssemblyName = s,
                                          ProcessStartInfo = Driver.CreateStartInfo(aotCompiler, aotArgs, Path.GetDirectoryName(s)),
                                          NextTasks = nextTasks
                                      } });
        }
        /*
         * Runs the AOT compiler, creating one of the following:
         *     [not llvm]     => .s           + .aotdata
         *     [is llvm-only] => .bc          + .aotdata
         *     [is llvm]      =>
         *          [is llvm creating assembly code] => .s + -llvm.s + .aotdata
         *          [is llvm creating object code]   => .s + -llvm.o + .aotdata
         */
        public void CreateAOTTask(Abi abi)
        {
            // Check if we've already created the AOT tasks.
            if (AotInfos.ContainsKey(abi))
            {
                return;
            }

            var assembly_path  = FullPath;
            var build_dir      = Path.GetDirectoryName(assembly_path);
            var arch           = abi.AsArchString();
            var asm_dir        = Path.Combine(App.Cache.Location, arch);
            var asm            = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + ".s";
            var data           = Path.Combine(asm_dir, Path.GetFileNameWithoutExtension(assembly_path)) + ".aotdata" + "." + arch;
            var llvm_aot_ofile = "";
            var asm_output     = (string)null;
            var other_output   = string.Empty;
            var is_llvm        = (abi & Abi.LLVM) == Abi.LLVM;

            Directory.CreateDirectory(asm_dir);

            if (!File.Exists(assembly_path))
            {
                throw new MonoTouchException(3004, true, Errors.MT3004, assembly_path);
            }

            var aotInfo = new AotInfo();

            AotInfos.Add(abi, aotInfo);

            if (App.EnableLLVMOnlyBitCode)
            {
                // In llvm-only mode, the AOT compiler emits a .bc file and no .s file for JITted code
                llvm_aot_ofile = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + ".bc";
                aotInfo.BitcodeFiles.Add(llvm_aot_ofile);
                other_output = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + "-output";
            }
            else if (is_llvm)
            {
                if (Driver.GetLLVMAsmWriter(App))
                {
                    llvm_aot_ofile = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + "-llvm.s";
                    aotInfo.AsmFiles.Add(llvm_aot_ofile);
                }
                else
                {
                    llvm_aot_ofile = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + "-llvm.o";
                    aotInfo.ObjectFiles.Add(llvm_aot_ofile);
                }
                asm_output = asm;
            }
            else
            {
                asm_output = asm;
            }

            if (!string.IsNullOrEmpty(asm_output))
            {
                aotInfo.AsmFiles.Add(asm_output);
            }
            aotInfo.AotDataFiles.Add(data);

            var aotCompiler = Driver.GetAotCompiler(App, abi, Target.Is64Build);
            var aotArgs     = Driver.GetAotArguments(App, assembly_path, abi, build_dir, asm_output ?? other_output, llvm_aot_ofile, data);
            var task        = new AOTTask
            {
                Assembly                = this,
                AssemblyName            = assembly_path,
                AddBitcodeMarkerSection = BuildTarget != AssemblyBuildTarget.StaticObject && App.EnableMarkerOnlyBitCode,
                AssemblyPath            = asm,
                ProcessStartInfo        = Driver.CreateStartInfo(App, aotCompiler, aotArgs, Path.GetDirectoryName(assembly_path)),
                AotInfo = aotInfo,
            };

            if (App.Platform == ApplePlatform.WatchOS)
            {
                // Visual Studio for Mac sets this environment variable, and it confuses the AOT compiler.
                // So unset it.
                // See https://github.com/mono/mono/issues/11765
                task.ProcessStartInfo.EnvironmentVariables ["MONO_THREADS_SUSPEND"] = null;
            }

            aotInfo.Task = task;
        }
        public static void Create(List<BuildTask> tasks, Abi abi, Target target, string ifile)
        {
            var arch = abi.AsArchString ();
            var ofile = Path.Combine (Cache.Location, "registrar." + arch + ".o");

            if (!Application.IsUptodate (ifile, ofile)) {
                tasks.Add (new RegistrarTask ()
                {
                    Target = target,
                    Abi = abi,
                    InputFile = ifile,
                    OutputFile = ofile,
                    SharedLibrary = false,
                    Language = "objective-c++",
                });
            } else {
                Driver.Log (3, "Target '{0}' is up-to-date.", ofile);
            }

            target.LinkWith (ofile);
        }
        public static void Create(List<BuildTask> tasks, Target target, Abi abi, IEnumerable<Assembly> assemblies, string assemblyName, IList<string> registration_methods)
        {
            var arch = abi.AsArchString ();
            var ofile = Path.Combine (Cache.Location, "main." + arch + ".o");
            var ifile = Path.Combine (Cache.Location, "main." + arch + ".m");

            var files = assemblies.Select (v => v.FullPath);

            if (!Application.IsUptodate (files, new string [] { ifile })) {
                Driver.GenerateMain (assemblies, assemblyName, abi, ifile, registration_methods);
            } else {
                Driver.Log (3, "Target '{0}' is up-to-date.", ifile);
            }

            if (!Application.IsUptodate (ifile, ofile)) {
                var main = new MainTask ()
                {
                    Target = target,
                    Abi = abi,
                    AssemblyName = assemblyName,
                    InputFile = ifile,
                    OutputFile = ofile,
                    SharedLibrary = false,
                    Language = "objective-c++",
                };
                main.CompilerFlags.AddDefine ("MONOTOUCH");
                tasks.Add (main);
            } else {
                Driver.Log (3, "Target '{0}' is up-to-date.", ofile);
            }

            target.LinkWith (ofile);
        }
        public static string GetAotArguments(Application app, string filename, Abi abi,
                                             string outputDir, string outputFile, string llvmOutputFile, string dataFile)
        {
            string aot_args         = string.Empty;
            string aot_other_args   = string.Empty;
            bool   debug_all        = false;
            var    debug_assemblies = new List <string>();

            string fname        = Path.GetFileName(filename);
            var    args         = new StringBuilder();
            bool   enable_llvm  = (abi & Abi.LLVM) != 0;
            bool   enable_thumb = (abi & Abi.Thumb) != 0;
            bool   enable_debug = app.EnableDebug;
            bool   enable_mdb   = app.PackageMdb;
            bool   llvm_only    = app.EnableLLVMOnlyBitCode;
            string arch         = abi.AsArchString();

            args.Append("--debug ");

            if (enable_llvm)
            {
                args.Append("--llvm ");
            }

            if (!llvm_only)
            {
                args.Append("-O=gsharedvt ");
            }
            args.Append(aot_other_args).Append(" ");
            args.Append("--aot=mtriple=");
            args.Append(enable_thumb ? arch.Replace("arm", "thumb") : arch);
            args.Append("-ios,");
            args.Append("data-outfile=").Append(Quote(dataFile)).Append(",");
            args.Append(aot_args);
            if (llvm_only)
            {
                args.Append("llvmonly,");
            }
            else
            {
                args.Append("full,");
            }

            //var sdk_or_product = Profile.IsSdkAssembly (aname) || Profile.IsProductAssembly (aname);
            var sdk_or_product = false;

            if (enable_llvm)
            {
                args.Append("nodebug,");
            }
            else if (!(enable_debug || enable_mdb))
            {
                args.Append("nodebug,");
            }
            else if (debug_all || debug_assemblies.Contains(fname) || !sdk_or_product)
            {
                args.Append("soft-debug,");
            }

            args.Append("dwarfdebug,");

            /* Needed for #4587 */
            if (enable_debug && !enable_llvm)
            {
                args.Append("no-direct-calls,");
            }

            if (!app.UseDlsym(filename))
            {
                args.Append("direct-pinvoke,");
            }

            if (app.EnableMSym)
            {
                var msymdir = Quote(Path.Combine(outputDir, "Msym"));
                args.Append($"msym-dir={msymdir},");
            }

            //if (enable_llvm)
            //args.Append ("llvm-path=").Append (MonoTouchDirectory).Append ("/LLVM/bin/,");

            if (!llvm_only)
            {
                args.Append("outfile=").Append(Quote(outputFile));
            }
            if (!llvm_only && enable_llvm)
            {
                args.Append(",");
            }
            if (enable_llvm)
            {
                args.Append("llvm-outfile=").Append(Quote(llvmOutputFile));
            }
            args.Append(" \"").Append(filename).Append("\"");
            return(args.ToString());
        }
Exemple #12
0
        /*
         * Runs the AOT compiler, creating one of the following:
         *     [not llvm]     => .s           + .aotdata
         *     [is llvm-only] => .bc          + .aotdata
         *     [is llvm]      =>
         *          [is llvm creating assembly code] => .s + -llvm.s + .aotdata
         *          [is llvm creating object code]   => .s + -llvm.o + .aotdata
         */
        public void CreateAOTTask(Abi abi)
        {
            // Check if we've already created the AOT tasks.
            if (AotInfos.ContainsKey(abi))
            {
                return;
            }

            var assembly_path  = FullPath;
            var build_dir      = Path.GetDirectoryName(assembly_path);
            var arch           = abi.AsArchString();
            var asm_dir        = Path.Combine(App.Cache.Location, arch);
            var asm            = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + ".s";
            var data           = Path.Combine(asm_dir, Path.GetFileNameWithoutExtension(assembly_path)) + ".aotdata" + "." + arch;
            var llvm_aot_ofile = "";
            var asm_output     = "";
            var is_llvm        = (abi & Abi.LLVM) == Abi.LLVM;

            Directory.CreateDirectory(asm_dir);

            if (!File.Exists(assembly_path))
            {
                throw new MonoTouchException(3004, true, "Could not AOT the assembly '{0}' because it doesn't exist.", assembly_path);
            }

            var aotInfo = new AotInfo();

            AotInfos.Add(abi, aotInfo);

            if (App.EnableLLVMOnlyBitCode)
            {
                // In llvm-only mode, the AOT compiler emits a .bc file and no .s file for JITted code
                llvm_aot_ofile = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + ".bc";
                aotInfo.BitcodeFiles.Add(llvm_aot_ofile);
            }
            else if (is_llvm)
            {
                if (Driver.GetLLVMAsmWriter(App))
                {
                    llvm_aot_ofile = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + "-llvm.s";
                    aotInfo.AsmFiles.Add(llvm_aot_ofile);
                }
                else
                {
                    llvm_aot_ofile = Path.Combine(asm_dir, Path.GetFileName(assembly_path)) + "-llvm.o";
                    aotInfo.ObjectFiles.Add(llvm_aot_ofile);
                }
                asm_output = asm;
            }
            else
            {
                asm_output = asm;
            }

            if (!string.IsNullOrEmpty(asm_output))
            {
                aotInfo.AsmFiles.Add(asm_output);
            }
            aotInfo.AotDataFiles.Add(data);

            var aotCompiler = Driver.GetAotCompiler(App, Target.Is64Build);
            var aotArgs     = Driver.GetAotArguments(App, assembly_path, abi, build_dir, asm_output, llvm_aot_ofile, data);
            var task        = new AOTTask
            {
                Assembly                = this,
                AssemblyName            = assembly_path,
                AddBitcodeMarkerSection = BuildTarget != AssemblyBuildTarget.StaticObject && App.EnableMarkerOnlyBitCode,
                AssemblyPath            = asm,
                ProcessStartInfo        = Driver.CreateStartInfo(App, aotCompiler, aotArgs, Path.GetDirectoryName(assembly_path)),
                AotInfo = aotInfo,
            };

            aotInfo.Task = task;
        }
Exemple #13
0
        IEnumerable<BuildTask> CreateManagedToAssemblyTasks(string s, Abi abi, string build_dir)
        {
            var arch = abi.AsArchString ();
            var asm_dir = Cache.Location;
            var asm = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + ".s";
            var llvm_asm = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + "-llvm.s";
            var data = Path.Combine (asm_dir, Path.GetFileNameWithoutExtension (s)) + "." + arch + ".aotdata";
            string llvm_ofile, llvm_aot_ofile = "";
            var is_llvm = (abi & Abi.LLVM) == Abi.LLVM;
            bool assemble_llvm = is_llvm && Driver.LLVMAsmWriter;

            if (!File.Exists (s))
                throw new MonoTouchException (3004, true, "Could not AOT the assembly '{0}' because it doesn't exist.", s);

            HashSet<string> dependencies = null;
            List<string> deps = null;
            List<string> outputs = new List<string> ();
            var warnings = new List<Exception> ();

            dependencies = ComputeDependencies (warnings);

            if (warnings.Count > 0) {
                ErrorHelper.Show (warnings);
                ErrorHelper.Warning (3006, "Could not compute a complete dependency map for the project. This will result in slower build times because Xamarin.iOS can't properly detect what needs to be rebuilt (and what does not need to be rebuilt). Please review previous warnings for more details.");
            } else {
                deps = new List<string> (dependencies.ToArray ());
                deps.Add (s);
                deps.Add (Driver.GetAotCompiler (Target.Is64Build));
            }

            if (App.EnableLLVMOnlyBitCode) {
                //
                // In llvm-only mode, the AOT compiler emits a .bc file and no .s file for JITted code
                //
                llvm_ofile = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + ".bc";
                outputs.Add (llvm_ofile);
                llvm_aot_ofile = llvm_ofile;
            } else {
                llvm_ofile = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + "-llvm.o";
                outputs.Add (asm);

                if (is_llvm) {
                    if (assemble_llvm) {
                        llvm_aot_ofile = llvm_asm;
                    } else {
                        llvm_aot_ofile = llvm_ofile;
                        Target.LinkWith (llvm_ofile);
                    }
                    outputs.Add (llvm_aot_ofile);
                }
            }

            if (deps != null && Application.IsUptodate (deps, outputs)) {
                Driver.Log (3, "Target {0} is up-to-date.", asm);
                if (App.EnableLLVMOnlyBitCode)
                    return CreateCompileTasks (s, null, llvm_ofile, abi);
                else
                    return CreateCompileTasks (s, asm, assemble_llvm ? llvm_asm : null, abi);
            } else {
                Application.TryDelete (asm); // otherwise the next task might not detect that it will have to rebuild.
                Application.TryDelete (llvm_asm);
                Application.TryDelete (llvm_ofile);
                Driver.Log (3, "Target {0} needs to be rebuilt.", asm);
            }

            var aotCompiler = Driver.GetAotCompiler (Target.Is64Build);
            var aotArgs = Driver.GetAotArguments (s, abi, build_dir, asm, llvm_aot_ofile, data);
            Driver.Log (3, "Aot compiler: {0} {1}", aotCompiler, aotArgs);

            AotDataFiles.Add (data);

            IEnumerable<BuildTask> nextTasks;
            if (App.EnableLLVMOnlyBitCode)
                nextTasks = CreateCompileTasks (s, null, llvm_ofile, abi);
            else
                nextTasks = CreateCompileTasks (s, asm, assemble_llvm ? llvm_asm : null, abi);

            return new BuildTask [] { new AOTTask ()
                {
                    AssemblyName = s,
                    ProcessStartInfo = Driver.CreateStartInfo (aotCompiler, aotArgs, Path.GetDirectoryName (s), App.EnableMSym ? "gen-compact-seq-points" : null),
                    NextTasks = nextTasks
                }
            };
        }
Exemple #14
0
        public static IList <string> GetAotArguments(Application app, string filename, Abi abi, string outputDir, string outputFile, string llvmOutputFile, string dataFile)
        {
            string fname                = Path.GetFileName(filename);
            var    args                 = new List <string> ();
            bool   enable_llvm          = (abi & Abi.LLVM) != 0;
            bool   enable_thumb         = (abi & Abi.Thumb) != 0;
            bool   enable_debug         = app.EnableDebug;
            bool   enable_debug_symbols = app.PackageManagedDebugSymbols;
            bool   llvm_only            = app.EnableLLVMOnlyBitCode;
            bool   interp               = app.IsInterpreted(Assembly.GetIdentity(filename));
            bool   interp_full          = !interp && app.UseInterpreter;
            bool   is32bit              = (abi & Abi.Arch32Mask) > 0;
            string arch                 = abi.AsArchString();

            args.Add("--debug");

            if (enable_llvm)
            {
                args.Add("--llvm");
            }

            if (!llvm_only && !interp)
            {
                args.Add("-O=gsharedvt");
            }
            if (app.AotOtherArguments != null)
            {
                args.AddRange(app.AotOtherArguments);
            }
            var aot = new StringBuilder();

            aot.Append("--aot=mtriple=");
            aot.Append(enable_thumb ? arch.Replace("arm", "thumb") : arch);
            aot.Append("-ios,");
            aot.Append("data-outfile=").Append(dataFile).Append(",");
            aot.Append(app.AotArguments);
            if (llvm_only)
            {
                aot.Append("llvmonly,");
            }
            else if (interp)
            {
                if (fname != "mscorlib.dll")
                {
                    throw ErrorHelper.CreateError(99, Errors.MX0099, fname);
                }
                aot.Append("interp,");
            }
            else if (interp_full)
            {
                aot.Append("interp,full,");
            }
            else
            {
                aot.Append("full,");
            }

            var aname          = Path.GetFileNameWithoutExtension(fname);
            var sdk_or_product = Profile.IsSdkAssembly(aname) || Profile.IsProductAssembly(aname);

            if (enable_llvm)
            {
                aot.Append("nodebug,");
            }
            else if (!(enable_debug || enable_debug_symbols))
            {
                aot.Append("nodebug,");
            }
            else if (app.DebugAll || app.DebugAssemblies.Contains(fname) || !sdk_or_product)
            {
                aot.Append("soft-debug,");
            }

            aot.Append("dwarfdebug,");

            /* Needed for #4587 */
            if (enable_debug && !enable_llvm)
            {
                aot.Append("no-direct-calls,");
            }

            if (!app.UseDlsym(filename))
            {
                aot.Append("direct-pinvoke,");
            }

            if (app.EnableMSym)
            {
                var msymdir = Path.Combine(outputDir, "Msym");
                aot.Append($"msym-dir={msymdir},");
            }

            if (enable_llvm)
            {
                aot.Append("llvm-path=").Append(GetFrameworkCurrentDirectory(app)).Append("/LLVM/bin/,");
            }

            aot.Append("outfile=").Append(outputFile);
            if (enable_llvm)
            {
                aot.Append(",llvm-outfile=").Append(llvmOutputFile);
            }
            args.Add(aot.ToString());
            args.Add(filename);
            return(args);
        }
Exemple #15
0
		// note: this is executed under Parallel.ForEach
		public static string GenerateMain (IEnumerable<Assembly> assemblies, string assembly_name, Abi abi, string main_source, IList<string> registration_methods)
		{
			var assembly_externs = new StringBuilder ();
			var assembly_aot_modules = new StringBuilder ();
			var register_assemblies = new StringBuilder ();
			var enable_llvm = (abi & Abi.LLVM) != 0;

			foreach (var s in assemblies) {
				if ((abi & Abi.SimulatorArchMask) == 0) {
					var info = s.AssemblyDefinition.Name.Name;
					info = EncodeAotSymbol (info);
					assembly_externs.Append ("extern void *mono_aot_module_").Append (info).AppendLine ("_info;");
					assembly_aot_modules.Append ("\tmono_aot_register_module (mono_aot_module_").Append (info).AppendLine ("_info);");
				}
				string sname = s.FileName;
				if (assembly_name != sname && IsBoundAssembly (s))
					register_assemblies.Append ("\txamarin_open_and_register (\"").Append (sname).Append ("\");").AppendLine ();
			}

			try {
				StringBuilder sb = new StringBuilder ();
				using (var sw = new StringWriter (sb)) {
					sw.WriteLine ("#include \"xamarin/xamarin.h\"");
					// Trial builds are only executable in the next 24 hours
					
					sw.WriteLine ();
					sw.WriteLine (assembly_externs);

					sw.WriteLine ("void xamarin_register_modules_impl ()");
					sw.WriteLine ("{");
					sw.WriteLine (assembly_aot_modules);
					sw.WriteLine ("}");
					sw.WriteLine ();

					sw.WriteLine ("void xamarin_register_assemblies_impl ()");
					sw.WriteLine ("{");
					sw.WriteLine (register_assemblies);
					sw.WriteLine ("}");
					sw.WriteLine ();

					if (registration_methods != null) {
						foreach (var method in registration_methods) {
							sw.Write ("void ");
							sw.Write (method);
							sw.WriteLine ("();");
						}
					}
					sw.WriteLine ("void xamarin_setup_impl ()");
					sw.WriteLine ("{");

					if (App.EnableLLVMOnlyBitCode)
						sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY);");

					if (app.Registrar == RegistrarMode.LegacyDynamic || app.Registrar == RegistrarMode.LegacyStatic)
						sw.WriteLine ("\txamarin_use_old_dynamic_registrar = TRUE;");
					else
						sw.WriteLine ("\txamarin_use_old_dynamic_registrar = FALSE;");

					if (registration_methods != null) {
						for (int i = 0; i < registration_methods.Count; i++) {
							sw.Write ("\t");
							sw.Write (registration_methods [i]);
							sw.WriteLine ("();");
						}
					}

					if (app.EnableDebug)
						sw.WriteLine ("\txamarin_gc_pump = {0};", debug_track.Value ? "TRUE" : "FALSE");
					sw.WriteLine ("\txamarin_init_mono_debug = {0};", app.PackageMdb ? "TRUE" : "FALSE");
					sw.WriteLine ("\txamarin_compact_seq_points = {0};", app.EnableMSym ? "TRUE" : "FALSE");
					sw.WriteLine ("\txamarin_executable_name = \"{0}\";", assembly_name);
					sw.WriteLine ("\txamarin_use_new_assemblies = {0};", app.IsUnified ? "1" : "0");
					sw.WriteLine ("\tmono_use_llvm = {0};", enable_llvm ? "TRUE" : "FALSE");
					sw.WriteLine ("\txamarin_log_level = {0};", verbose);
					sw.WriteLine ("\txamarin_arch_name = \"{0}\";", abi.AsArchString ());
					if (app.EnableDebug)
						sw.WriteLine ("\txamarin_debug_mode = TRUE;");
					if (!string.IsNullOrEmpty (app.MonoGCParams))
						sw.WriteLine ("\tsetenv (\"MONO_GC_PARAMS\", \"{0}\", 1);", app.MonoGCParams);
					foreach (var kvp in environment_variables)
						sw.WriteLine ("\tsetenv (\"{0}\", \"{1}\", 1);", kvp.Key.Replace ("\"", "\\\""), kvp.Value.Replace ("\"", "\\\""));
					sw.WriteLine ("}");
					sw.WriteLine ();
					sw.Write ("int ");
					sw.Write (app.IsWatchExtension ? "xamarin_watchextension_main" : "main");
					sw.WriteLine (" (int argc, char **argv)");
					sw.WriteLine ("{");
					sw.WriteLine ("\tNSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];");
					if (app.IsExtension) {
						// the name of the executable must be the bundle id (reverse dns notation)
						// but we do not want to impose that (ugly) restriction to the managed .exe / project name / ...
						sw.WriteLine ("\targv [0] = \"{0}\";", Path.GetFileNameWithoutExtension (app.RootAssembly));
						sw.WriteLine ("\tint rv = xamarin_main (argc, argv, true);");
					} else {
						sw.WriteLine ("\tint rv = xamarin_main (argc, argv, false);");
					}
					sw.WriteLine ("\t[pool drain];");
					sw.WriteLine ("\treturn rv;");
					sw.WriteLine ("}");

					sw.WriteLine ("void xamarin_initialize_callbacks () __attribute__ ((constructor));");
					sw.WriteLine ("void xamarin_initialize_callbacks ()");
					sw.WriteLine ("{");
					sw.WriteLine ("\txamarin_setup = xamarin_setup_impl;");
					sw.WriteLine ("\txamarin_register_assemblies = xamarin_register_assemblies_impl;");
					sw.WriteLine ("\txamarin_register_modules = xamarin_register_modules_impl;");
					sw.WriteLine ("}");

				}
				WriteIfDifferent (main_source, sb.ToString ());
			} catch (MonoTouchException) {
				throw;
			} catch (Exception e) {
				throw new MonoTouchException (4001, true, e, "The main template could not be expanded to `{0}`.", main_source);
			}

			return main_source;
		}
Exemple #16
0
		public static string GetAotArguments (string filename, Abi abi, string outputDir, string outputFile, string llvmOutputFile, string dataFile)
		{
			string fname = Path.GetFileName (filename);
			StringBuilder args = new StringBuilder ();
			bool enable_llvm = (abi & Abi.LLVM) != 0;
			bool enable_thumb = (abi & Abi.Thumb) != 0;
			bool enable_debug = app.EnableDebug;
			bool enable_mdb = app.PackageMdb;
			bool llvm_only = app.EnableLLVMOnlyBitCode;
			string arch = abi.AsArchString ();

			args.Append ("--debug ");

			if (enable_llvm)
				args.Append ("--llvm ");

			if (!llvm_only)
				args.Append ("-O=gsharedvt ");
			args.Append (aot_other_args).Append (" ");
			args.Append ("--aot=mtriple=");
			args.Append (enable_thumb ? arch.Replace ("arm", "thumb") : arch);
			args.Append ("-ios,");
			args.Append ("data-outfile=").Append (Quote (dataFile)).Append (",");
			args.Append (aot_args);
			if (llvm_only)
				args.Append ("llvmonly,");
			else
				args.Append ("full,");

			var aname = Path.GetFileNameWithoutExtension (fname);
			var sdk_or_product = Profile.IsSdkAssembly (aname) || Profile.IsProductAssembly (aname);

			if (enable_llvm)
				args.Append ("nodebug,");
			else if (!(enable_debug || enable_mdb))
				args.Append ("nodebug,");
			else if (debug_all || debug_assemblies.Contains (fname) || !sdk_or_product)
				args.Append ("soft-debug,");

			args.Append ("dwarfdebug,");

			/* Needed for #4587 */
			if (enable_debug && !enable_llvm)
				args.Append ("no-direct-calls,");

			if (!app.UseDlsym (filename))
				args.Append ("direct-pinvoke,");

			if (app.EnableMSym)
				args.Append ("gen-seq-points-file,");

			if (enable_llvm)
				args.Append ("llvm-path=").Append (MonoTouchDirectory).Append ("/LLVM/bin/,");

			if (!llvm_only)
				args.Append ("outfile=").Append (Quote (outputFile));
			if (!llvm_only && enable_llvm)
				args.Append (",");
			if (enable_llvm)
				args.Append ("llvm-outfile=").Append (Quote (llvmOutputFile));
			args.Append (" \"").Append (filename).Append ("\"");
			return args.ToString ();
		}