Exemple #1
0
 public MonoTouchException(int code, bool error, Exception innerException, string message, params object[] args) :
     base(String.Format(message, args), innerException)
 {
     Code  = code;
     Error = error || ErrorHelper.GetWarningLevel(code) == ErrorHelper.WarningLevel.Error;
 }
Exemple #2
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5103, Errors.MT5103_A, string.Join("', '", CompilerFlags.SourceFiles.ToArray()));
 }
Exemple #3
0
        IEnumerable <BuildTask> CreateManagedToAssemblyTasks(string s, Abi abi, string build_dir)
        {
            var    arch = abi.AsArchString();
            var    asm_dir = App.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.GetLLVMAsmWriter(App);

            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(App, 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(App, Target.Is64Build);
            var aotArgs     = Driver.GetAotArguments(App, 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,
                                          AddBitcodeMarkerSection = App.FastDev && App.EnableMarkerOnlyBitCode,
                                          AssemblyPath = asm,
                                          ProcessStartInfo = Driver.CreateStartInfo(App, aotCompiler, aotArgs, Path.GetDirectoryName(s)),
                                          NextTasks = nextTasks
                                      } });
        }
Exemple #4
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(4109, "Failed to compile the generated registrar code. Please file a bug report at https://github.com/xamarin/xamarin-macios/issues/new");
 }
Exemple #5
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5216, Errors.MT5216, OutputFile);
 }
Exemple #6
0
        // Checks if any of the source files have a time stamp later than any of the target files.
        //
        // If check_stamp is true, the function will use the timestamp of a "target".stamp file
        // if it's later than the timestamp of the "target" file itself.
        public static bool IsUptodate(IEnumerable <string> sources, IEnumerable <string> targets, bool check_stamp = true)
        {
            if (Driver.Force)
            {
                return(false);
            }

            DateTime max_source = DateTime.MinValue;
            string   max_s      = null;

            if (sources.Count() == 0 || targets.Count() == 0)
            {
                ErrorHelper.Error(1013, "Dependency tracking error: no files to compare. Please file a bug report at http://bugzilla.xamarin.com with a test case.");
            }

            foreach (var s in sources)
            {
                var sfi = new FileInfo(s);
                if (!sfi.Exists)
                {
                    Driver.Log(3, "Prerequisite '{0}' does not exist.", s);
                    return(false);
                }

                var st = sfi.LastWriteTimeUtc;
                if (st > max_source)
                {
                    max_source = st;
                    max_s      = s;
                }
            }


            foreach (var t in targets)
            {
                var tfi = new FileInfo(t);
                if (!tfi.Exists)
                {
                    Driver.Log(3, "Target '{0}' does not exist.", t);
                    return(false);
                }

                if (check_stamp)
                {
                    var tfi_stamp = new FileInfo(t + ".stamp");
                    if (tfi_stamp.Exists && tfi_stamp.LastWriteTimeUtc > tfi.LastWriteTimeUtc)
                    {
                        Driver.Log(3, "Target '{0}' has a stamp file with newer timestamp ({1} > {2}), using the stamp file's timestamp", t, tfi_stamp.LastWriteTimeUtc, tfi.LastWriteTimeUtc);
                        tfi = tfi_stamp;
                    }
                }

                var lwt = tfi.LastWriteTimeUtc;
                if (max_source > lwt)
                {
                    Driver.Log(3, "Prerequisite '{0}' is newer than target '{1}' ({2} vs {3}).", max_s, t, max_source, lwt);
                    return(false);
                }
            }

            Driver.Log(3, "Prerequisite(s) '{0}' are all older than the target(s) '{1}'.", string.Join("', '", sources.ToArray()), string.Join("', '", targets.ToArray()));

            return(true);
        }
