Example #1
0
        public void MinOSVersion(Profile profile, MachO.LoadCommands load_command, MachO.Platform platform, bool device = false)
        {
            if (device)
            {
                Configuration.AssertDeviceAvailable();
            }

            var machoFiles = Directory.GetFiles(Configuration.GetSdkPath(profile, device), "*", SearchOption.AllDirectories)
                             .Where((v) => {
                if (v.Contains("dylib.dSYM/Contents/Resources/DWARF"))
                {
                    // Don't include *.dylib from inside .dSYMs.
                    return(false);
                }
                else if (v.Contains("libxammac-classic") || v.Contains("libxammac-system-classic"))
                {
                    // We don't care about XM Classic, those are binary dependencies.
                    return(false);
                }
                var ext = Path.GetExtension(v);
                return(ext == ".a" || ext == ".dylib");
            }
                                    );

            var failed = new List <string> ();

            foreach (var machoFile in machoFiles)
            {
                var fatfile = MachO.Read(machoFile);
                foreach (var slice in fatfile)
                {
                    var any_load_command = false;
                    foreach (var lc in slice.load_commands)
                    {
                        Version lc_min_version;
                        var     mincmd = lc as MinCommand;
                        if (mincmd != null)
                        {
                            Assert.AreEqual(load_command, mincmd.Command, "Unexpected min load command");
                            lc_min_version = mincmd.Version;
                        }
                        else
                        {
                            // starting from iOS SDK 12 the LC_BUILD_VERSION is used instead
                            var buildver = lc as BuildVersionCommand;
                            if (buildver == null)
                            {
                                continue;
                            }

                            var alternativePlatform = (MachO.Platform) 0;
                            switch (platform)
                            {
                            case MachO.Platform.IOSSimulator:
                                alternativePlatform = MachO.Platform.IOS;
                                break;

                            case MachO.Platform.TvOSSimulator:
                                alternativePlatform = MachO.Platform.TvOS;
                                break;

                            case MachO.Platform.WatchOSSimulator:
                                alternativePlatform = MachO.Platform.WatchOS;
                                break;
                            }
                            Assert.That(buildver.Platform, Is.EqualTo(platform).Or.EqualTo(alternativePlatform), $"Unexpected build version command in {machoFile} ({slice.Filename})");
                            lc_min_version = buildver.MinOS;
                        }

                        Version version;
                        Version alternate_version = null;
                        Version mono_native_compat_version;
                        Version mono_native_unified_version;
                        Version alternate_mono_native_unified_version = null;
                        switch (load_command)
                        {
                        case MachO.LoadCommands.MinMacOSX:
                            version = SdkVersions.MinOSXVersion;
                            mono_native_compat_version  = SdkVersions.MinOSXVersion;
                            mono_native_unified_version = new Version(10, 12, 0);
                            break;

                        case MachO.LoadCommands.MiniPhoneOS:
                            version = SdkVersions.MiniOSVersion;
                            if (slice.IsDynamicLibrary && device)
                            {
                                if (version.Major < 7)
                                {
                                    version = new Version(7, 0, 0);                                      // dylibs are supported starting with iOS 7.
                                }
                                alternate_version = new Version(8, 0, 0);                                // some iOS dylibs also have min OS 8.0 (if they're used as frameworks as well).
                            }
                            else if (slice.Architecture == MachO.Architectures.ARM64)
                            {
                                alternate_version = new Version(7, 0, 0);                                  // our arm64 slices has min iOS 7.0.
                            }
                            mono_native_compat_version  = version;
                            mono_native_unified_version = new Version(10, 0, 0);
                            break;

                        case MachO.LoadCommands.MintvOS:
                            version = SdkVersions.MinTVOSVersion;
                            mono_native_compat_version  = version;
                            mono_native_unified_version = new Version(10, 0, 0);
                            break;

                        case MachO.LoadCommands.MinwatchOS:
                            version = SdkVersions.MinWatchOSVersion;
                            if (device)
                            {
                                alternate_version = new Version(5, 1, 0);                                  // arm64_32 has min OS 5.1
                            }
                            mono_native_compat_version  = version;
                            mono_native_unified_version = new Version(5, 0, 0);
                            if (device)
                            {
                                alternate_mono_native_unified_version = new Version(5, 1, 0);                                  // armv7k has 5.0, arm64_32 has 5.1
                            }
                            break;

                        default:
                            throw new NotImplementedException(load_command.ToString());
                        }

                        version = version.WithBuild();
                        mono_native_compat_version  = mono_native_compat_version.WithBuild();
                        mono_native_unified_version = mono_native_unified_version.WithBuild();
                        if (alternate_version == null)
                        {
                            alternate_version = version;
                        }
                        if (alternate_mono_native_unified_version == null)
                        {
                            alternate_mono_native_unified_version = mono_native_unified_version;
                        }

                        switch (Path.GetFileName(machoFile))
                        {
                        case "libmono-native-compat.dylib":
                        case "libmono-native-compat.a":
                            if (mono_native_compat_version != lc_min_version)
                            {
                                failed.Add($"Unexpected minOS version (expected {mono_native_compat_version}, found {lc_min_version}) in {machoFile} ({slice.Filename}).");
                            }
                            break;

                        case "libmono-native-unified.dylib":
                        case "libmono-native-unified.a":
                            if (mono_native_unified_version != lc_min_version && alternate_mono_native_unified_version != lc_min_version)
                            {
                                failed.Add($"Unexpected minOS version (expected {mono_native_unified_version}, found {lc_min_version}) in {machoFile} ({slice.Filename}).");
                            }
                            break;

                        default:
                            if (version != lc_min_version && alternate_version != lc_min_version)
                            {
                                failed.Add($"Unexpected minOS version (expected {version}, alternatively {alternate_version}, found {lc_min_version}) in {machoFile} ({slice.Filename}).");
                            }
                            break;
                        }
                        any_load_command = true;
                    }
                    if (!any_load_command)
                    {
                        failed.Add($"No minOS version found in {machoFile}.");
                    }
                }
            }
            CollectionAssert.IsEmpty(failed, "Failures");
        }
