Beispiel #1
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);
                    }
                }
            }
        }
Beispiel #2
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");
 }
Beispiel #3
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5216, Errors.MT5216, OutputFile);
 }
Beispiel #4
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, $"Internal error: could not find the product assembly {Driver.GetProductAssembly (App)} in the list of assemblies referenced by the executable. Please file a bug report with a test case (https://github.com/xamarin/xamarin-macios/issues/new).");
            }

            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
#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 = 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);
        }
Beispiel #5
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, $"Internal error: invalid symbol type {symbol.Type} for {symbol.Name}. Please file a bug report with a test case (https://github.com/xamarin/xamarin-macios/issues/new).");
                }
            }
            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, $"Internal error: invalid symbol type {symbol.Type} for {symbol.Name}. Please file a bug report with a test case (https://github.com/xamarin/xamarin-macios/issues/new).");
                }
            }
            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
        }
Beispiel #6
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(4109, "Failed to compile the generated registrar code. Please file a bug report at http://bugzilla.xamarin.com");
 }
Beispiel #7
0
 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()));
 }
Beispiel #8
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");
            }
        }
Beispiel #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 && !NET
                        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 "CHIP":
                        case "PHASE":
                        case "ThreadNetwork":
                            // 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;

#if !NET
                        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
                        default:
                            if (App.IsSimulatorBuild && !App.IsFrameworkAvailableInSimulator(framework.Name))
                            {
                                if (App.AreAnyAssembliesTrimmed)
                                {
                                    ErrorHelper.Warning(5223, Errors.MX5223, framework.Name, App.PlatformName);
                                }
                                else
                                {
                                    Driver.Log(3, Errors.MX5223, framework.Name, App.PlatformName);
                                }
                                continue;
                            }
                            break;
#endif
                        }

                        if (framework.Unavailable)
                        {
                            ErrorHelper.Warning(181, Errors.MX0181 /* Not linking with the framework {0} (used by the type {1}) because it's not available on the current platform ({2}). */, framework.Name, td.FullName, App.PlatformName);
                            continue;
                        }

                        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);
        }
Beispiel #10
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);
        }
Beispiel #11
0
 protected virtual void Execute()
 {
     throw ErrorHelper.CreateError(99, "Internal error: 'Either Execute or ExecuteAsync must be overridden'. Please file a bug report with a test case (https://github.com/xamarin/xamarin-macios/issues/new).");
 }
Beispiel #12
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);
        }
        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");
            }
        }
Beispiel #14
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(new Mono.Options.ResponseFileSource());
        }
Beispiel #15
0
 public static Exception CreateError(int code, string message, params object[] args) => ErrorHelper.CreateError(code, message, args);
Beispiel #16
0
        public void CollectAllSymbols()
        {
            if (dynamic_symbols != null)
            {
                return;
            }

            var dyn_msgSend_functions = new [] {
                new { Name = "xamarin_dyn_objc_msgSend", ValidAbis = Abi.SimulatorArchMask | Abi.ARM64 },
                new { Name = "xamarin_dyn_objc_msgSendSuper", ValidAbis = Abi.SimulatorArchMask | Abi.ARM64 },
                new { Name = "xamarin_dyn_objc_msgSend_stret", ValidAbis = Abi.SimulatorArchMask },
                new { Name = "xamarin_dyn_objc_msgSendSuper_stret", ValidAbis = Abi.SimulatorArchMask },
            };

            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;

                switch (App.Platform)
                {
                case ApplePlatform.iOS:
                case ApplePlatform.TVOS:
                case ApplePlatform.WatchOS:
                    has_dyn_msgSend = App.IsSimulatorBuild;
                    break;

                case ApplePlatform.MacCatalyst:
                case ApplePlatform.MacOSX:
                    has_dyn_msgSend = App.MarshalObjectiveCExceptions != MarshalObjectiveCExceptionMode.Disable && !App.RequiresPInvokeWrappers;
                    break;

                default:
                    throw ErrorHelper.CreateError(71, Errors.MX0071, App.Platform, App.ProductName);
                }

                if (has_dyn_msgSend)
                {
                    foreach (var dyn_msgSend_function in dyn_msgSend_functions)
                    {
                        dynamic_symbols.AddFunction(dyn_msgSend_function.Name);
                    }
                }

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

                dynamic_symbols.Save(cache_location);
            }

            foreach (var dynamicFunction in dyn_msgSend_functions)
            {
                var symbol = dynamic_symbols.Find(dynamicFunction.Name);
                if (symbol != null)
                {
                    symbol.ValidAbis = dynamicFunction.ValidAbis;
                }
            }

            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;
                }
            }
        }