Exemple #7
0
        public void RunRegistrar()
        {
            // The static registrar.
            if (Registrar != RegistrarMode.Static)
            {
                throw new PlatformException(67, "Invalid registrar: {0}", Registrar);                  // this is only called during our own build
            }
            if (RootAssemblies.Count < 1)
            {
                throw ErrorHelper.CreateError(130, "No root assemblies found. You should provide at least one root assembly.");
            }

            var registrar_m        = RegistrarOutputLibrary;
            var RootAssembly       = RootAssemblies [0];
            var resolvedAssemblies = new Dictionary <string, AssemblyDefinition> ();
            var resolver           = new PlatformResolver()
            {
                FrameworkDirectory = Driver.GetPlatformFrameworkDirectory(this),
                RootDirectory      = Path.GetDirectoryName(RootAssembly),
            };

#if MMP
            resolver.RecursiveSearchDirectories.AddRange(Driver.RecursiveSearchDirectories);
#endif

            if (Platform == ApplePlatform.iOS || Platform == ApplePlatform.MacOSX)
            {
                if (Is32Build)
                {
                    resolver.ArchDirectory = Driver.GetArch32Directory(this);
                }
                else
                {
                    resolver.ArchDirectory = Driver.GetArch64Directory(this);
                }
            }

            var ps = new ReaderParameters();
            ps.AssemblyResolver = resolver;
            resolvedAssemblies.Add("mscorlib", ps.AssemblyResolver.Resolve(AssemblyNameReference.Parse("mscorlib"), new ReaderParameters()));

            var  productAssembly      = Driver.GetProductAssembly(this);
            bool foundProductAssembly = false;
            foreach (var asm in RootAssemblies)
            {
                var rootName = Path.GetFileNameWithoutExtension(asm);
                if (rootName == productAssembly)
                {
                    foundProductAssembly = true;
                }

                try {
                    AssemblyDefinition lastAssembly = ps.AssemblyResolver.Resolve(AssemblyNameReference.Parse(rootName), new ReaderParameters());
                    if (lastAssembly == null)
                    {
                        ErrorHelper.CreateWarning(7, "The root assembly '{0}' does not exist", rootName);
                        continue;
                    }

                    if (resolvedAssemblies.TryGetValue(rootName, out var previousAssembly))
                    {
                        if (lastAssembly.MainModule.RuntimeVersion != previousAssembly.MainModule.RuntimeVersion)
                        {
                            Driver.Log(2, "Attemping to load an assembly another time {0} (previous {1})", lastAssembly.FullName, previousAssembly.FullName);
                        }
                        continue;
                    }

                    resolvedAssemblies.Add(rootName, lastAssembly);
                    Driver.Log(3, "Loaded {0}", lastAssembly.MainModule.FileName);
                } catch (Exception ex) {
                    ErrorHelper.Warning(9, ex, "Error while loading assemblies: {0}: {1}", rootName, ex.Message);
                    continue;
                }
            }

            if (!foundProductAssembly)
            {
                throw ErrorHelper.CreateError(131, "Product assembly '{0}' not found in assembly list: '{1}'", productAssembly, string.Join("', '", RootAssemblies.ToArray()));
            }

#if MONOTOUCH
            BuildTarget = BuildTarget.Simulator;
#endif
            var registrar = new Registrar.StaticRegistrar(this);
            if (RootAssemblies.Count == 1)
            {
                registrar.GenerateSingleAssembly(resolvedAssemblies.Values, Path.ChangeExtension(registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension(RootAssembly));
            }
            else
            {
                registrar.Generate(resolvedAssemblies.Values, Path.ChangeExtension(registrar_m, "h"), registrar_m);
            }
        }
        public void Convert()
        {
            Driver.Log(3, "Converting '{0}' to bitcode file {1}.", input, outputFile);

            var reader = new StreamReader(input);
            var writer = new StreamWriter(outputFile);

            writer.WriteLine("; ModuleID = '{0}'", input);

            //This is for x86_64
            switch (platform)
            {
            case ApplePlatform.TVOS:
                if ((abi & Abi.ARM64) != 0)
                {
                    writer.WriteLine("target datalayout = \"e-m:o-i64:64-i128:128-n32:64-S128\"");
                    writer.Write("target triple = \"arm64-apple-tvos");
                }
                else if ((abi & Abi.x86_64) != 0)
                {
                    writer.WriteLine("target datalayout = \"e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128\"");
                    //not 100% of this one (below)
                    writer.Write("target triple = \"x86_64-apple-tvos");
                }
                else
                {
                    throw ErrorHelper.CreateError(1301, "Unsupported TvOS ABI: {0}.", abi);
                }
                writer.Write(deployment_target.Major);
                writer.Write('.');
                writer.Write(deployment_target.Minor);
                writer.Write('.');
                writer.Write(deployment_target.Revision < 0 ? 0 : deployment_target.Revision);
                writer.WriteLine('"');
                break;

            default:
                throw ErrorHelper.CreateError(1300, "Unsupported bitcode platform: {0}.", platform);
            }


            writer.WriteLine("!llvm.module.flags = !{!0}");
            writer.WriteLine("!llvm.ident = !{!1}");
            writer.WriteLine("!0 = !{i32 1, !\"PIC Level\", i32 2}");
            writer.WriteLine("!1 = !{!\"Apple LLVM version 7.0.0 (clang-700.0.72)\"}");
            writer.WriteLine();

            string s;
            int    line = 0;

            while ((s = reader.ReadLine()) != null)
            {
                ++line;
                s = s.Trim();
                if (s.Length == 0)
                {
                    continue;
                }

                if (s.StartsWith(".asciz") || s.StartsWith(".ascii"))
                {
                    s = FixAsciz(s, line);
                }
                else if (s.Contains("\""))
                {
                    s = s.Replace("\"", "\\22");
                }

                writer.WriteLine("module asm \"{0}\"", s);
            }
            reader.Close();
            writer.Close();
        }
Exemple #9
0
        public void GatherFrameworks()
        {
            Assembly asm = null;

            foreach (var assembly in Assemblies)
            {
                if (assembly.AssemblyDefinition.Name.Name == Driver.GetProductAssembly(App))
                {
                    asm = assembly;
                    break;
                }
            }

            if (asm == null)
            {
                throw ErrorHelper.CreateError(99, Errors.MX0099, $"could not find the product assembly {Driver.GetProductAssembly(App)} in the list of assemblies referenced by the executable");
            }

            AssemblyDefinition productAssembly = asm.AssemblyDefinition;

            // *** make sure any change in the above lists (or new list) are also reflected in
            // *** Makefile so simlauncher-sgen does not miss any framework

            HashSet <string> processed = new HashSet <string> ();

#if !MONOMAC
            Version v80 = new Version(8, 0);
#endif

            foreach (ModuleDefinition md in productAssembly.Modules)
            {
                foreach (TypeDefinition td in md.Types)
                {
                    // process only once each namespace (as we keep adding logic below)
                    string nspace = td.Namespace;
                    if (processed.Contains(nspace))
                    {
                        continue;
                    }
                    processed.Add(nspace);

                    Framework framework;
                    if (Driver.GetFrameworks(App).TryGetValue(nspace, out framework))
                    {
                        // framework specific processing
                        switch (framework.Name)
                        {
#if MONOMAC
                        case "QTKit":
                            // we already warn in Frameworks.cs Gather method
                            if (!Driver.LinkProhibitedFrameworks)
                            {
                                continue;
                            }
                            break;
#else
                        case "CoreAudioKit":
                            // CoreAudioKit seems to be functional in the iOS 9 simulator.
                            if (App.IsSimulatorBuild && App.SdkVersion.Major < 9)
                            {
                                continue;
                            }
                            break;

                        case "Metal":
                        case "MetalKit":
                        case "MetalPerformanceShaders":
                        case "CoreNFC":
                            // some frameworks do not exists on simulators and will result in linker errors if we include them
                            if (App.IsSimulatorBuild)
                            {
                                continue;
                            }
                            break;

                        case "DeviceCheck":
                            if (App.IsSimulatorBuild && App.SdkVersion.Major < 13)
                            {
                                continue;
                            }
                            break;

                        case "PushKit":
                            // in Xcode 6 beta 7 this became an (ld) error - it was a warning earlier :(
                            // ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later (@rpath/PushKit.framework/PushKit) for architecture armv7
                            // this was fixed in Xcode 6.2 (6.1 was still buggy) see #29786
                            if ((App.DeploymentTarget < v80) && (Driver.XcodeVersion < new Version(6, 2)))
                            {
                                ErrorHelper.Warning(49, Errors.MT0049, framework.Name);
                                continue;
                            }
                            break;

                        case "WatchKit":
                            // Xcode 11 doesn't ship WatchKit for iOS
                            if (Driver.XcodeVersion.Major == 11 && App.Platform == ApplePlatform.iOS)
                            {
                                ErrorHelper.Warning(5219, Errors.MT5219);
                                continue;
                            }
                            break;
#endif
                        }

                        if (App.SdkVersion >= framework.Version)
                        {
                            var add_to = framework.AlwaysWeakLinked || App.DeploymentTarget < framework.Version ? asm.WeakFrameworks : asm.Frameworks;
                            add_to.Add(framework.Name);
                            continue;
                        }
                        else
                        {
                            Driver.Log(3, "Not linking with the framework {0} (used by the type {1}) because it was introduced in {2} {3}, and we're using the {2} {4} SDK.", framework.Name, td.FullName, App.PlatformName, framework.Version, App.SdkVersion);
                        }
                    }
                }
            }

            // Make sure there are no duplicates between frameworks and weak frameworks.
            // Keep the weak ones.
            asm.Frameworks.ExceptWith(asm.WeakFrameworks);
        }
Exemple #10
0
 protected virtual void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5106, "Could not compile the file(s) '{0}'. Please file a bug report at https://github.com/xamarin/xamarin-macios/issues/new", string.Join("', '", CompilerFlags.SourceFiles.ToArray()));
 }
        string FixAsciz(string s, int line)
        {
            bool first = true;
            var  m     = Regex.Match(s, "^.asci(i|z)\\s*\"(.*)\"$");

            if (!m.Success)
            {
                return(s);
            }
            var str = m.Groups [2].Value;

            var res = new StringBuilder(str.Length * 3);

            res.Append(".byte ");
            /* it's a regular C string, parse time! */
            for (int i = 0; i < str.Length; ++i)
            {
                int to_append = 0;
                if (str [i] == '\\')
                {
                    ++i;
                    if (i >= str.Length)
                    {
                        throw ErrorHelper.CreateError(1302, "Invalid escape sequence when converting .s to .ll, \\ as the last characted in {0}:{1}.", input, line);
                    }
                    switch (str [i])
                    {
                    case 'b':
                        to_append = 0x8;
                        break;

                    case 'f':
                        to_append = 0xc;
                        break;

                    case 'n':
                        to_append = 0xa;
                        break;

                    case 'r':
                        to_append = 0xd;
                        break;

                    case 't':
                        to_append = 9;
                        break;

                    case '\"':
                    case '\\':
                        to_append = str [i];
                        break;

                    case 'x':
                    case 'X':
                        ++i;
                        if (!ParseHex(str, ref i, ref to_append))
                        {
                            throw ErrorHelper.CreateError(1302, "Invalid escape sequence when converting .s to .ll, bad hex escape in {0}:{1}.", input, line);
                        }

                        break;

                    default:
                        if (IsDigit(str [i]))
                        {
                            string error_msg = null;
                            if (!ParseOctal(str, ref i, ref to_append, ref error_msg))
                            {
                                throw ErrorHelper.CreateError(1302, "Invalid escape sequence when converting .s to .ll, bad octal escape in {0}:{1} due to {2}.", input, line, error_msg);
                            }
                        }
                        else
                        {
                            to_append = str [i];                             // "\K" is the same as "K"
                        }
                        break;
                    }
                }
                else
                {
                    to_append = str [i];
                }

                if (!first)
                {
                    res.Append(", ");
                }
                first = false;
                res.Append(to_append.ToString());
            }

            if (s.StartsWith(".asciz"))
            {
                if (!first)
                {
                    res.Append(", ");
                }
                res.Append("0");
            }
            return(res.ToString());
        }
Exemple #12
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5216, "Native linking failed for '{0}'. Please file a bug report at https://github.com/xamarin/xamarin-macios/issues/new", OutputFile);
 }
Exemple #13
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(4002, "Failed to compile the generated code for P/Invoke methods. Please file a bug report at https://github.com/xamarin/xamarin-macios/issues/new");
 }
Exemple #14
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(Target.Executable);
            }
            Driver.Watch("Native Link", 1);
        }