Example #2
0
        public void MinOSVersion(Profile profile, MachO.LoadCommands load_command, bool device = false)
        {
            if (device)
            {
                Configuration.AssertDeviceAvailable();
            }

            var dylibs = Directory.GetFiles(Configuration.GetSdkPath(profile, device), "*.dylib", SearchOption.AllDirectories)
                         .Where((v) => !v.Contains("dylib.dSYM/Contents/Resources/DWARF"));          // Don't include *.dylib from inside .dSYMs.

            var failed = new List <string> ();

            foreach (var dylib in dylibs)
            {
                var fatfile = MachO.Read(dylib);
                foreach (var slice in fatfile)
                {
                    var any_load_command = false;
                    foreach (var lc in slice.load_commands)
                    {
                        var mincmd = lc as MinCommand;
                        if (mincmd == null)
                        {
                            continue;
                        }
                        // Console.WriteLine ($"    {mincmd.Command} version: {mincmd.version}=0x{mincmd.version.ToString ("x")}={mincmd.Version} sdk: {mincmd.sdk}=0x{mincmd.sdk.ToString ("x")}={mincmd.Sdk}");

                        Assert.AreEqual(load_command, mincmd.Command, "Unexpected min load command");

                        Version version;
                        Version alternate_version = null;
                        switch (load_command)
                        {
                        case MachO.LoadCommands.MinMacOSX:
                            version = SdkVersions.MinOSXVersion;
                            break;

                        case MachO.LoadCommands.MiniPhoneOS:
                            version = SdkVersions.MiniOSVersion;
                            if (device)
                            {
                                if (version.Major < 7)
                                {
                                    version = new Version(7, 0, 0);                                      // dylibs are supported starting with iOS 7.
                                }
                                alternate_version = new Version(8, 0, 0);                                // some iOS dylibs also have min OS 8.0 (if they're used as frameworks as well).
                            }
                            break;

                        case MachO.LoadCommands.MintvOS:
                            version = SdkVersions.MinTVOSVersion;
                            break;

                        case MachO.LoadCommands.MinwatchOS:
                            version = SdkVersions.MinWatchOSVersion;
                            break;

                        default:
                            throw new NotImplementedException(load_command.ToString());
                        }

                        version = new Version(version.Major, version.Minor, version.Build < 0 ? 0 : version.Build);
                        if (alternate_version == null)
                        {
                            alternate_version = version;
                        }

                        if (version != mincmd.Version && alternate_version != mincmd.Version)
                        {
                            failed.Add($"Unexpected minOS version (expected {version}, alternatively {alternate_version}, found {mincmd.Version}) in {dylib}.");
                        }
                        any_load_command = true;
                    }
                    if (!any_load_command)
                    {
                        failed.Add($"No minOS version found in {dylib}.");
                    }
                }
            }
            CollectionAssert.IsEmpty(failed, "Failures");
        }