Beispiel #17
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 http://bugzilla.xamarin.com");
 }
Beispiel #18
0
        static void AddSharedOptions(Application app, Mono.Options.OptionSet options)
        {
            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 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);
            });
        }
Beispiel #19
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5216, "Native linking failed for '{0}'. Please file a bug report at http://bugzilla.xamarin.com", OutputFile);
 }
Beispiel #20
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());
        }
Beispiel #21
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);
            });
        }
Beispiel #22
0
        public void InitializeCommon()
        {
            Namespaces.Initialize();
            SelectRegistrar();
            foreach (var target in Targets)
            {
                target.SelectMonoNative();
            }

            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);
        }
Beispiel #23
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, $"Internal error: invalid symbol type {symbol.Type} for symbol {symbol.Name}. Please file a bug report with a test case (https://github.com/xamarin/xamarin-macios/issues/new).");
            }
        }
Beispiel #24
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
                CommandLineAssemblies = RootAssemblies,
#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
            Registrar.IStaticRegistrar registrar;
#if MMP
            if (Driver.IsClassic)
            {
                registrar = new Registrar.ClassicStaticRegistrar(this);
            }
            else
            {
                registrar = new Registrar.StaticRegistrar(this);
            }
#else
            registrar = new Registrar.StaticRegistrar(this);
#endif
            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);
            }
        }
Beispiel #25
0
 protected override void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(4002, Errors.MT4002);
 }
Beispiel #26
0
        public static IList <string> GetAotArguments(Application app, string filename, Abi abi, string outputDir, string outputFile, string llvmOutputFile, string dataFile)
        {
            string fname                = Path.GetFileName(filename);
            var    args                 = new List <string> ();
            bool   enable_llvm          = (abi & Abi.LLVM) != 0;
            bool   enable_thumb         = (abi & Abi.Thumb) != 0;
            bool   enable_debug         = app.EnableDebug;
            bool   enable_debug_symbols = app.PackageManagedDebugSymbols;
            bool   llvm_only            = app.EnableLLVMOnlyBitCode;
            bool   interp               = app.IsInterpreted(Assembly.GetIdentity(filename));
            bool   interp_full          = !interp && app.UseInterpreter;
            bool   is32bit              = (abi & Abi.Arch32Mask) > 0;
            string arch                 = abi.AsArchString();

            args.Add("--debug");

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

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

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

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

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

            aot.Append("dwarfdebug,");

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

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

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

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

            aot.Append("outfile=").Append(outputFile);
            if (enable_llvm)
            {
                aot.Append(",llvm-outfile=").Append(llvmOutputFile);
            }
            args.Add(aot.ToString());
            args.Add(filename);
            return(args);
        }
Beispiel #27
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.UserGccFlags?.Count > 0)
                    {
                        linker_errors.Add(new ProductException(5201, true, Errors.MT5201, StringUtils.FormatArguments(Target.App.UserGccFlags)));
                    }
                    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);
        }
Beispiel #28
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 MMP || MTOUCH  // msbuild does not have force
            if (Driver.Force)
            {
                return(false);
            }
#endif

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

            if (sources.Count() == 0 || targets.Count() == 0)
            {
                throw ErrorHelper.CreateError(1013, Errors.MT1013);
            }

            foreach (var s in sources)
            {
                var sfi = new FileInfo(s);
                if (!sfi.Exists)
                {
                    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)
                {
                    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)
                    {
                        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)
                {
                    Log(3, "Prerequisite '{0}' is newer than target '{1}' ({2} vs {3}).", max_s, t, max_source, lwt);
                    return(false);
                }
            }

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

            return(true);
        }
Beispiel #29
0
 protected virtual void CompilationFailed(int exitCode)
 {
     throw ErrorHelper.CreateError(5106, Errors.MT5106, string.Join("', '", CompilerFlags.SourceFiles.ToArray()));
 }
Beispiel #30
0
        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, Errors.MT1301, 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, Errors.MT1300, 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", StringComparison.Ordinal) || s.StartsWith(".ascii", StringComparison.Ordinal))
                {
                    s = FixAsciz(s, line);
                }
                else if (s.StartsWith(".file", StringComparison.Ordinal))
                {
                    s = FixFile(s, line);
                }
                else if (s.Contains("\""))
                {
                    s = s.Replace("\"", "\\22");
                }

                writer.WriteLine("module asm \"{0}\"", s);
            }
            reader.Close();
            writer.Close();
        }