Exemple #15
0
        List <string> GetFilesToAOT(IFileEnumerator files)
        {
            // Make a dictionary of included/excluded files to track if we've missed some at the end
            Dictionary <string, bool> includedAssemblies = new Dictionary <string, bool> ();

            foreach (var item in options.IncludedAssemblies)
            {
                includedAssemblies [item] = false;
            }

            Dictionary <string, bool> excludedAssemblies = new Dictionary <string, bool> ();

            foreach (var item in options.ExcludedAssemblies)
            {
                excludedAssemblies [item] = false;
            }

            var aotFiles = new List <string> ();

            foreach (var file in files.Files)
            {
                string fileName  = Path.GetFileName(file);
                string extension = Path.GetExtension(file);
                if (extension != ".exe" && extension != ".dll")
                {
                    continue;
                }

                if (excludedAssemblies.ContainsKey(fileName))
                {
                    excludedAssemblies [fileName] = true;
                    continue;
                }

                if (includedAssemblies.ContainsKey(fileName))
                {
                    includedAssemblies [fileName] = true;
                    aotFiles.Add(file);
                    continue;
                }

                switch (options.CompilationType)
                {
                case AOTCompilationType.All:
                    aotFiles.Add(file);
                    break;

                case AOTCompilationType.SDK:
                    string fileNameNoExtension = Path.GetFileNameWithoutExtension(fileName);
                    if (Profile.IsSdkAssembly(fileNameNoExtension) || fileName == "Xamarin.Mac.dll")
                    {
                        aotFiles.Add(file);
                    }
                    break;

                case AOTCompilationType.Core:
                    if (fileName == "Xamarin.Mac.dll" || fileName == "System.dll" || fileName == "mscorlib.dll")
                    {
                        aotFiles.Add(file);
                    }
                    break;

                case AOTCompilationType.Explicit:
                    break;                     // In explicit, only included includedAssemblies included

                default:
                    throw ErrorHelper.CreateError(0099, "Internal error \"GetFilesToAOT with aot: {0}\" Please file a bug report with a test case (http://bugzilla.xamarin.com).", options.CompilationType);
                }
            }

            var unusedIncludes = includedAssemblies.Where(pair => !pair.Value).Select(pair => pair.Key).ToList();

            if (unusedIncludes.Count > 0)
            {
                throw ErrorHelper.CreateError(3009, "AOT of '{0}' was requested but was not found", String.Join(" ", unusedIncludes));
            }

            var unusedExcludes = excludedAssemblies.Where(pair => !pair.Value).Select(pair => pair.Key).ToList();

            if (unusedExcludes.Count > 0)
            {
                throw ErrorHelper.CreateError(3010, "Exclusion of AOT of '{0}' was requested but was not found", String.Join(" ", unusedExcludes));
            }

            return(aotFiles);
        }
Exemple #16
0
        public void CollectAllSymbols()
        {
            if (dynamic_symbols != null)
            {
                return;
            }

            var cache_location = Path.Combine(App.Cache.Location, "entry-points.txt");

            if (cached_link)
            {
                dynamic_symbols = new Symbols();
                dynamic_symbols.Load(cache_location, this);
            }
            else
            {
                if (LinkContext == null)
                {
                    // This happens when using the simlauncher and the msbuild tasks asked for a list
                    // of symbols (--symbollist). In that case just produce an empty list, since the
                    // binary shouldn't end up stripped anyway.
                    dynamic_symbols = new Symbols();
                }
                else
                {
                    dynamic_symbols = LinkContext.RequiredSymbols;
                }

                // keep the debugging helper in debugging binaries only
                var has_mono_pmip = App.EnableDebug;
#if MMP
                has_mono_pmip &= !Driver.IsUnifiedFullSystemFramework;
#endif
                if (has_mono_pmip)
                {
                    dynamic_symbols.AddFunction("mono_pmip");
                }

                bool has_dyn_msgSend;
#if MONOTOUCH
                has_dyn_msgSend = App.IsSimulatorBuild;
#else
                has_dyn_msgSend = App.MarshalObjectiveCExceptions != MarshalObjectiveCExceptionMode.Disable && !App.RequiresPInvokeWrappers && Is64Build;
#endif

                if (has_dyn_msgSend)
                {
                    dynamic_symbols.AddFunction("xamarin_dyn_objc_msgSend");
                    dynamic_symbols.AddFunction("xamarin_dyn_objc_msgSendSuper");
                    dynamic_symbols.AddFunction("xamarin_dyn_objc_msgSend_stret");
                    dynamic_symbols.AddFunction("xamarin_dyn_objc_msgSendSuper_stret");
                }

#if MONOTOUCH
                if (App.EnableProfiling && App.LibProfilerLinkMode == AssemblyBuildTarget.StaticObject)
                {
                    dynamic_symbols.AddFunction("mono_profiler_init_log");
                }
#endif

                dynamic_symbols.Save(cache_location);
            }

            foreach (var name in App.IgnoredSymbols)
            {
                var symbol = dynamic_symbols.Find(name);
                if (symbol == null)
                {
                    ErrorHelper.Warning(5218, Errors.MT5218, StringUtils.Quote(name));
                }
                else
                {
                    symbol.Ignore = true;
                }
            }
        }
Exemple #17
0
        public void InitializeCommon()
        {
            SelectRegistrar();
            foreach (var target in Targets)
            {
                target.SelectMonoNative();
            }

            if (RequiresXcodeHeaders && SdkVersion < SdkVersions.GetVersion(Platform))
            {
                throw ErrorHelper.CreateError(91, Errors.MX0091, ProductName, PlatformName, SdkVersions.GetVersion(Platform), SdkVersions.Xcode, Error91LinkerSuggestion);
            }

            if (DeploymentTarget != null)
            {
                if (DeploymentTarget < Xamarin.SdkVersions.GetMinVersion(Platform))
                {
                    throw new PlatformException(73, true, Errors.MT0073, Constants.Version, DeploymentTarget, Xamarin.SdkVersions.GetMinVersion(Platform), PlatformName, ProductName);
                }
                if (DeploymentTarget > Xamarin.SdkVersions.GetVersion(Platform))
                {
                    throw new PlatformException(74, true, Errors.MX0074, Constants.Version, DeploymentTarget, Xamarin.SdkVersions.GetVersion(Platform), PlatformName, ProductName);
                }
            }

            if (Platform == ApplePlatform.WatchOS && EnableCoopGC.HasValue && !EnableCoopGC.Value)
            {
                throw ErrorHelper.CreateError(88, Errors.MT0088);
            }

            if (!EnableCoopGC.HasValue)
            {
                EnableCoopGC = Platform == ApplePlatform.WatchOS;
            }

            if (EnableCoopGC.Value)
            {
                switch (MarshalObjectiveCExceptions)
                {
                case MarshalObjectiveCExceptionMode.UnwindManagedCode:
                case MarshalObjectiveCExceptionMode.Disable:
                    throw ErrorHelper.CreateError(89, Errors.MT0089, "--marshal-objectivec-exceptions", MarshalObjectiveCExceptions.ToString().ToLowerInvariant());
                }
                switch (MarshalManagedExceptions)
                {
                case MarshalManagedExceptionMode.UnwindNativeCode:
                case MarshalManagedExceptionMode.Disable:
                    throw ErrorHelper.CreateError(89, Errors.MT0089, "--marshal-managed-exceptions", MarshalManagedExceptions.ToString().ToLowerInvariant());
                }
            }


            bool isSimulatorOrDesktopDebug = EnableDebug;

#if MTOUCH
            isSimulatorOrDesktopDebug &= IsSimulatorBuild;
#endif

            if (MarshalObjectiveCExceptions == MarshalObjectiveCExceptionMode.Default)
            {
                if (EnableCoopGC.Value || (Platform == ApplePlatform.MacOSX && EnableDebug))
                {
                    MarshalObjectiveCExceptions = MarshalObjectiveCExceptionMode.ThrowManagedException;
                }
                else
                {
                    MarshalObjectiveCExceptions = isSimulatorOrDesktopDebug ? MarshalObjectiveCExceptionMode.UnwindManagedCode : MarshalObjectiveCExceptionMode.Disable;
                }
            }

            if (MarshalManagedExceptions == MarshalManagedExceptionMode.Default)
            {
                if (EnableCoopGC.Value)
                {
                    MarshalManagedExceptions = MarshalManagedExceptionMode.ThrowObjectiveCException;
                }
                else
                {
                    MarshalManagedExceptions = isSimulatorOrDesktopDebug ? MarshalManagedExceptionMode.UnwindNativeCode : MarshalManagedExceptionMode.Disable;
                }
                IsDefaultMarshalManagedExceptionMode = true;
            }

            if (SymbolMode == SymbolMode.Default)
            {
#if MONOTOUCH
                SymbolMode = EnableBitCode ? SymbolMode.Code : SymbolMode.Linker;
#else
                SymbolMode = SymbolMode.Linker;
#endif
            }

#if MONOTOUCH
            if (EnableBitCode && SymbolMode != SymbolMode.Code)
            {
                // This is a warning because:
                // * The user will get a linker error anyway if they do this.
                // * I see it as quite unlikely that anybody will in fact try this (it must be manually set in the additional mtouch arguments).
                // * I find it more probable that Apple will remove the -u restriction, in which case someone might actually want to try this, and if it's a warning, we won't prevent it.
                ErrorHelper.Warning(115, Errors.MT0115);
            }
#endif

            Optimizations.Initialize(this);
        }
