// this will filter/remove warnings that are not helpful (e.g. complaining about non-matching armv6-6 then armv7-6 on fat binaries)
        // and turn the remaining of the warnings into MT5203 that MonoDevelop will be able to report as real warnings (not just logs)
        // it will also look for symbol-not-found errors and try to provide useful error messages.
        public static void ProcessNativeLinkerOutput(Target target, string output, IList<string> inputs, List<Exception> errors, bool error)
        {
            List<string> lines = new List<string> (output.Split (new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries));

            // filter
            for (int i = 0; i < lines.Count; i++) {
                string line = lines [i];

                if (errors.Count > 100)
                    return;

                if (line.Contains ("ld: warning: ignoring file ") &&
                    line.Contains ("file was built for") &&
                    line.Contains ("which is not the architecture being linked") &&
                // Only ignore warnings related to the object files we've built ourselves (assemblies, main.m, registrar.m)
                    inputs.Any ((v) => line.Contains (v))) {
                    continue;
                } else if (line.Contains ("ld: symbol(s) not found for architecture") && errors.Count > 0) {
                    continue;
                } else if (line.Contains ("clang: error: linker command failed with exit code 1")) {
                    continue;
                } else if (line.Contains ("was built for newer iOS version (5.1.1) than being linked (5.1)")) {
                    continue;
                }

                if (line.Contains ("Undefined symbols for architecture")) {
                    while (++i < lines.Count) {
                        line = lines [i];
                        if (!line.EndsWith (", referenced from:"))
                            break;

                        var symbol = line.Replace (", referenced from:", "").Trim ('\"', ' ');
                        if (symbol.StartsWith ("_OBJC_CLASS_$_")) {
                            errors.Add (new MonoTouchException (5211, error,
                                                                "Native linking failed, undefined Objective-C class: {0}. The symbol '{1}' could not be found in any of the libraries or frameworks linked with your application.",
                                                                symbol.Replace ("_OBJC_CLASS_$_", ""), symbol));
                        } else {
                            var member = target.GetMemberForSymbol (symbol.Substring (1));
                            if (member != null) {
                                // Neither P/Invokes nor fields have IL, so we can't find the source code location.
                                errors.Add (new MonoTouchException (5214, error,
                                    "Native linking failed, undefined symbol: {0}. " +
                                    "This symbol was referenced by the managed member {1}.{2}. " +
                                    "Please verify that all the necessary frameworks have been referenced and native libraries linked.",
                                    symbol, member.DeclaringType.FullName, member.Name));
                            } else {
                                errors.Add (new MonoTouchException (5210, error,
                                                                "Native linking failed, undefined symbol: {0}. " +
                                                                "Please verify that all the necessary frameworks have been referenced and native libraries are properly linked in.",
                                                                symbol));
                            }
                        }

                        // skip all subsequent lines related to the same error.
                        // we skip all subsequent lines with more indentation than the initial line.
                        var indent = GetIndentation (line);
                        while (i + 1 < lines.Count) {
                            line = lines [i + 1];
                            if (GetIndentation (lines [i + 1]) <= indent)
                                break;
                            i++;
                        }
                    }
                } else if (line.StartsWith ("duplicate symbol") && line.EndsWith (" in:")) {
                    var symbol = line.Replace ("duplicate symbol ", "").Replace (" in:", "").Trim ();
                    errors.Add (new MonoTouchException (5212, error, "Native linking failed, duplicate symbol: '{0}'.", symbol));

                    var indent = GetIndentation (line);
                    while (i + 1 < lines.Count) {
                        line = lines [i + 1];
                        if (GetIndentation (lines [i + 1]) <= indent)
                            break;
                        i++;
                        errors.Add (new MonoTouchException (5213, error, "Duplicate symbol in: {0} (Location related to previous error)", line.Trim ()));
                    }
                } else {
                    if (line.StartsWith ("ld: "))
                        line = line.Substring (4);

                    line = line.Trim ();

                    if (error) {
                        errors.Add (new MonoTouchException (5209, error, "Native linking error: {0}", line));
                    } else {
                        errors.Add (new MonoTouchException (5203, error, "Native linking warning: {0}", line));
                    }
                }
            }
        }
        public static void Create(List<BuildTask> tasks, Target target, Abi abi, IEnumerable<Assembly> assemblies, string assemblyName, IList<string> registration_methods)
        {
            var arch = abi.AsArchString ();
            var ofile = Path.Combine (Cache.Location, "main." + arch + ".o");
            var ifile = Path.Combine (Cache.Location, "main." + arch + ".m");

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

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

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

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

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

            target.LinkWith (ofile);
        }