Exemple #18
0
        bool IsRequiredSymbol(Symbol symbol, Assembly single_assembly = null)
        {
            if (symbol.Ignore)
            {
                return(false);
            }

            // Check if this symbol is used in the assembly we're filtering to
            if (single_assembly != null && !symbol.Members.Any((v) => v.Module.Assembly == single_assembly.AssemblyDefinition))
            {
                return(false);                // nope, this symbol is not used in the assembly we're using as filter.
            }
#if MTOUCH
            // If we're code-sharing, the managed linker might have found symbols
            // that are not in any of the assemblies in the current app.
            // This occurs because the managed linker processes all the
            // assemblies for all the apps together, but when linking natively
            // we're only linking with the assemblies that actually go into the app.
            if (App.IsCodeShared && symbol.Assemblies.Count > 0)
            {
                // So if this is a symbol related to any assembly, make sure
                // at least one of those assemblies are in the current app.
                if (!symbol.Assemblies.Any((v) => Assemblies.Contains(v)))
                {
                    return(false);
                }
            }
#endif

            switch (symbol.Type)
            {
            case SymbolType.Field:
                return(true);

            case SymbolType.Function:
#if MTOUCH
                // functions are not required if they're used in an assembly which isn't using dlsym, and we're AOT-compiling.
                if (App.IsSimulatorBuild)
                {
                    return(true);
                }
                if (single_assembly != null)
                {
                    return(App.UseDlsym(single_assembly.FileName));
                }

                if (symbol.Members?.Any() == true)
                {
                    foreach (var member in symbol.Members)
                    {
                        if (App.UseDlsym(member.Module.FileName))
                        {
                            // If any assembly uses dlsym to reference this symbol, it's a required symbol that must be preserved,
                            // because otherwise stripping the binary will cause the symbol (but not the function itself) to be removed,
                            // preventing any assembly using dlsym to find it.
                            return(true);
                        }
                    }
                    // None of the members use dlsym (and we have at least one member), then we don't need to preserve the symbol.
                    return(false);
                }
#endif
                return(true);

            case SymbolType.ObjectiveCClass:
                // Objective-C classes are not required when we're using the static registrar and we're not compiling to shared libraries,
                // (because the registrar code is linked into the main app, but not each shared library,
                // so the registrar code won't keep symbols in the shared libraries).
                if (single_assembly != null)
                {
                    return(true);
                }
                return(App.Registrar != RegistrarMode.Static);

            default:
                throw ErrorHelper.CreateError(99, Errors.MX0099, $"invalid symbol type {symbol.Type} for symbol {symbol.Name}");
            }
        }
Exemple #19
0
        public void InitializeCommon()
        {
            SelectRegistrar();

            if (RequiresXcodeHeaders && SdkVersion < SdkVersions.GetVersion(Platform))
            {
                throw ErrorHelper.CreateError(91, "This version of {0} requires the {1} {2} SDK (shipped with Xcode {3}). Either upgrade Xcode to get the required header files or {4} (to try to avoid the new APIs).", ProductName, PlatformName, SdkVersions.GetVersion(Platform), SdkVersions.Xcode, Error91LinkerSuggestion);
            }

            if (DeploymentTarget != null)
            {
                if (DeploymentTarget < Xamarin.SdkVersions.GetMinVersion(Platform))
                {
                    throw new PlatformException(73, true, "{4} {0} does not support a deployment target of {1} for {3} (the minimum is {2}). Please select a newer deployment target in your project's Info.plist.", Constants.Version, DeploymentTarget, Xamarin.SdkVersions.GetMinVersion(Platform), PlatformName, ProductName);
                }
                if (DeploymentTarget > Xamarin.SdkVersions.GetVersion(Platform))
                {
                    throw new PlatformException(74, true, "{4} {0} does not support a deployment target of {1} for {3} (the maximum is {2}). Please select an older deployment target in your project's Info.plist or upgrade to a newer version of {4}.", Constants.Version, DeploymentTarget, Xamarin.SdkVersions.GetVersion(Platform), PlatformName, ProductName);
                }
            }

            if (Platform == ApplePlatform.WatchOS && EnableCoopGC.HasValue && !EnableCoopGC.Value)
            {
                throw ErrorHelper.CreateError(88, "The GC must be in cooperative mode for watchOS apps. Please remove the --coop:false argument to mtouch.");
            }

            if (!EnableCoopGC.HasValue)
            {
                EnableCoopGC = Platform == ApplePlatform.WatchOS;
            }

            if (EnableCoopGC.Value)
            {
                switch (MarshalObjectiveCExceptions)
                {
                case MarshalObjectiveCExceptionMode.UnwindManagedCode:
                case MarshalObjectiveCExceptionMode.Disable:
                    throw ErrorHelper.CreateError(89, "The option '{0}' cannot take the value '{1}' when cooperative mode is enabled for the GC.", "--marshal-objectivec-exceptions", MarshalObjectiveCExceptions.ToString().ToLowerInvariant());
                }
                switch (MarshalManagedExceptions)
                {
                case MarshalManagedExceptionMode.UnwindNativeCode:
                case MarshalManagedExceptionMode.Disable:
                    throw ErrorHelper.CreateError(89, "The option '{0}' cannot take the value '{1}' when cooperative mode is enabled for the GC.", "--marshal-managed-exceptions", MarshalManagedExceptions.ToString().ToLowerInvariant());
                }
            }


            bool isSimulatorOrDesktopDebug = EnableDebug;

#if MTOUCH
            isSimulatorOrDesktopDebug &= IsSimulatorBuild;
#endif

            if (MarshalObjectiveCExceptions == MarshalObjectiveCExceptionMode.Default)
            {
                if (EnableCoopGC.Value)
                {
                    MarshalObjectiveCExceptions = MarshalObjectiveCExceptionMode.ThrowManagedException;
                }
                else
                {
                    MarshalObjectiveCExceptions = isSimulatorOrDesktopDebug ? MarshalObjectiveCExceptionMode.UnwindManagedCode : MarshalObjectiveCExceptionMode.Disable;
                }
            }

            if (MarshalManagedExceptions == MarshalManagedExceptionMode.Default)
            {
                if (EnableCoopGC.Value)
                {
                    MarshalManagedExceptions = MarshalManagedExceptionMode.ThrowObjectiveCException;
                }
                else
                {
                    MarshalManagedExceptions = isSimulatorOrDesktopDebug ? MarshalManagedExceptionMode.UnwindNativeCode : MarshalManagedExceptionMode.Disable;
                }
                IsDefaultMarshalManagedExceptionMode = true;
            }

            if (SymbolMode == SymbolMode.Default)
            {
#if MONOTOUCH
                SymbolMode = EnableBitCode ? SymbolMode.Code : SymbolMode.Linker;
#else
                SymbolMode = SymbolMode.Linker;
#endif
            }

#if MONOTOUCH
            if (EnableBitCode && SymbolMode != SymbolMode.Code)
            {
                // This is a warning because:
                // * The user will get a linker error anyway if they do this.
                // * I see it as quite unlikely that anybody will in fact try this (it must be manually set in the additional mtouch arguments).
                // * I find it more probable that Apple will remove the -u restriction, in which case someone might actually want to try this, and if it's a warning, we won't prevent it.
                ErrorHelper.Warning(115, "It is recommended to reference dynamic symbols using code (--dynamic-symbol-mode=code) when bitcode is enabled.");
            }
#endif

            Optimizations.Initialize(this);
        }
Exemple #20
0
        internal string GenerateReferencingSource(string reference_m, IEnumerable <Symbol> symbols)
#endif
        {
            if (!symbols.Any())
            {
                if (File.Exists(reference_m))
                {
                    File.Delete(reference_m);
                }
#if MTOUCH
                yield break;
#else
                return(null);
#endif
            }
            var sb = new StringBuilder();
            sb.AppendLine("#import <Foundation/Foundation.h>");
            foreach (var symbol in symbols)
            {
                switch (symbol.Type)
                {
                case SymbolType.Function:
                case SymbolType.Field:
                    sb.Append("extern void * ").Append(symbol.Name).AppendLine(";");
                    break;

                case SymbolType.ObjectiveCClass:
                    sb.AppendLine($"@interface {symbol.ObjectiveCName} : NSObject @end");
                    break;

                default:
                    throw ErrorHelper.CreateError(99, Errors.MX0099, $"invalid symbol type {symbol.Type} for symbol {symbol.Name}");
                }
            }
            sb.AppendLine("static void __xamarin_symbol_referencer () __attribute__ ((used)) __attribute__ ((optnone));");
            sb.AppendLine("void __xamarin_symbol_referencer ()");
            sb.AppendLine("{");
            sb.AppendLine("\tvoid *value;");
            foreach (var symbol in symbols)
            {
                switch (symbol.Type)
                {
                case SymbolType.Function:
                case SymbolType.Field:
                    sb.AppendLine($"\tvalue = {symbol.Name};");
                    break;

                case SymbolType.ObjectiveCClass:
                    sb.AppendLine($"\tvalue = [{symbol.ObjectiveCName} class];");
                    break;

                default:
                    throw ErrorHelper.CreateError(99, Errors.MX0099, $"invalid symbol type {symbol.Type} for symbol {symbol.Name}");
                }
            }
            sb.AppendLine("}");
            sb.AppendLine();

            Driver.WriteIfDifferent(reference_m, sb.ToString(), true);

#if MTOUCH
            foreach (var abi in GetArchitectures(AssemblyBuildTarget.StaticObject))
            {
                var arch         = abi.AsArchString();
                var reference_o  = Path.Combine(Path.GetDirectoryName(reference_m), arch, Path.GetFileNameWithoutExtension(reference_m) + ".o");
                var compile_task = new CompileTask {
                    Target        = this,
                    Abi           = abi,
                    InputFile     = reference_m,
                    OutputFile    = reference_o,
                    SharedLibrary = false,
                    Language      = "objective-c",
                };
                yield return(compile_task);
            }
#else
            return(reference_m);
#endif
        }
Exemple #21
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(4002, Errors.MT4002);
 }
Exemple #22
0
        public void Initialize(Application app)
        {
            // warn if the user asked to optimize something when the optimization can't be applied
            for (int i = 0; i < values.Length; i++)
            {
                if (!values [i].HasValue)
                {
                    continue;
                }
                switch ((Opt)i)
                {
                case Opt.StaticBlockToDelegateLookup:
                    if (app.Registrar != RegistrarMode.Static)
                    {
                        ErrorHelper.Warning(2003, Errors.MT2003, (values [i].Value ? "" : "-"), opt_names [i]);
                        values [i] = false;
                        continue;
                    }
                    break;                     // does not require the linker

                case Opt.TrimArchitectures:
                    break;                     // Does not require linker

                case Opt.RegisterProtocols:
                case Opt.RemoveDynamicRegistrar:
                    if (app.Registrar != RegistrarMode.Static)
                    {
                        ErrorHelper.Warning(2003, Errors.MT2003, (values[i].Value ? "" : "-"), opt_names[i]);
                        values [i] = false;
                        continue;
                    }
                    goto default;                     // also requires the linker

#if MONOTOUCH
                case Opt.RemoveUnsupportedILForBitcode:
                    if (app.Platform != Utils.ApplePlatform.WatchOS)
                    {
                        if (!all.HasValue)                         // Don't show this warning if it was enabled with --optimize=all
                        {
                            ErrorHelper.Warning(2003, Errors.MT2003_A, opt_names [(int)Opt.RemoveUnsupportedILForBitcode]);
                        }
                        values [i] = false;
                    }
                    break;
#endif
                default:
                    if (app.LinkMode == LinkMode.None)
                    {
                        ErrorHelper.Warning(2003, Errors.MT2003_B, (values [i].Value ? "" : "-"), opt_names [i]);
                        values [i] = false;
                    }
                    break;
                }
            }

            // by default we keep the code to ensure we're executing on the UI thread (for UI code) for debug builds
            // but this can be overridden to either (a) remove it from debug builds or (b) keep it in release builds
            if (!RemoveUIThreadChecks.HasValue)
            {
                RemoveUIThreadChecks = !app.EnableDebug;
            }

            // By default we always eliminate dead code.
            if (!DeadCodeElimination.HasValue)
            {
                DeadCodeElimination = true;
            }

            if (!InlineIsDirectBinding.HasValue)
            {
#if MONOTOUCH
                // By default we always inline calls to NSObject.IsDirectBinding
                // unless the interpreter is enabled (we can't predict if code will be subclassed)
                InlineIsDirectBinding = !app.UseInterpreter;
#else
                // NSObject.IsDirectBinding is not a safe optimization to apply to XM apps,
                // because there may be additional code/assemblies we don't know about at build time.
                InlineIsDirectBinding = false;
#endif
            }

            // The default behavior for InlineIntPtrSize depends on the assembly being linked,
            // which means we can't set it to a global constant. It's handled in the OptimizeGeneratedCodeSubStep directly.

#if MONOTOUCH
            // By default we always inline calls to Runtime.Arch
            if (!InlineRuntimeArch.HasValue)
            {
                InlineRuntimeArch = true;
            }
#endif

            // We try to optimize calls to BlockLiteral.SetupBlock if the static registrar is enabled
            if (!OptimizeBlockLiteralSetupBlock.HasValue)
            {
                OptimizeBlockLiteralSetupBlock = app.Registrar == RegistrarMode.Static;
            }

            // We will register protocols if the static registrar is enabled and loading assemblies is not possible
            if (!RegisterProtocols.HasValue)
            {
#if MONOTOUCH
                RegisterProtocols = (app.Registrar == RegistrarMode.Static) && !app.UseInterpreter;
#else
                RegisterProtocols = false;
#endif
            }
            else if (app.Registrar != RegistrarMode.Static && RegisterProtocols == true)
            {
                RegisterProtocols = false;                 // we've already shown a warning for this.
            }

            // By default we always inline calls to Runtime.DynamicRegistrationSupported
            if (!InlineDynamicRegistrationSupported.HasValue)
            {
                InlineDynamicRegistrationSupported = true;
            }

            // By default always enable static block-to-delegate lookup (it won't make a difference unless the static registrar is used though)
            if (!StaticBlockToDelegateLookup.HasValue)
            {
                StaticBlockToDelegateLookup = true;
            }

            if (!RemoveDynamicRegistrar.HasValue)
            {
                if (InlineDynamicRegistrationSupported != true)
                {
                    // Can't remove the dynamic registrar unless also inlining Runtime.DynamicRegistrationSupported
                    RemoveDynamicRegistrar = false;
                }
                else if (StaticBlockToDelegateLookup != true)
                {
                    // Can't remove the dynamic registrar unless also generating static lookup of block-to-delegates in the static registrar.
                    RemoveDynamicRegistrar = false;
                }
                else if (app.Registrar != RegistrarMode.Static || app.LinkMode == LinkMode.None)
                {
                    // Both the linker and the static registrar are also required
                    RemoveDynamicRegistrar = false;
                }
                else
                {
#if MONOTOUCH
                    // we can't predict is unknown (at build time) code will require registration (at runtime)
                    if (app.UseInterpreter)
                    {
                        RemoveDynamicRegistrar = false;
                    }
                    // We don't have enough information yet to determine if we can remove the dynamic
                    // registrar or not, so let the value stay unset until we do know (when running the linker).
#else
                    // By default disabled for XM apps
                    RemoveDynamicRegistrar = false;
#endif
                }
            }

#if !MONOTOUCH
            // By default on macOS trim-architectures for Release and not for debug
            if (!TrimArchitectures.HasValue)
            {
                TrimArchitectures = !app.EnableDebug;
            }
#endif

#if MONOTOUCH
            if (!RemoveUnsupportedILForBitcode.HasValue)
            {
                // By default enabled for watchOS device builds.
                RemoveUnsupportedILForBitcode = app.Platform == Utils.ApplePlatform.WatchOS && app.IsDeviceBuild;
            }

            if (!SealAndDevirtualize.HasValue)
            {
                // by default run the linker SealerSubStep unless the interpreter is enabled
                SealAndDevirtualize = !app.UseInterpreter;
            }
#endif
            // By default Runtime.IsARM64CallingConvention inlining is always enabled.
            if (!InlineIsARM64CallingConvention.HasValue)
            {
                InlineIsARM64CallingConvention = true;
            }

            // by default we try to eliminate any .cctor we can
            if (!StaticConstructorBeforeFieldInit.HasValue)
            {
                StaticConstructorBeforeFieldInit = true;
            }

            // by default we remove rarely used custom attributes
            if (!CustomAttributesRemoval.HasValue)
            {
                CustomAttributesRemoval = true;
            }

            if (Driver.Verbosity > 3)
            {
                Driver.Log(4, "Enabled optimizations: {0}", string.Join(", ", values.Select((v, idx) => v == true ? opt_names [idx] : string.Empty).Where((v) => !string.IsNullOrEmpty(v))));
            }
        }