Beispiel #4
0
        void Initialize()
        {
            if (EnableDebug && IsLLVM)
                ErrorHelper.Warning (3003, "Debugging is not supported when building with LLVM. Debugging has been disabled.");

            if (!IsLLVM && (EnableAsmOnlyBitCode || EnableLLVMOnlyBitCode))
                throw ErrorHelper.CreateError (3008, "Bitcode support requires the use of LLVM (--abi=arm64+llvm etc.)");

            if (IsLLVM && Platform == ApplePlatform.WatchOS && BitCodeMode != BitCodeMode.LLVMOnly) {
                ErrorHelper.Warning (111, "Bitcode has been enabled because this version of Xamarin.iOS does not support building watchOS projects using LLVM without enabling bitcode.");
                BitCodeMode = BitCodeMode.LLVMOnly;
            }

            if (EnableDebug) {
                if (!DebugTrack.HasValue) {
                    DebugTrack = IsSimulatorBuild;
                }
            } else {
                if (DebugTrack.HasValue) {
                    ErrorHelper.Warning (32, "The option '--debugtrack' is ignored unless '--debug' is also specified.");
                }
                DebugTrack = false;
            }

            if (EnableAsmOnlyBitCode)
                LLVMAsmWriter = true;

            if (!File.Exists (RootAssembly))
                throw new MonoTouchException (7, true, "The root assembly '{0}' does not exist", RootAssembly);

            if (no_framework)
                throw ErrorHelper.CreateError (96, "No reference to Xamarin.iOS.dll was found.");

            // Add a reference to the platform assembly if none has been added, and check that we're not referencing
            // any platform assemblies from another platform.
            var platformAssemblyReference = false;
            foreach (var reference in References) {
                var name = Path.GetFileNameWithoutExtension (reference);
                if (name == Driver.GetProductAssembly (this)) {
                    platformAssemblyReference = true;
                } else {
                    switch (name) {
                    case "Xamarin.iOS":
                    case "Xamarin.TVOS":
                    case "Xamarin.WatchOS":
                        throw ErrorHelper.CreateError (41, "Cannot reference '{0}' in a {1} app.", Path.GetFileName (reference), Driver.TargetFramework.Identifier);
                    }
                }
            }
            if (!platformAssemblyReference) {
                ErrorHelper.Warning (85, "No reference to '{0}' was found. It will be added automatically.", Driver.GetProductAssembly (this) + ".dll");
                References.Add (Path.Combine (Driver.GetPlatformFrameworkDirectory (this), Driver.GetProductAssembly (this) + ".dll"));
            }

            var FrameworkDirectory = Driver.GetPlatformFrameworkDirectory (this);
            var RootDirectory = Path.GetDirectoryName (Path.GetFullPath (RootAssembly));

            ((MonoTouchProfile) Profile.Current).SetProductAssembly (Driver.GetProductAssembly (this));

            string root_wo_ext = Path.GetFileNameWithoutExtension (RootAssembly);
            if (Profile.IsSdkAssembly (root_wo_ext) || Profile.IsProductAssembly (root_wo_ext))
                throw new MonoTouchException (3, true, "Application name '{0}.exe' conflicts with an SDK or product assembly (.dll) name.", root_wo_ext);

            if (IsDualBuild) {
                var target32 = new Target (this);
                var target64 = new Target (this);

                target32.ArchDirectory = Path.Combine (Cache.Location, "32");
                target32.TargetDirectory = IsSimulatorBuild ? Path.Combine (AppDirectory, ".monotouch-32") : Path.Combine (target32.ArchDirectory, "Output");
                target32.AppTargetDirectory = Path.Combine (AppDirectory, ".monotouch-32");
                target32.Resolver.ArchDirectory = Driver.GetArch32Directory (this);
                target32.Abis = SelectAbis (abis, Abi.Arch32Mask);

                target64.ArchDirectory = Path.Combine (Cache.Location, "64");
                target64.TargetDirectory = IsSimulatorBuild ? Path.Combine (AppDirectory, ".monotouch-64") : Path.Combine (target64.ArchDirectory, "Output");
                target64.AppTargetDirectory = Path.Combine (AppDirectory, ".monotouch-64");
                target64.Resolver.ArchDirectory = Driver.GetArch64Directory (this);
                target64.Abis = SelectAbis (abis, Abi.Arch64Mask);

                Targets.Add (target64);
                Targets.Add (target32);
            } else {
                var target = new Target (this);

                target.TargetDirectory = AppDirectory;
                target.AppTargetDirectory = IsSimulatorBuild ? AppDirectory : Path.Combine (AppDirectory, Is64Build ? ".monotouch-64" : ".monotouch-32");
                target.ArchDirectory = Cache.Location;
                target.Resolver.ArchDirectory = Path.Combine (FrameworkDirectory, "..", "..", Is32Build ? "32bits" : "64bits");
                target.Abis = abis;

                Targets.Add (target);

                // Make sure there aren't any lingering .monotouch-* directories.
                if (IsSimulatorBuild) {
                    var dir = Path.Combine (AppDirectory, ".monotouch-32");
                    if (Directory.Exists (dir))
                        Directory.Delete (dir, true);
                    dir = Path.Combine (AppDirectory, ".monotouch-64");
                    if (Directory.Exists (dir))
                        Directory.Delete (dir, true);
                }
            }

            foreach (var target in Targets) {
                target.Resolver.FrameworkDirectory = FrameworkDirectory;
                target.Resolver.RootDirectory = RootDirectory;
                target.Resolver.EnableRepl = EnableRepl;
                target.ManifestResolver.EnableRepl = EnableRepl;
                target.ManifestResolver.FrameworkDirectory = target.Resolver.FrameworkDirectory;
                target.ManifestResolver.RootDirectory = target.Resolver.RootDirectory;
                target.ManifestResolver.ArchDirectory = target.Resolver.ArchDirectory;
                target.Initialize (target == Targets [0]);

                if (!Directory.Exists (target.TargetDirectory))
                    Directory.CreateDirectory (target.TargetDirectory);
            }

            if (string.IsNullOrEmpty (ExecutableName)) {
                var bundleExecutable = GetStringFromInfoPList ("CFBundleExecutable");
                ExecutableName = bundleExecutable ?? Path.GetFileNameWithoutExtension (RootAssembly);
            }

            if (ExecutableName != Path.GetFileNameWithoutExtension (AppDirectory))
                ErrorHelper.Warning (30, "The executable name ({0}) and the app name ({1}) are different, this may prevent crash logs from getting symbolicated properly.",
                    ExecutableName, Path.GetFileName (AppDirectory));

            if (IsExtension && Platform == ApplePlatform.iOS && SdkVersion < new Version (8, 0))
                throw new MonoTouchException (45, true, "--extension is only supported when using the iOS 8.0 (or later) SDK.");

            if (IsExtension && Platform != ApplePlatform.iOS && Platform != ApplePlatform.WatchOS && Platform != ApplePlatform.TVOS)
                throw new MonoTouchException (72, true, "Extensions are not supported for the platform '{0}'.", Platform);

            if (!IsExtension && Platform == ApplePlatform.WatchOS)
                throw new MonoTouchException (77, true, "WatchOS projects must be extensions.");

            #if ENABLE_BITCODE_ON_IOS
            if (Platform == ApplePlatform.iOS)
                DeploymentTarget = new Version (9, 0);
            #endif

            if (DeploymentTarget == null) {
                DeploymentTarget = Xamarin.SdkVersions.GetVersion (Platform);
            } else if (DeploymentTarget < Xamarin.SdkVersions.GetMinVersion (Platform)) {
                throw new MonoTouchException (73, true, "Xamarin.iOS {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);
            } else if (DeploymentTarget > Xamarin.SdkVersions.GetVersion (Platform)) {
                throw new MonoTouchException (74, true, "Xamarin.iOS {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 Xamarin.iOS.", Constants.Version, DeploymentTarget, Xamarin.SdkVersions.GetVersion (Platform), PlatformName);
            }

            if (Platform == ApplePlatform.iOS && FastDev && DeploymentTarget.Major < 8) {
                ErrorHelper.Warning (78, "Incremental builds are enabled with a deployment target < 8.0 (currently {0}). This is not supported (the resulting application will not launch on iOS 9), so the deployment target will be set to 8.0.", DeploymentTarget);
                DeploymentTarget = new Version (8, 0);
            }

            if (!package_mdb.HasValue) {
                package_mdb = EnableDebug;
            } else if (package_mdb.Value && IsLLVM) {
                ErrorHelper.Warning (3007, "Debug info files (*.mdb) will not be loaded when llvm is enabled.");
            }

            if (!enable_msym.HasValue)
                enable_msym = !EnableDebug && IsDeviceBuild;

            if (!UseMonoFramework.HasValue && DeploymentTarget >= new Version (8, 0)) {
                if (IsExtension) {
                    UseMonoFramework = true;
                    Driver.Log (2, "Automatically linking with Mono.framework because this is an extension");
                } else if (Extensions.Count > 0) {
                    UseMonoFramework = true;
                    Driver.Log (2, "Automatically linking with Mono.framework because this is an app with extensions");
                }
            }

            if (!UseMonoFramework.HasValue)
                UseMonoFramework = false;

            if (UseMonoFramework.Value)
                Frameworks.Add (Path.Combine (Driver.GetProductFrameworksDirectory (this), "Mono.framework"));

            if (!PackageMonoFramework.HasValue) {
                if (!IsExtension && Extensions.Count > 0 && !UseMonoFramework.Value) {
                    // The main app must package the Mono framework if we have extensions, even if it's not linking with
                    // it. This happens when deployment target < 8.0 for the main app.
                    PackageMonoFramework = true;
                } else {
                    // Package if we're not an extension and we're using the mono framework.
                    PackageMonoFramework = UseMonoFramework.Value && !IsExtension;
                }
            }

            if (Frameworks.Count > 0) {
                switch (Platform) {
                case ApplePlatform.iOS:
                    if (DeploymentTarget < new Version (8, 0))
                        throw ErrorHelper.CreateError (65, "Xamarin.iOS only supports embedded frameworks when deployment target is at least 8.0 (current deployment target: '{0}'; embedded frameworks: '{1}')", DeploymentTarget, string.Join (", ", Frameworks.ToArray ()));
                    break;
                case ApplePlatform.WatchOS:
                    if (DeploymentTarget < new Version (2, 0))
                        throw ErrorHelper.CreateError (65, "Xamarin.iOS only supports embedded frameworks when deployment target is at least 2.0 (current deployment target: '{0}'; embedded frameworks: '{1}')", DeploymentTarget, string.Join (", ", Frameworks.ToArray ()));
                    break;
                case ApplePlatform.TVOS:
                    // All versions of tvOS support extensions
                    break;
                default:
                    throw ErrorHelper.CreateError (71, "Unknown platform: {0}. This usually indicates a bug in Xamarin.iOS; please file a bug report at http://bugzilla.xamarin.com with a test case.", Platform);
                }
            }

            if (IsDeviceBuild) {
                switch (BitCodeMode) {
                case BitCodeMode.ASMOnly:
                    if (Platform == ApplePlatform.WatchOS)
                        throw ErrorHelper.CreateError (83, "asm-only bitcode is not supported on watchOS. Use either --bitcode:marker or --bitcode:full.");
                    break;
                case BitCodeMode.LLVMOnly:
                case BitCodeMode.MarkerOnly:
                    break;
                case BitCodeMode.None:
                    // If neither llvmonly nor asmonly is enabled, enable markeronly.
                    if (Platform == ApplePlatform.TVOS || Platform == ApplePlatform.WatchOS)
                        BitCodeMode = BitCodeMode.MarkerOnly;
                    break;
                }
            }

            if (EnableBitCode && IsSimulatorBuild)
                throw ErrorHelper.CreateError (84, "Bitcode is not supported in the simulator. Do not pass --bitcode when building for the simulator.");

            if (LinkMode == LinkMode.None && SdkVersion < SdkVersions.GetVersion (Platform))
                throw ErrorHelper.CreateError (91, "This version of Xamarin.iOS requires the {0} {1} SDK (shipped with Xcode {2}) when the managed linker is disabled. Either upgrade Xcode, or enable the managed linker by changing the Linker behaviour to Link Framework SDKs Only.", PlatformName, SdkVersions.GetVersion (Platform), SdkVersions.Xcode);

            Namespaces.Initialize ();

            InitializeCommon ();

            Driver.Watch ("Resolve References", 1);
        }
        void Initialize()
        {
            if (!File.Exists (RootAssembly))
                throw new MonoTouchException (7, true, "The root assembly '{0}' does not exist", RootAssembly);

            if (implicit_monotouch_reference)
                ErrorHelper.Warning (42, "No reference to either monotouch.dll or Xamarin.iOS.dll was found. A reference to monotouch.dll will be added.");

            // Add a reference to the platform assembly if none has been added, and check that we're not referencing
            // any platform assemblies from another platform.
            var platformAssemblyReference = false;
            foreach (var reference in References) {
                var name = Path.GetFileNameWithoutExtension (reference);
                if (name == Driver.ProductAssembly) {
                    platformAssemblyReference = true;
                } else {
                    switch (name) {
                    case "monotouch":
                    case "Xamarin.iOS":
                    case "Xamarin.TVOS":
                    case "Xamarin.WatchOS":
                        throw ErrorHelper.CreateError (41, "Cannot reference '{0}' in a {1} app.", Path.GetFileName (reference), Driver.TargetFramework.Identifier);
                    }
                }
            }
            if (!platformAssemblyReference) {
                ErrorHelper.Warning (85, "No reference to '{0}' was found. It will be added automatically.", Driver.ProductAssembly + ".dll");
                References.Add (Path.Combine (Driver.PlatformFrameworkDirectory, Driver.ProductAssembly + ".dll"));
            }

            var FrameworkDirectory = Driver.PlatformFrameworkDirectory;
            var RootDirectory = Path.GetDirectoryName (Path.GetFullPath (RootAssembly));

            ((MonoTouchProfile) Profile.Current).SetProductAssembly (Driver.ProductAssembly);

            string root_wo_ext = Path.GetFileNameWithoutExtension (RootAssembly);
            if (Profile.IsSdkAssembly (root_wo_ext) || Profile.IsProductAssembly (root_wo_ext))
                throw new MonoTouchException (3, true, "Application name '{0}.exe' conflicts with an SDK or product assembly (.dll) name.", root_wo_ext);

            if (IsDualBuild) {
                var target32 = new Target (this);
                var target64 = new Target (this);

                target32.ArchDirectory = Path.Combine (Cache.Location, "32");
                target32.TargetDirectory = IsSimulatorBuild ? Path.Combine (AppDirectory, ".monotouch-32") : Path.Combine (target32.ArchDirectory, "Output");
                target32.AppTargetDirectory = Path.Combine (AppDirectory, ".monotouch-32");
                target32.Resolver.ArchDirectory = Path.Combine (Driver.PlatformFrameworkDirectory, "..", "..", "32bits");
                target32.Abis = SelectAbis (abis, Abi.Arch32Mask);

                target64.ArchDirectory = Path.Combine (Cache.Location, "64");
                target64.TargetDirectory = IsSimulatorBuild ? Path.Combine (AppDirectory, ".monotouch-64") : Path.Combine (target64.ArchDirectory, "Output");
                target64.AppTargetDirectory = Path.Combine (AppDirectory, ".monotouch-64");
                target64.Resolver.ArchDirectory = Path.Combine (Driver.PlatformFrameworkDirectory, "..", "..", "64bits");
                target64.Abis = SelectAbis (abis, Abi.Arch64Mask);

                Targets.Add (target64);
                Targets.Add (target32);
            } else {
                var target = new Target (this);

                target.TargetDirectory = AppDirectory;
                target.AppTargetDirectory = (IsSimulatorBuild || IsClassic) ? AppDirectory : Path.Combine (AppDirectory, Is64Build ? ".monotouch-64" : ".monotouch-32");
                target.ArchDirectory = Cache.Location;
                if (IsClassic) {
                    target.Resolver.ArchDirectory = Driver.PlatformFrameworkDirectory;
                } else {
                    target.Resolver.ArchDirectory = Path.Combine (Driver.PlatformFrameworkDirectory, "..", "..", Is32Build ? "32bits" : "64bits");
                }
                target.Abis = abis;

                Targets.Add (target);

                // Make sure there aren't any lingering .monotouch-* directories.
                if (IsSimulatorBuild) {
                    var dir = Path.Combine (AppDirectory, ".monotouch-32");
                    if (Directory.Exists (dir))
                        Directory.Delete (dir, true);
                    dir = Path.Combine (AppDirectory, ".monotouch-64");
                    if (Directory.Exists (dir))
                        Directory.Delete (dir, true);
                }
            }

            foreach (var target in Targets) {
                target.Resolver.FrameworkDirectory = Driver.PlatformFrameworkDirectory;
                target.Resolver.RootDirectory = RootDirectory;
                target.Resolver.EnableRepl = EnableRepl;
                target.ManifestResolver.EnableRepl = EnableRepl;
                target.ManifestResolver.FrameworkDirectory = target.Resolver.FrameworkDirectory;
                target.ManifestResolver.RootDirectory = target.Resolver.RootDirectory;
                target.ManifestResolver.ArchDirectory = target.Resolver.ArchDirectory;
                target.Initialize (target == Targets [0]);

                if (!Directory.Exists (target.TargetDirectory))
                    Directory.CreateDirectory (target.TargetDirectory);
            }

            if (string.IsNullOrEmpty (ExecutableName)) {
                var bundleExecutable = GetStringFromInfoPList ("CFBundleExecutable");
                ExecutableName = bundleExecutable ?? Path.GetFileNameWithoutExtension (RootAssembly);
            }

            if (ExecutableName != Path.GetFileNameWithoutExtension (AppDirectory))
                ErrorHelper.Warning (30, "The executable name ({0}) and the app name ({1}) are different, this may prevent crash logs from getting symbolicated properly.",
                    ExecutableName, Path.GetFileName (AppDirectory));

            if (Is64Build && IsClassic)
                ErrorHelper.Error (37, "monotouch.dll is not 64-bit compatible. Either reference Xamarin.iOS.dll, or do not build for a 64-bit architecture (ARM64 or x86_64).");

            if (IsExtension && Platform == ApplePlatform.iOS && Driver.SDKVersion < new Version (8, 0))
                throw new MonoTouchException (45, true, "--extension is only supported when using the iOS 8.0 (or later) SDK.");

            if (IsExtension && Platform != ApplePlatform.iOS && Platform != ApplePlatform.WatchOS && Platform != ApplePlatform.TVOS)
                throw new MonoTouchException (72, true, "Extensions are not supported for the platform '{0}'.", Platform);

            if (!IsExtension && Platform == ApplePlatform.WatchOS)
                throw new MonoTouchException (77, true, "WatchOS projects must be extensions.");

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

            if (Platform == ApplePlatform.iOS && FastDev && DeploymentTarget.Major < 7) {
                ErrorHelper.Warning (78, "Incremental builds are enabled with a deployment target < 7.0 (currently {0}). This is not supported (the resulting application will not launch on iOS 9), so the deployment target will be set to 7.0.", DeploymentTarget);
                DeploymentTarget = new Version (7, 0);
            }

            if (Driver.classic_only_arguments.Count > 0) {
                var exceptions = new List<Exception> ();
                foreach (var deprecated in Driver.classic_only_arguments) {
                    switch (deprecated) {
                    case "--nomanifest":
                    case "--nosign":
                        // These options default to 'true' (for Classic), so we can't deprecated them (for Classic).
                        if (IsClassic)
                            continue;
                        break;
                    }
                    exceptions.Add (new MonoTouchException (16, IsUnified, "The option '{0}' has been deprecated.", deprecated));
                }
                ErrorHelper.Show (exceptions);
            }

            if (!generate_manifests.HasValue)
                generate_manifests = IsClassic;

            if (!sign.HasValue)
                sign = IsClassic;

            if (!package_mdb.HasValue) {
                package_mdb = EnableDebug;
            } else if (package_mdb.Value && IsLLVM) {
                ErrorHelper.Warning (3007, "Debug info files (*.mdb) will not be loaded when llvm is enabled.");
            }

            if (!enable_msym.HasValue)
                enable_msym = false; // Disable by default for C7 // !EnableDebug && IsDeviceBuild;

            if (!UseMonoFramework.HasValue && DeploymentTarget >= new Version (8, 0)) {
                if (IsExtension) {
                    if (IsUnified) {
                        UseMonoFramework = true;
                        Driver.Log (2, "Automatically linking with Mono.framework because this is an extension");
                    }
                } else if (IsUnified) {
                    if (Extensions.Count > 0) {
                        UseMonoFramework = true;
                        Driver.Log (2, "Automatically linking with Mono.framework because this is an app with extensions");
                    }
                }
            }

            if (!UseMonoFramework.HasValue)
                UseMonoFramework = false;

            if (UseMonoFramework.Value)
                Frameworks.Add (Path.Combine (Driver.ProductFrameworksDirectory, "Mono.framework"));

            if (!PackageMonoFramework.HasValue) {
                if (!IsExtension && Extensions.Count > 0 && !UseMonoFramework.Value) {
                    // The main app must package the Mono framework if we have extensions, even if it's not linking with
                    // it. This happens when deployment target < 8.0 for the main app.
                    PackageMonoFramework = true;
                } else {
                    // Package if we're not an extension and we're using the mono framework.
                    PackageMonoFramework = UseMonoFramework.Value && !IsExtension;
                }
            }

            if (Frameworks.Count > 0) {
                if (DeploymentTarget < new Version (8, 0))
                    throw ErrorHelper.CreateError (65, "Xamarin.iOS only supports embedded frameworks when deployment target is at least 8.0 (current deployment target: '{0}'; embedded frameworks: '{1}')", DeploymentTarget, string.Join (", ", Frameworks.ToArray ()));

                if (IsClassic)
                    throw ErrorHelper.CreateError (64, "Xamarin.iOS only supports embedded frameworks with Unified projects.");
            }

            if (IsDeviceBuild) {
                switch (BitCodeMode) {
                case BitCodeMode.ASMOnly:
                    if (Platform == ApplePlatform.WatchOS)
                        throw ErrorHelper.CreateError (83, "asm-only bitcode is not supported on watchOS. Use either --bitcode:marker or --bitcode:full.");
                    break;
                case BitCodeMode.LLVMOnly:
                case BitCodeMode.MarkerOnly:
                    break;
                case BitCodeMode.None:
                    // If neither llvmonly nor asmonly is enabled, enable markeronly.
                    if (Platform == ApplePlatform.TVOS || Platform == ApplePlatform.WatchOS)
                        BitCodeMode = BitCodeMode.MarkerOnly;
                    break;
                }
            }

            if (EnableBitCode && IsSimulatorBuild)
                throw ErrorHelper.CreateError (84, "Bitcode is not supported in the simulator. Do not pass --bitcode when building for the simulator.");

            if (LinkMode == LinkMode.None && Driver.SDKVersion < SdkVersions.GetVersion (Platform))
                throw ErrorHelper.CreateError (91, "This version of Xamarin.iOS requires the {0} {1} SDK (shipped with Xcode {2}) when the managed linker is disabled. Either upgrade Xcode, or enable the managed linker.", PlatformName, SdkVersions.GetVersion (Platform), SdkVersions.Xcode);

            Namespaces.Initialize ();

            Driver.Watch ("Resolve References", 1);
        }
Beispiel #6
0
 public Assembly(Target target, AssemblyDefinition definition)
 {
     this.Target = target;
     this.AssemblyDefinition = definition;
     this.FullPath = definition.MainModule.FullyQualifiedName;
 }
Beispiel #7
0
        // This method generates the manifest that is required by the symbolication in order to be able to debug the application,
        // The following is an example of the manifest to be generated:
        // <mono-debug version=”1”>
        //    <app-id>com.foo.bar</app-id>
        //    <build-date>datetime</build-date>
        //    <build-id>build-id</build-id>
        //    <build-id>build-id</build-id>
        // </mono-debug>
        // where:
        //
        // app-id: iOS/Android/Mac app/package ID. Currently for verification and user info only but in future may be used to find symbols automatically.
        // build-date: Local time in DateTime “O” format. For user info only.
        // build-id: The build UUID. Needed for HockeyApp to find the mSYM folder matching the app build. There may be more than one, as in the case of iOS multi-arch.
        void GenerateMSymManifest(Target target, string target_directory)
        {
            var manifestPath = Path.Combine (target_directory, "manifest.xml");
            if (String.IsNullOrEmpty (target_directory))
                throw new ArgumentNullException (nameof (target_directory));
            var root = new XElement ("mono-debug",
                new XAttribute("version", 1),
                new XElement ("app-id", BundleId),
                new XElement ("build-date", DateTime.Now.ToString ("O")));

            var file = MachO.Read (target.Executable);

            if (file is MachO) {
                var mfile = file as MachOFile;
                var uuids = GetUuids (mfile);
                foreach (var str in uuids) {
                    root.Add (new XElement ("build-id", str));
                }
            } else if (file is IEnumerable<MachOFile>) {
                var ffile = file as IEnumerable<MachOFile>;
                foreach (var fentry in ffile) {
                    var uuids = GetUuids (fentry);
                    foreach (var str in uuids) {
                        root.Add (new XElement ("build-id", str));
                    }
                }

            } else {
                // do not write a manifest
                return;
            }

            // Write only if we need to update the manifest
            Driver.WriteIfDifferent (manifestPath, root.ToString ());
        }
Beispiel #8
0
		// The input file is either a .s or a .bc file
		BuildTask CreateCompileTask (string assembly_name, string infile_path, Abi abi)
		{
			var ext = App.FastDev ? "dylib" : "o";
			var ofile = Path.ChangeExtension (infile_path, ext);
			var install_name = string.Empty;

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

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

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

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

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

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

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

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

			if (bitcode_task != null) {
				bitcode_task.NextTasks = new BuildTask[] { link_task };
				return bitcode_task;
			}
			return link_task;
		}
Beispiel #9
0
 public Assembly(Target target, string path)
 {
     this.Target = target;
     this.FullPath = path;
 }
Beispiel #10
0
		IEnumerable<BuildTask> CreateManagedToAssemblyTasks (string s, Abi abi, string build_dir)
		{
			var arch = abi.AsArchString ();
			var asm_dir = Cache.Location;
			var asm = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + ".s";
			var llvm_asm = Path.Combine (asm_dir, Path.GetFileName (s)) + "." + arch + "-llvm.s";
			var data = Path.Combine (asm_dir, Path.GetFileNameWithoutExtension (s)) + "." + arch + ".aotdata";
			string llvm_ofile, llvm_aot_ofile = "";
			var is_llvm = (abi & Abi.LLVM) == Abi.LLVM;
			bool assemble_llvm = is_llvm && Driver.LLVMAsmWriter;

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

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

			dependencies = ComputeDependencies (warnings);

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

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

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

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

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

			AotDataFiles.Add (data);

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

			return new BuildTask [] { new AOTTask ()
				{
					AssemblyName = s,
					ProcessStartInfo = Driver.CreateStartInfo (aotCompiler, aotArgs, Path.GetDirectoryName (s)),
					NextTasks = nextTasks
				}
			};
		}
Beispiel #11
0
 public Assembly(Target target, AssemblyDefinition definition)
 {
     this.Target             = target;
     this.AssemblyDefinition = definition;
     this.FullPath           = definition.MainModule.FileName;
 }
Beispiel #12
0
        List <string> link_with_resources;        // a list of resources that must be removed from the app

        public Assembly(Target target, string path)
        {
            this.Target   = target;
            this.FullPath = path;
        }
Beispiel #13
0
		public static void GatherFrameworks (Target target, HashSet<string> frameworks, HashSet<string> weak_frameworks)
		{
			AssemblyDefinition monotouch = null;

			foreach (var assembly in target.Assemblies) {
				if (assembly.AssemblyDefinition.FullName == target.ProductAssembly.FullName) {
					monotouch = assembly.AssemblyDefinition;
					break;
				}
			}

			// *** 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> ();
			Version v80 = new Version (8, 0);

			foreach (ModuleDefinition md in monotouch.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.Frameworks.TryGetValue (nspace, out framework)) {
						// framework specific processing
						switch (framework.Name) {
						case "CoreAudioKit":
							// CoreAudioKit seems to be functional in the iOS 9 simulator.
							if (app.IsSimulatorBuild && SDKVersion.Major < 9)
								continue;
							break;
						case "Metal":
						case "MetalKit":
						case "MetalPerformanceShaders":
							// 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) && (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;
						}

						if (sdk_version >= framework.Version) {
							var add_to = app.DeploymentTarget >= framework.Version ? frameworks : weak_frameworks;
							add_to.Add (framework.Name);
							continue;
						}
					}
				}
			}
		}
Beispiel #14
0
		public static string RunRegistrar (Target target, List<Assembly> assemblies, string assemblies_path, string output_dir, bool old, bool is_64_bits, string out_file = null)
		{
			const string registrar_file = "registrar.m";

			var resolvedAssemblies = assemblies.Select (asm => asm.AssemblyDefinition);
			var output_file = out_file ?? Path.Combine (output_dir, registrar_file);
			var code = string.Empty;

			if (old) {
				code = OldStaticRegistrar.Generate (resolvedAssemblies);
			} else {
				code = StaticRegistrar.Generate (app, resolvedAssemblies, target.App.IsSimulatorBuild, is_64_bits, target.LinkContext);
			}

			WriteIfDifferent (output_file, code);
			
			return output_file;
		}