Exemple #23
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(), output : 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 ProductException(5215, false, Errors.MT5215, name));
                        }
                    }
                    // mtouch does not validate extra parameters given to GCC when linking (--gcc_flags)
                    if (Target.App.CustomLinkFlags?.Count > 0)
                    {
                        linker_errors.Add(new ProductException(5201, true, Errors.MT5201, StringUtils.FormatArguments(Target.App.CustomLinkFlags)));
                    }
                    else
                    {
                        linker_errors.Add(new ProductException(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);
        }
Exemple #24
0
        static void AddSharedOptions(Application app, Mono.Options.OptionSet options)
        {
            options.Add("warnaserror:", "An optional comma-separated list of warning codes that should be reported as errors (if no warnings are specified all warnings are reported as errors).", v =>
            {
                try {
                    if (!string.IsNullOrEmpty(v))
                    {
                        foreach (var code in v.Split(new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Error, int.Parse(code));
                        }
                    }
                    else
                    {
                        ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Error);
                    }
                } catch (Exception ex) {
                    ErrorHelper.Error(26, ex, "Could not parse the command line argument '{0}': {1}", "--warnaserror", ex.Message);
                }
            });
            options.Add("nowarn:", "An optional comma-separated list of warning codes to ignore (if no warnings are specified all warnings are ignored).", v =>
            {
                try {
                    if (!string.IsNullOrEmpty(v))
                    {
                        foreach (var code in v.Split(new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Disable, int.Parse(code));
                        }
                    }
                    else
                    {
                        ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Disable);
                    }
                } catch (Exception ex) {
                    ErrorHelper.Error(26, ex, "Could not parse the command line argument '{0}': {1}", "--nowarn", ex.Message);
                }
            });
            options.Add("coop:", "If the GC should run in cooperative mode.", v => { app.EnableCoopGC = ParseBool(v, "coop"); }, hidden: true);
            options.Add("sgen-conc", "Enable the *experimental* concurrent garbage collector.", v => { app.EnableSGenConc = true; });
            options.Add("marshal-objectivec-exceptions:", "Specify how Objective-C exceptions should be marshalled. Valid values: default, unwindmanagedcode, throwmanagedexception, abort and disable. The default depends on the target platform (on watchOS the default is 'throwmanagedexception', while on all other platforms it's 'disable').", v => {
                switch (v)
                {
                case "default":
                    app.MarshalObjectiveCExceptions = MarshalObjectiveCExceptionMode.Default;
                    break;

                case "unwindmanaged":
                case "unwindmanagedcode":
                    app.MarshalObjectiveCExceptions = MarshalObjectiveCExceptionMode.UnwindManagedCode;
                    break;

                case "throwmanaged":
                case "throwmanagedexception":
                    app.MarshalObjectiveCExceptions = MarshalObjectiveCExceptionMode.ThrowManagedException;
                    break;

                case "abort":
                    app.MarshalObjectiveCExceptions = MarshalObjectiveCExceptionMode.Abort;
                    break;

                case "disable":
                    app.MarshalObjectiveCExceptions = MarshalObjectiveCExceptionMode.Disable;
                    break;

                default:
                    throw ErrorHelper.CreateError(26, "Could not parse the command line argument '{0}': {1}", "--marshal-objective-exceptions", $"Invalid value: {v}. Valid values are: default, unwindmanagedcode, throwmanagedexception, abort and disable.");
                }
            });
            options.Add("marshal-managed-exceptions:", "Specify how managed exceptions should be marshalled. Valid values: default, unwindnativecode, throwobjectivecexception, abort and disable. The default depends on the target platform (on watchOS the default is 'throwobjectivecexception', while on all other platform it's 'disable').", v => {
                switch (v)
                {
                case "default":
                    app.MarshalManagedExceptions = MarshalManagedExceptionMode.Default;
                    break;

                case "unwindnative":
                case "unwindnativecode":
                    app.MarshalManagedExceptions = MarshalManagedExceptionMode.UnwindNativeCode;
                    break;

                case "throwobjectivec":
                case "throwobjectivecexception":
                    app.MarshalManagedExceptions = MarshalManagedExceptionMode.ThrowObjectiveCException;
                    break;

                case "abort":
                    app.MarshalManagedExceptions = MarshalManagedExceptionMode.Abort;
                    break;

                case "disable":
                    app.MarshalManagedExceptions = MarshalManagedExceptionMode.Disable;
                    break;

                default:
                    throw ErrorHelper.CreateError(26, "Could not parse the command line argument '{0}': {1}", "--marshal-managed-exceptions", $"Invalid value: {v}. Valid values are: default, unwindnativecode, throwobjectivecexception, abort and disable.");
                }
            });
            options.Add("j|jobs=", "The level of concurrency. Default is the number of processors.", v => {
                Jobs = int.Parse(v);
            });
            options.Add("embeddinator", "Enables Embeddinator targetting mode.", v => {
                app.Embeddinator = true;
            }, true);
            options.Add("dynamic-symbol-mode:", "Specify how dynamic symbols are treated so that they're not linked away by the native linker. Valid values: linker (pass \"-u symbol\" to the native linker), code (generate native code that uses the dynamic symbol), ignore (do nothing and hope for the best). The default is 'code' when using bitcode, and 'linker' otherwise.", (v) => {
                switch (v.ToLowerInvariant())
                {
                case "default":
                    app.SymbolMode = SymbolMode.Default;
                    break;

                case "linker":
                    app.SymbolMode = SymbolMode.Linker;
                    break;

                case "code":
                    app.SymbolMode = SymbolMode.Code;
                    break;

                case "ignore":
                    app.SymbolMode = SymbolMode.Ignore;
                    break;

                default:
                    throw ErrorHelper.CreateError(26, "Could not parse the command line argument '{0}': {1}", "--dynamic-symbol-mode", $"Invalid value: {v}. Valid values are: default, linker, code and ignore.");
                }
            });
            options.Add("ignore-dynamic-symbol:", "Specify that Xamarin.iOS/Xamarin.Mac should not try to prevent the linker from removing the specified symbol.", (v) => {
                app.IgnoredSymbols.Add(v);
            });
            options.Add("root-assembly=", "Specifies any root assemblies. There must be at least one root assembly, usually the main executable.", (v) => {
                app.RootAssemblies.Add(v);
            });
            options.Add("optimize=", "A comma-delimited list of optimizations to enable/disable. To enable an optimization, use --optimize=[+]remove-uithread-checks. To disable an optimizations: --optimize=-remove-uithread-checks. Use '+all' to enable or '-all' disable all optimizations. Only compiler-generated code or code otherwise marked as safe to optimize will be optimized.\n" +
                        "Available optimizations:\n" +
                        "    dead-code-elimination: By default always enabled (requires the linker). Removes IL instructions the linker can determine will never be executed. This is most useful in combination with the inline-* optimizations, since inlined conditions almost always also results in blocks of code that will never be executed.\n" +
                        "    remove-uithread-checks: By default enabled for release builds (requires the linker). Remove all UI Thread checks (makes the app smaller, and slightly faster at runtime).\n" +
#if MONOTOUCH
                        "    inline-isdirectbinding: By default enabled (requires the linker). Tries to inline calls to NSObject.IsDirectBinding to load a constant value. Makes the app smaller, and slightly faster at runtime.\n" +
#else
                        "    inline-isdirectbinding: By default disabled, because it may require the linker. Tries to inline calls to NSObject.IsDirectBinding to load a constant value. Makes the app smaller, and slightly faster at runtime.\n" +
#endif
#if MONOTOUCH
                        "    remove-dynamic-registrar: By default enabled when the static registrar is enabled. Removes the dynamic registrar (makes the app smaller).\n" +
                        "    inline-runtime-arch: By default always enabled (requires the linker). Inlines calls to ObjCRuntime.Runtime.Arch to load a constant value. Makes the app smaller, and slightly faster at runtime.\n" +
#endif
                        "    blockliteral-setupblock: By default enabled when using the static registrar. Optimizes calls to BlockLiteral.SetupBlock to avoid having to calculate the block signature at runtime.\n" +
                        "    inline-intptr-size: By default enabled for builds that target a single architecture (requires the linker). Inlines calls to IntPtr.Size to load a constant value. Makes the app smaller, and slightly faster at runtime.\n" +
                        "    inline-dynamic-registration-supported: By default always enabled (requires the linker). Optimizes calls to Runtime.DynamicRegistrationSupported to be a constant value. Makes the app smaller, and slightly faster at runtime.\n" +
                        "    register-protocols: Remove unneeded metadata for protocol support. Makes the app smaller and reduces memory requirements.\n" +
#if !MONOTOUCH
                        "    trim-architectures: Remove unneeded architectures from bundled native libraries. Makes the app smaller and is required for macOS App Store submissions.\n",
#else
                        "",
#endif
                        (v) => {
                app.Optimizations.Parse(v);
            });
            options.Add(new Mono.Options.ResponseFileSource());
        }
Exemple #25
0
        protected async Task <int> CompileAsync()
        {
            if (App.IsDeviceBuild)
            {
                GetDeviceCompilerFlags(CompilerFlags, IsAssembler);
            }
            else if (App.Platform == ApplePlatform.MacCatalyst)
            {
                GetCatalystCompilerFlags(CompilerFlags, Abi, App);
            }
            else
            {
                GetSimulatorCompilerFlags(CompilerFlags, IsAssembler, App, Language);
            }

            if (App.EnableBitCode)
            {
                GetBitcodeCompilerFlags(CompilerFlags);
            }
            GetArchFlags(CompilerFlags, Abi);

            if (SharedLibrary)
            {
                GetSharedCompilerFlags(CompilerFlags, InstallName);
            }
            else
            {
                GetStaticCompilerFlags(CompilerFlags);
            }

            if (App.EnableDebug)
            {
                CompilerFlags.AddDefine("DEBUG");
            }

            CompilerFlags.AddOtherFlag("-o", OutputFile);

            if (!string.IsNullOrEmpty(Language))
            {
                CompilerFlags.AddOtherFlag("-x", Language);
            }

            Directory.CreateDirectory(Path.GetDirectoryName(OutputFile));

            var exceptions      = new List <Exception> ();
            var output          = new List <string> ();
            var assembly_name   = Path.GetFileNameWithoutExtension(OutputFile);
            var output_received = new Action <string> ((string line) => {
                if (line == null)
                {
                    return;
                }
                output.Add(line);
                CheckFor5107(assembly_name, line, exceptions);
            });

            var rv = await Driver.RunCommandAsync(App.CompilerPath, CompilerFlags.ToArray(), output_received : output_received, suppressPrintOnErrors : true);

            WriteLimitedOutput(rv != 0 ? $"Compilation failed with code {rv}, command:\n{App.CompilerPath} {CompilerFlags.ToString ()}" : null, output, exceptions);

            ErrorHelper.Show(exceptions);

            return(rv);
        }
Exemple #26
0
        public void Compile(IFileEnumerator files)
        {
            if (!options.IsAOT)
            {
                throw ErrorHelper.CreateError(0099, Errors.MX0099, $"\"AOTBundle with aot: {options.CompilationType}\" ");
            }

            var monoEnv = new Dictionary <string, string> {
                { "MONO_PATH", files.RootDir }
            };
            List <string> filesToAOT = GetFilesToAOT(files);

            bool   needsLipo  = abis.Length > 1 && filesToAOT.Count > 0;
            string tempAotDir = needsLipo ? Path.GetDirectoryName(filesToAOT [0]) : null;

            if (needsLipo && Directory.Exists(tempAotDir))
            {
                foreach (var abi in abis)
                {
                    Directory.CreateDirectory(Path.Combine(tempAotDir, "aot", abi.AsArchString()));
                }
            }

            Parallel.ForEach(filesToAOT.SelectMany(f => abis, (file, abi) => new Tuple <string, Abi> (file, abi)), ParallelOptions, tuple => {
                var file = tuple.Item1;
                var abi  = tuple.Item2;

                var cmd     = new List <string> ();
                var aotArgs = new List <string> ();
                aotArgs.Add($"mtriple={abi.AsArchString ()}");
                if (options.IsHybridAOT)
                {
                    aotArgs.Add("hybrid");
                }
                if (needsLipo)
                {
                    aotArgs.Add($"outfile={Path.Combine (tempAotDir, "aot", abi.AsArchString (), Path.GetFileName (file) + ".dylib")}");
                }
                cmd.Add($"--aot={string.Join (",", aotArgs)}");
                if (IsModern)
                {
                    cmd.Add("--runtime=mobile");
                }
                cmd.Add(file);
                if (RunCommand(GetMonoPath(abi), cmd, monoEnv) != 0)
                {
                    throw ErrorHelper.CreateError(3001, Errors.MX3001, "AOT", file);
                }
            });

            // Lipo the result
            if (needsLipo)
            {
                Parallel.ForEach(filesToAOT, ParallelOptions, file => {
                    string [] inputs = abis.Select(abi => Path.Combine(tempAotDir, "aot", abi.AsArchString(), Path.GetFileName(file) + ".dylib")).Where(File.Exists).ToArray();
                    string output    = file + ".dylib";

                    if (inputs.Length > 0)
                    {
                        Driver.RunLipoAndCreateDsym(Driver.App, output, inputs);
                    }
                });
            }

            if (needsLipo && Directory.Exists(tempAotDir))
            {
                Directory.Delete(Path.Combine(tempAotDir, "aot"), true);
            }

            if (IsRelease && options.IsHybridAOT)
            {
                Parallel.ForEach(filesToAOT, ParallelOptions, file => {
                    if (RunCommand(StripCommand, new [] { file }) != 0)
                    {
                        throw ErrorHelper.CreateError(3001, Errors.MX3001, "strip", file);
                    }
                });
            }

            if (IsRelease)
            {
                // mono --aot creates .dll.dylib.dSYM directories for each assembly AOTed
                // There isn't an easy was to disable this behavior
                // We move them (cheap) so they can be archived for release builds
                foreach (var file in filesToAOT)
                {
                    var source = file + ".dylib.dSYM/";
                    if (Directory.Exists(source))
                    {
                        var dest = Path.GetFullPath(Path.Combine(source, "..", "..", "..", "..", Path.GetFileName(file) + ".dylib.dSYM/"));
                        if (Directory.Exists(dest))
                        {
                            Directory.Delete(dest, true);
                        }
                        Directory.Move(source, dest);
                    }
                }
            }
        }
Exemple #27
0
        public void ExtractNativeLinkInfo()
        {
            // ignore framework assemblies, they won't have any LinkWith attributes
            if (IsFrameworkAssembly == true)
            {
                return;
            }

            var assembly = AssemblyDefinition;

            if (!assembly.HasCustomAttributes)
            {
                return;
            }

            string resourceBundlePath = Path.ChangeExtension(FullPath, ".resources");

            if (!Directory.Exists(resourceBundlePath))
            {
                var zipPath = resourceBundlePath + ".zip";
                if (File.Exists(zipPath))
                {
                    var path = Path.Combine(App.Cache.Location, Path.GetFileName(resourceBundlePath));
                    if (Driver.RunCommand("/usr/bin/unzip", "-u", "-o", "-d", path, zipPath) != 0)
                    {
                        throw ErrorHelper.CreateError(1306, Errors.MX1306 /* Could not decompress the file '{0}'. Please review the build log for more information from the native 'unzip' command. */, zipPath);
                    }
                    resourceBundlePath = path;
                }
            }
            string manifestPath = Path.Combine(resourceBundlePath, "manifest");

            if (File.Exists(manifestPath))
            {
                foreach (NativeReferenceMetadata metadata in ReadManifest(manifestPath))
                {
                    LogNativeReference(metadata);
                    ProcessNativeReferenceOptions(metadata);

                    switch (Path.GetExtension(metadata.LibraryName).ToLowerInvariant())
                    {
                    case ".framework":
                        AssertiOSVersionSupportsUserFrameworks(metadata.LibraryName);
                        Frameworks.Add(metadata.LibraryName);
#if MMP // HACK - MMP currently doesn't respect Frameworks on non-App - https://github.com/xamarin/xamarin-macios/issues/5203
                        App.Frameworks.Add(metadata.LibraryName);
#endif
                        break;

                    case ".xcframework":
                        // this is resolved, at msbuild time, into a framework
                        // but we must ignore it here (can't be the `default` case)
                        break;

                    default:
#if MMP // HACK - MMP currently doesn't respect LinkWith - https://github.com/xamarin/xamarin-macios/issues/5203
                        Driver.native_references.Add(metadata.LibraryName);
#endif
                        LinkWith.Add(metadata.LibraryName);
                        break;
                    }
                }
            }

            ProcessLinkWithAttributes(assembly);

            // Make sure there are no duplicates between frameworks and weak frameworks.
            // Keep the weak ones.
            if (Frameworks != null && WeakFrameworks != null)
            {
                Frameworks.ExceptWith(WeakFrameworks);
            }

            if (NeedsGccExceptionHandling)
            {
                if (LinkerFlags == null)
                {
                    LinkerFlags = new List <string> ();
                }
                LinkerFlags.Add("-lgcc_eh");
            }
        }
Exemple #28
0
        public void ExtractNativeLinkInfo()
        {
            // ignore framework assemblies, they won't have any LinkWith attributes
            if (IsFrameworkAssembly)
            {
                return;
            }

            var assembly = AssemblyDefinition;

            if (!assembly.HasCustomAttributes)
            {
                return;
            }

            var    exceptions = new List <Exception> ();
            string path;

            //
            // Tasks:
            // * Remove LinkWith attribute: this is done in the linker.
            // * Remove embedded resources related to LinkWith attribute from assembly: this is done at a later stage,
            //   here we just compile a list of resources to remove.
            // * Extract embedded resources related to LinkWith attribute to a file
            // * Modify the linker flags used to build/link the dylib (if fastdev) or the main binary (if !fastdev)
            //

            for (int i = 0; i < assembly.CustomAttributes.Count; i++)
            {
                CustomAttribute attr = assembly.CustomAttributes[i];

                if (attr.Constructor == null)
                {
                    continue;
                }

                TypeReference type = attr.Constructor.DeclaringType;
                if (!type.IsPlatformType("ObjCRuntime", "LinkWithAttribute"))
                {
                    continue;
                }

                // Let the linker remove it the attribute from the assembly
                HasLinkWithAttributes = true;

                LinkWithAttribute linkWith    = GetLinkWithAttribute(attr);
                string            libraryName = linkWith.LibraryName;

                // Remove the resource from the assembly at a later stage.
                if (!string.IsNullOrEmpty(libraryName))
                {
                    AddResourceToBeRemoved(libraryName);
                }

                // We can't add -dead_strip if there are any LinkWith attributes where smart linking is disabled.
                if (!linkWith.SmartLink)
                {
                    App.DeadStrip = false;
                }

                // Don't add -force_load if the binding's SmartLink value is set and the static registrar is being used.
                if (linkWith.ForceLoad && !(linkWith.SmartLink && App.Registrar == RegistrarMode.Static))
                {
                    ForceLoad = true;
                }

                if (!string.IsNullOrEmpty(linkWith.LinkerFlags))
                {
                    if (LinkerFlags == null)
                    {
                        LinkerFlags = new List <string> ();
                    }
                    LinkerFlags.Add(linkWith.LinkerFlags);
                }

                if (!string.IsNullOrEmpty(linkWith.Frameworks))
                {
                    foreach (var f in linkWith.Frameworks.Split(new char[] { ' ' }))
                    {
                        if (Frameworks == null)
                        {
                            Frameworks = new HashSet <string> ();
                        }
                        Frameworks.Add(f);
                    }
                }

                if (!string.IsNullOrEmpty(linkWith.WeakFrameworks))
                {
                    foreach (var f in linkWith.WeakFrameworks.Split(new char[] { ' ' }))
                    {
                        if (WeakFrameworks == null)
                        {
                            WeakFrameworks = new HashSet <string> ();
                        }
                        WeakFrameworks.Add(f);
                    }
                }

                if (linkWith.NeedsGccExceptionHandling)
                {
                    NeedsGccExceptionHandling = true;
                }

                if (linkWith.IsCxx)
                {
                    EnableCxx = true;
                }

#if MONOTOUCH
                if (linkWith.Dlsym != DlsymOption.Default)
                {
                    App.SetDlsymOption(FullPath, linkWith.Dlsym == DlsymOption.Required);
                }
#endif

                if (!string.IsNullOrEmpty(libraryName))
                {
                    path = Path.Combine(App.Cache.Location, libraryName);
                    if (path.EndsWith(".framework", StringComparison.Ordinal))
                    {
#if MONOTOUCH
                        if (App.Platform == Xamarin.Utils.ApplePlatform.iOS && App.DeploymentTarget.Major < 8)
                        {
                            throw ErrorHelper.CreateError(1305, "The binding library '{0}' contains a user framework ({0}), but embedded user frameworks require iOS 8.0 (the deployment target is {1}). Please set the deployment target in the Info.plist file to at least 8.0.",
                                                          FileName, Path.GetFileName(path), App.DeploymentTarget);
                        }
#endif
                        var zipPath = path + ".zip";
                        if (!Application.IsUptodate(FullPath, zipPath))
                        {
                            Application.ExtractResource(assembly.MainModule, libraryName, zipPath, false);
                            Driver.Log(3, "Extracted third-party framework '{0}' from '{1}' to '{2}'", libraryName, FullPath, zipPath);
                            LogLinkWithAttribute(linkWith);
                        }
                        else
                        {
                            Driver.Log(3, "Target '{0}' is up-to-date.", path);
                        }

                        if (!File.Exists(zipPath))
                        {
                            ErrorHelper.Warning(1302, "Could not extract the native framework '{0}' from '{1}'. " +
                                                "Please ensure the native framework was properly embedded in the managed assembly " +
                                                "(if the assembly was built using a binding project, the native framework must be included in the project, and its Build Action must be 'ObjcBindingNativeFramework').",
                                                libraryName, zipPath);
                        }
                        else
                        {
                            if (!Directory.Exists(path))
                            {
                                Directory.CreateDirectory(path);
                            }

                            if (Driver.RunCommand("/usr/bin/unzip", string.Format("-u -o -d {0} {1}", StringUtils.Quote(path), StringUtils.Quote(zipPath))) != 0)
                            {
                                throw ErrorHelper.CreateError(1303, "Could not decompress the native framework '{0}' from '{1}'. Please review the build log for more information from the native 'unzip' command.", libraryName, zipPath);
                            }
                        }

                        Frameworks.Add(path);
                    }
                    else
                    {
                        if (!Application.IsUptodate(FullPath, path))
                        {
                            Application.ExtractResource(assembly.MainModule, libraryName, path, false);
                            Driver.Log(3, "Extracted third-party binding '{0}' from '{1}' to '{2}'", libraryName, FullPath, path);
                            LogLinkWithAttribute(linkWith);
                        }
                        else
                        {
                            Driver.Log(3, "Target '{0}' is up-to-date.", path);
                        }

                        if (!File.Exists(path))
                        {
                            ErrorHelper.Warning(1302, "Could not extract the native library '{0}' from '{1}'. " +
                                                "Please ensure the native library was properly embedded in the managed assembly " +
                                                "(if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').",
                                                libraryName, path);
                        }

                        LinkWith.Add(path);
                    }
                }
            }

            if (exceptions != null && exceptions.Count > 0)
            {
                throw new AggregateException(exceptions);
            }

            // Make sure there are no duplicates between frameworks and weak frameworks.
            // Keep the weak ones.
            if (Frameworks != null && WeakFrameworks != null)
            {
                Frameworks.ExceptWith(WeakFrameworks);
            }

            if (NeedsGccExceptionHandling)
            {
                if (LinkerFlags == null)
                {
                    LinkerFlags = new List <string> ();
                }
                LinkerFlags.Add("-lgcc_eh");
            }
        }
Exemple #29
0
        public void GatherFrameworks()
        {
            Assembly           asm             = null;
            AssemblyDefinition productAssembly = null;

            foreach (var assembly in Assemblies)
            {
                if (assembly.AssemblyDefinition.Name.Name == Driver.GetProductAssembly(App))
                {
                    asm = assembly;
                    break;
                }
            }

            productAssembly = asm.AssemblyDefinition;

            // *** make sure any change in the above lists (or new list) are also reflected in
            // *** Makefile so simlauncher-sgen does not miss any framework

            HashSet <string> processed = new HashSet <string> ();

#if !MONOMAC
            Version v80 = new Version(8, 0);
#endif

            foreach (ModuleDefinition md in productAssembly.Modules)
            {
                foreach (TypeDefinition td in md.Types)
                {
                    // process only once each namespace (as we keep adding logic below)
                    string nspace = td.Namespace;
                    if (processed.Contains(nspace))
                    {
                        continue;
                    }
                    processed.Add(nspace);

                    Framework framework;
                    if (Driver.GetFrameworks(App).TryGetValue(nspace, out framework))
                    {
                        // framework specific processing
#if !MONOMAC
                        switch (framework.Name)
                        {
                        case "CoreAudioKit":
                            // CoreAudioKit seems to be functional in the iOS 9 simulator.
                            if (App.IsSimulatorBuild && App.SdkVersion.Major < 9)
                            {
                                continue;
                            }
                            break;

                        case "Metal":
                        case "MetalKit":
                        case "MetalPerformanceShaders":
                        case "CoreNFC":
                        case "DeviceCheck":
                            // some frameworks do not exists on simulators and will result in linker errors if we include them
                            if (App.IsSimulatorBuild)
                            {
                                continue;
                            }
                            break;

                        case "PushKit":
                            // in Xcode 6 beta 7 this became an (ld) error - it was a warning earlier :(
                            // ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later (@rpath/PushKit.framework/PushKit) for architecture armv7
                            // this was fixed in Xcode 6.2 (6.1 was still buggy) see #29786
                            if ((App.DeploymentTarget < v80) && (Driver.XcodeVersion < new Version(6, 2)))
                            {
                                ErrorHelper.Warning(49, "{0}.framework is supported only if deployment target is 8.0 or later. {0} features might not work correctly.", framework.Name);
                                continue;
                            }
                            break;
                        }
#endif

                        if (App.SdkVersion >= framework.Version)
                        {
                            var add_to = App.DeploymentTarget >= framework.Version ? asm.Frameworks : asm.WeakFrameworks;
                            add_to.Add(framework.Name);
                            continue;
                        }
                    }
                }
            }

            // Make sure there are no duplicates between frameworks and weak frameworks.
            // Keep the weak ones.
            asm.Frameworks.ExceptWith(asm.WeakFrameworks);
        }
 protected virtual void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5106, "Could not compile the file(s) '{0}'. Please file a bug report at http://bugzilla.xamarin.com", string.Join("', '", CompilerFlags.SourceFiles.ToArray()));
 }