Exemple #1
0
 void BuildEntitlementFlags(GccOptions gcc)
 {
     if (SdkIsSimulator && !string.IsNullOrEmpty(CompiledEntitlements) && EntitlementsRequireLinkerFlags(CompiledEntitlements))
     {
         gcc.Arguments.AddQuoted(new [] { "-Xlinker", "-sectcreate", "-Xlinker", "__TEXT", "-Xlinker", "__entitlements" });
         gcc.Arguments.Add("-Xlinker");
         gcc.Arguments.AddQuoted(Path.GetFullPath(CompiledEntitlements));
     }
 }
Exemple #2
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new ProcessArgumentBuilder();
            TargetArchitecture architectures;
            bool msym;

            if (string.IsNullOrEmpty(Architectures) || !Enum.TryParse(Architectures, out architectures))
            {
                architectures = TargetArchitecture.Default;
            }

            if (architectures == TargetArchitecture.ARMv6)
            {
                Log.LogError("Target architecture ARMv6 is no longer supported in Xamarin.iOS. Please select a supported architecture.");
                return(null);
            }

            if (IsClassic && minimumOSVersion < IPhoneSdkVersion.V3_1 && architectures.HasFlag(TargetArchitecture.ARMv7))
            {
                Log.LogWarning(null, null, null, AppManifest.ItemSpec, 0, 0, 0, 0, "Deployment Target changed from iOS {0} to iOS 3.1 (minimum requirement for ARMv7)", minimumOSVersion);
                minimumOSVersion = IPhoneSdkVersion.V3_1;
            }

            if (!string.IsNullOrEmpty(IntermediateOutputPath))
            {
                Directory.CreateDirectory(IntermediateOutputPath);

                args.Add("--cache");
                args.AddQuoted(Path.GetFullPath(IntermediateOutputPath));
            }

            if (IsClassic || IPhoneSdks.MonoTouch.Version < new IPhoneSdkVersion(8, 5, 0))
            {
                args.Add("--nomanifest");
                args.Add("--nosign");
            }

            args.Add(SdkIsSimulator ? "--sim" : "--dev");
            args.AddQuoted(Path.GetFullPath(AppBundleDir));

            if (AppleSdkSettings.XcodeVersion.Major >= 5 && IPhoneSdks.MonoTouch.Version.CompareTo(new IPhoneSdkVersion(6, 3, 7)) < 0)
            {
                args.Add("--compiler", "clang");
            }

            args.Add("--executable");
            args.AddQuoted(ExecutableName);

            if (IsAppExtension)
            {
                args.Add("--extension");
            }

            if (Debug)
            {
                if (FastDev && IPhoneSdks.MonoTouch.SupportsFastDev)
                {
                    args.Add("--fastdev");
                }

                args.Add("--debug");
            }

            if (Profiling)
            {
                args.Add("--profiling");
            }

            if (LinkerDumpDependencies)
            {
                args.Add("--linkerdumpdependencies");
            }

            switch (LinkMode.ToLowerInvariant())
            {
            case "sdkonly": args.Add("--linksdkonly"); break;

            case "none":    args.Add("--nolink"); break;
            }

            if (!string.IsNullOrEmpty(I18n))
            {
                args.Add("--i18n");
                args.AddQuotedFormat(I18n);
            }

            args.Add("--sdkroot");
            args.AddQuoted(SdkRoot);

            args.Add("--sdk");
            args.AddQuoted(SdkVersion);

            if (!minimumOSVersion.IsUseDefault)
            {
                args.Add("--targetver");
                args.AddQuoted(minimumOSVersion.ToString());
            }

            if (UseFloat32 /* We want to compile 32-bit floating point code to use 32-bit floating point operations */)
            {
                args.Add("--aot-options=-O=float32");
            }

            if (IPhoneSdks.MonoTouch.SupportsGenericValueTypeSharing)
            {
                if (!EnableGenericValueTypeSharing)
                {
                    args.Add("--gsharedvt=false");
                }
            }

            if (LinkDescriptions != null)
            {
                foreach (var desc in LinkDescriptions)
                {
                    args.AddQuoted(string.Format("--xml={0}", desc.ItemSpec));
                }
            }

            if (EnableBitcode)
            {
                switch (Framework)
                {
                case PlatformFramework.WatchOS:
                    args.Add("--bitcode=full");
                    break;

                case PlatformFramework.TVOS:
                    args.Add("--bitcode=asmonly");
                    break;

                default:
                    throw new InvalidOperationException(string.Format("Bitcode is currently not supported on {0}.", Framework));
                }
            }

            if (!string.IsNullOrEmpty(HttpClientHandler))
            {
                args.Add(string.Format("--http-message-handler={0}", HttpClientHandler));
            }

            if (!string.IsNullOrEmpty(TLSProvider))
            {
                args.Add(string.Format("--tls-provider={0}", TLSProvider.ToLowerInvariant()));
            }

            string thumb = UseThumb && UseLlvm ? "+thumb2" : "";
            string llvm  = UseLlvm ? "+llvm" : "";
            string abi   = "";

            if (SdkIsSimulator)
            {
                if (architectures.HasFlag(TargetArchitecture.i386))
                {
                    abi += (abi.Length > 0 ? "," : "") + "i386";
                }

                if (architectures.HasFlag(TargetArchitecture.x86_64))
                {
                    abi += (abi.Length > 0 ? "," : "") + "x86_64";
                }

                if (string.IsNullOrEmpty(abi))
                {
                    architectures = TargetArchitecture.i386;
                    abi           = "i386";
                }
            }
            else
            {
                if (architectures == TargetArchitecture.Default)
                {
                    architectures = TargetArchitecture.ARMv7;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7" + llvm + thumb;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7s))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7s" + llvm + thumb;
                }

                if (architectures.HasFlag(TargetArchitecture.ARM64))
                {
                    // Note: ARM64 does not have thumb.
                    abi += (abi.Length > 0 ? "," : "") + "arm64" + llvm;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7k))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7k" + llvm;
                }

                if (string.IsNullOrEmpty(abi))
                {
                    abi = "armv7" + llvm + thumb;
                }
            }

            // Output the CompiledArchitectures
            CompiledArchitectures = architectures.ToString();

            args.Add("--abi=" + abi);

            // output symbols to preserve when stripping
            args.Add("--symbollist");
            args.AddQuoted(Path.GetFullPath(SymbolsList));

            // don't have mtouch generate the dsyms...
            args.Add("--dsym=no");

            if (!string.IsNullOrEmpty(ArchiveSymbols) && bool.TryParse(ArchiveSymbols.Trim(), out msym))
            {
                args.Add("--msym=" + (msym ? "yes" : "no"));
            }

            var gcc = new GccOptions();

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var    extraArgs = ProcessArgumentBuilder.Parse(ExtraArgs);
                var    target    = MainAssembly.ItemSpec;
                string projectDir;

                if (ProjectDir.StartsWith("~/", StringComparison.Ordinal))
                {
                    // Note: Since the Visual Studio plugin doesn't know the user's home directory on the Mac build host,
                    // it simply uses paths relative to "~/". Expand these paths to their full path equivalents.
                    var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

                    projectDir = Path.Combine(home, ProjectDir.Substring(2));
                }
                else
                {
                    projectDir = ProjectDir;
                }

                var customTags = new Dictionary <string, string> (StringComparer.OrdinalIgnoreCase)
                {
                    { "projectdir", projectDir },
                    // Apparently msbuild doesn't propagate the solution path, so we can't get it.
                    // { "solutiondir",  proj.ParentSolution != null ? proj.ParentSolution.BaseDirectory : proj.BaseDirectory },
                    { "appbundledir", AppBundleDir },
                    { "targetpath", Path.Combine(Path.GetDirectoryName(target), Path.GetFileName(target)) },
                    { "targetdir", Path.GetDirectoryName(target) },
                    { "targetname", Path.GetFileName(target) },
                    { "targetext", Path.GetExtension(target) },
                };

                for (int i = 0; i < extraArgs.Length; i++)
                {
                    if (extraArgs[i] == "-gcc_flags" || extraArgs[i] == "--gcc_flags")
                    {
                        // user-defined -gcc_flags argument
                        if (i + 1 < extraArgs.Length && !string.IsNullOrEmpty(extraArgs[i + 1]))
                        {
                            var gccArgs = ProcessArgumentBuilder.Parse(extraArgs[i + 1]);

                            for (int j = 0; j < gccArgs.Length; j++)
                            {
                                gcc.Arguments.Add(StringParserService.Parse(gccArgs[j], customTags));
                            }
                        }

                        i++;
                    }
                    else
                    {
                        // other user-defined mtouch arguments
                        args.AddQuoted(StringParserService.Parse(extraArgs[i], customTags));
                    }
                }
            }

            BuildNativeReferenceFlags(gcc);
            BuildEntitlementFlags(gcc);

            foreach (var framework in gcc.Frameworks)
            {
                args.Add("-framework");
                args.AddQuoted(framework);
            }

            foreach (var framework in gcc.WeakFrameworks)
            {
                args.Add("-weak-framework");
                args.AddQuoted(framework);
            }

            if (gcc.Cxx)
            {
                args.Add("--cxx");
            }

            if (gcc.Arguments.Length > 0)
            {
                args.Add("--gcc_flags");
                args.AddQuoted(gcc.Arguments.ToString());
            }

            foreach (var asm in References)
            {
                args.Add("-r");
                if (IsFrameworkItem(asm))
                {
                    args.AddQuoted(ResolveFrameworkFile(asm.ItemSpec));
                }
                else
                {
                    args.AddQuoted(Path.GetFullPath(asm.ItemSpec));
                }
            }

            foreach (var ext in AppExtensionReferences)
            {
                args.Add("--app-extension");
                args.AddQuoted(Path.GetFullPath(ext.ItemSpec));
            }

            args.Add("--target-framework");
            args.Add(TargetFrameworkIdentifier + "," + TargetFrameworkVersion);

            args.AddQuoted(MainAssembly.ItemSpec);

            // We give the priority to the ExtraArgs to set the mtouch verbosity.
            if (string.IsNullOrEmpty(ExtraArgs) || (!string.IsNullOrEmpty(ExtraArgs) && !ExtraArgs.Contains("-q") && !ExtraArgs.Contains("-v")))
            {
                args.Add(GetVerbosityLevel(Verbosity));
            }

            if (!string.IsNullOrWhiteSpace(License))
            {
                args.Add(string.Format("--license={0}", License));
            }

            return(args.ToString());
        }
        protected override string GenerateCommandLineCommands()
        {
            var           args          = GenerateCommandLineArguments();
            List <string> unescapedArgs = new List <string> ();

            TargetArchitecture architectures;

            if (string.IsNullOrEmpty(Architectures) || !Enum.TryParse(Architectures, out architectures))
            {
                architectures = TargetArchitecture.Default;
            }

            if (architectures == TargetArchitecture.ARMv6)
            {
                Log.LogError(MSBStrings.E0053);
                return(null);
            }

            args.AddQuotedLine((SdkIsSimulator ? "--sim=" : "--dev=") + Path.GetFullPath(AppBundleDir));

            if (AppleSdkSettings.XcodeVersion.Major >= 5 && IPhoneSdks.MonoTouch.Version.CompareTo(new IPhoneSdkVersion(6, 3, 7)) < 0)
            {
                args.AddLine("--compiler=clang");
            }

            args.AddQuotedLine($"--executable={ExecutableName}");

            if (IsAppExtension)
            {
                args.AddLine("--extension");
            }

            if (Debug)
            {
                if (FastDev && !SdkIsSimulator)
                {
                    args.AddLine("--fastdev");
                }
            }

            if (LinkerDumpDependencies)
            {
                args.AddLine("--linkerdumpdependencies");
            }

            if (!string.IsNullOrEmpty(Interpreter))
            {
                args.AddLine($"--interpreter={Interpreter}");
            }

            switch (LinkMode.ToLowerInvariant())
            {
            case "sdkonly": args.AddLine("--linksdkonly"); break;

            case "none":    args.AddLine("--nolink"); break;
            }

            args.AddQuotedLine($"--sdk={SdkVersion}");

            if (!minimumOSVersion.IsUseDefault)
            {
                args.AddQuotedLine($"--targetver={minimumOSVersion.ToString ()}");
            }

            if (UseFloat32 /* We want to compile 32-bit floating point code to use 32-bit floating point operations */)
            {
                args.AddLine("--aot-options=-O=float32");
            }
            else
            {
                args.AddLine("--aot-options=-O=-float32");
            }

            if (LinkDescriptions != null)
            {
                foreach (var desc in LinkDescriptions)
                {
                    args.AddQuotedLine($"--xml={desc.ItemSpec}");
                }
            }

            if (EnableBitcode)
            {
                switch (Platform)
                {
                case ApplePlatform.WatchOS:
                    args.AddLine("--bitcode=full");
                    break;

                case ApplePlatform.TVOS:
                    args.AddLine("--bitcode=asmonly");
                    break;

                default:
                    throw new InvalidOperationException(string.Format("Bitcode is currently not supported on {0}.", Platform));
                }
            }

            string thumb = UseThumb && UseLlvm ? "+thumb2" : "";
            string llvm  = UseLlvm ? "+llvm" : "";
            string abi   = "";

            if (SdkIsSimulator)
            {
                if (architectures.HasFlag(TargetArchitecture.i386))
                {
                    abi += (abi.Length > 0 ? "," : "") + "i386";
                }

                if (architectures.HasFlag(TargetArchitecture.x86_64))
                {
                    abi += (abi.Length > 0 ? "," : "") + "x86_64";
                }

                if (string.IsNullOrEmpty(abi))
                {
                    architectures = TargetArchitecture.i386;
                    abi           = "i386";
                }
            }
            else
            {
                if (architectures == TargetArchitecture.Default)
                {
                    architectures = TargetArchitecture.ARMv7;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7" + llvm + thumb;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7s))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7s" + llvm + thumb;
                }

                if (architectures.HasFlag(TargetArchitecture.ARM64))
                {
                    // Note: ARM64 does not have thumb.
                    abi += (abi.Length > 0 ? "," : "") + "arm64" + llvm;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7k))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7k" + llvm;
                }

                if (architectures.HasFlag(TargetArchitecture.ARM64_32))
                {
                    abi += (abi.Length > 0 ? "," : "") + "arm64_32" + llvm;
                }

                if (string.IsNullOrEmpty(abi))
                {
                    abi = "armv7" + llvm + thumb;
                }
            }

            // Output the CompiledArchitectures
            CompiledArchitectures = architectures.ToString();

            args.AddLine($"--abi={abi}");

            // output symbols to preserve when stripping
            args.AddQuotedLine($"--symbollist={Path.GetFullPath (SymbolsList)}");

            // don't have mtouch generate the dsyms...
            args.AddLine("--dsym=no");

            var gcc = new GccOptions();

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var    extraArgs = CommandLineArgumentBuilder.Parse(ExtraArgs);
                var    target    = MainAssembly.ItemSpec;
                string projectDir;

                if (ProjectDir.StartsWith("~/", StringComparison.Ordinal))
                {
                    // Note: Since the Visual Studio plugin doesn't know the user's home directory on the Mac build host,
                    // it simply uses paths relative to "~/". Expand these paths to their full path equivalents.
                    var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

                    projectDir = Path.Combine(home, ProjectDir.Substring(2));
                }
                else
                {
                    projectDir = ProjectDir;
                }

                var customTags = new Dictionary <string, string> (StringComparer.OrdinalIgnoreCase)
                {
                    { "projectdir", projectDir },
                    // Apparently msbuild doesn't propagate the solution path, so we can't get it.
                    // { "solutiondir",  proj.ParentSolution != null ? proj.ParentSolution.BaseDirectory : proj.BaseDirectory },
                    { "appbundledir", AppBundleDir },
                    { "targetpath", Path.Combine(Path.GetDirectoryName(target), Path.GetFileName(target)) },
                    { "targetdir", Path.GetDirectoryName(target) },
                    { "targetname", Path.GetFileName(target) },
                    { "targetext", Path.GetExtension(target) },
                };

                for (int i = 0; i < extraArgs.Length; i++)
                {
                    var argument   = extraArgs[i];
                    int startIndex = 0;

                    while (argument.Length > startIndex && argument[startIndex] == '-')
                    {
                        startIndex++;
                    }

                    int endIndex = startIndex;
                    while (endIndex < argument.Length && argument[endIndex] != '=')
                    {
                        endIndex++;
                    }

                    int length = endIndex - startIndex;

                    if (length == 9 && string.CompareOrdinal(argument, startIndex, "gcc_flags", 0, 9) == 0)
                    {
                        // user-defined -gcc_flags argument
                        string flags = null;

                        if (endIndex < extraArgs[i].Length)
                        {
                            flags = Unquote(argument, endIndex + 1);
                        }
                        else if (i + 1 < extraArgs.Length)
                        {
                            flags = extraArgs[++i];
                        }

                        if (!string.IsNullOrEmpty(flags))
                        {
                            var gccArgs = CommandLineArgumentBuilder.Parse(flags);

                            for (int j = 0; j < gccArgs.Length; j++)
                            {
                                gcc.Arguments.Add(StringParserService.Parse(gccArgs[j], customTags));
                            }
                        }
                    }
                    else
                    {
                        // other user-defined mtouch arguments
                        unescapedArgs.Add(StringParserService.Parse(argument, customTags));
                    }
                }
            }

            BuildNativeReferenceFlags(gcc);
            BuildEntitlementFlags(gcc);

            foreach (var framework in gcc.Frameworks)
            {
                args.AddQuotedLine($"--framework={framework}");
            }

            foreach (var framework in gcc.WeakFrameworks)
            {
                args.AddQuotedLine($"--weak-framework={framework}");
            }

            if (gcc.Cxx)
            {
                args.AddLine("--cxx");
            }

            if (gcc.Arguments.Length > 0)
            {
                unescapedArgs.Add($"--gcc_flags={gcc.Arguments.ToString ()}");
            }

            foreach (var asm in References)
            {
                if (IsFrameworkItem(asm))
                {
                    args.AddQuotedLine($"--reference={ResolveFrameworkFile (asm.ItemSpec)}");
                }
                else
                {
                    args.AddQuotedLine($"--reference={Path.GetFullPath (asm.ItemSpec)}");
                }
            }

            foreach (var ext in AppExtensionReferences)
            {
                args.AddQuotedLine($"--app-extension={Path.GetFullPath (ext.ItemSpec)}");
            }

            if (!string.IsNullOrWhiteSpace(License))
            {
                args.AddLine($"--license={License}");
            }

            return(CreateResponseFile(args, unescapedArgs));
        }
Exemple #4
0
        void BuildNativeReferenceFlags(GccOptions gcc)
        {
            if (NativeReferences == null)
            {
                return;
            }

            foreach (var item in NativeReferences)
            {
                var value = item.GetMetadata("Kind");
                NativeReferenceKind kind;
                bool boolean;

                if (string.IsNullOrEmpty(value) || !Enum.TryParse(value, out kind))
                {
                    Log.LogWarning("Unknown native reference type for '{0}'.", item.ItemSpec);
                    continue;
                }

                if (kind == NativeReferenceKind.Static)
                {
                    var libName = Path.GetFileName(item.ItemSpec);

                    if (libName.EndsWith(".a", StringComparison.Ordinal))
                    {
                        libName = libName.Substring(0, libName.Length - 2);
                    }

                    if (libName.StartsWith("lib", StringComparison.Ordinal))
                    {
                        libName = libName.Substring(3);
                    }

                    if (!string.IsNullOrEmpty(Path.GetDirectoryName(item.ItemSpec)))
                    {
                        gcc.Arguments.AddQuoted("-L" + Path.GetDirectoryName(item.ItemSpec));
                    }

                    gcc.Arguments.AddQuoted("-l" + libName);

                    value = item.GetMetadata("ForceLoad");

                    if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean)
                    {
                        gcc.Arguments.Add("-force_load");
                        gcc.Arguments.AddQuoted(item.ItemSpec);
                    }

                    value = item.GetMetadata("IsCxx");

                    if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean)
                    {
                        gcc.Cxx = true;
                    }
                }
                else if (kind == NativeReferenceKind.Framework)
                {
                    gcc.Frameworks.Add(item.ItemSpec);
                }
                else
                {
                    Log.LogWarning("Dynamic native references are not supported: '{0}'", item.ItemSpec);
                    continue;
                }

                value = item.GetMetadata("NeedsGccExceptionHandling");
                if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean)
                {
                    if (!gcc.Arguments.Contains("-lgcc_eh"))
                    {
                        gcc.Arguments.Add("-lgcc_eh");
                    }
                }

                value = item.GetMetadata("WeakFrameworks");
                if (!string.IsNullOrEmpty(value))
                {
                    foreach (var framework in value.Split(' ', '\t'))
                    {
                        gcc.WeakFrameworks.Add(framework);
                    }
                }

                value = item.GetMetadata("Frameworks");
                if (!string.IsNullOrEmpty(value))
                {
                    foreach (var framework in value.Split(' ', '\t'))
                    {
                        gcc.Frameworks.Add(framework);
                    }
                }

                // Note: these get merged into gccArgs by our caller
                value = item.GetMetadata("LinkerFlags");
                if (!string.IsNullOrEmpty(value))
                {
                    var linkerFlags = ProcessArgumentBuilder.Parse(value);

                    foreach (var flag in linkerFlags)
                    {
                        gcc.Arguments.AddQuoted(flag);
                    }
                }
            }
        }
Exemple #5
0
        protected override string GenerateCommandLineCommands()
        {
            var           args          = new CommandLineArgumentBuilder();
            List <string> unescapedArgs = new List <string> ();

            TargetArchitecture architectures;
            bool msym;

            if (string.IsNullOrEmpty(Architectures) || !Enum.TryParse(Architectures, out architectures))
            {
                architectures = TargetArchitecture.Default;
            }

            if (architectures == TargetArchitecture.ARMv6)
            {
                Log.LogError("Target architecture ARMv6 is no longer supported in Xamarin.iOS. Please select a supported architecture.");
                return(null);
            }

            if (!string.IsNullOrEmpty(IntermediateOutputPath))
            {
                Directory.CreateDirectory(IntermediateOutputPath);

                args.AddQuotedLine($"--cache={Path.GetFullPath (IntermediateOutputPath)}");
            }

            args.AddQuotedLine((SdkIsSimulator ? "--sim=" : "--dev=") + Path.GetFullPath(AppBundleDir));

            if (AppleSdkSettings.XcodeVersion.Major >= 5 && IPhoneSdks.MonoTouch.Version.CompareTo(new IPhoneSdkVersion(6, 3, 7)) < 0)
            {
                args.AddLine("--compiler=clang");
            }

            args.AddQuotedLine($"--executable={ExecutableName}");

            if (IsAppExtension)
            {
                args.AddLine("--extension");
            }

            if (Debug)
            {
                if (FastDev && !SdkIsSimulator)
                {
                    args.AddLine("--fastdev");
                }

                args.AddLine("--debug");
            }

            if (Profiling)
            {
                args.AddLine("--profiling");
            }

            if (LinkerDumpDependencies)
            {
                args.AddLine("--linkerdumpdependencies");
            }

            if (EnableSGenConc)
            {
                args.AddLine("--sgen-conc");
            }

            if (!string.IsNullOrEmpty(Interpreter))
            {
                args.Add($"--interpreter={Interpreter}");
            }

            switch (LinkMode.ToLowerInvariant())
            {
            case "sdkonly": args.AddLine("--linksdkonly"); break;

            case "none":    args.AddLine("--nolink"); break;
            }

            if (!string.IsNullOrEmpty(I18n))
            {
                args.AddQuotedLine($"--i18n={I18n}");
            }

            args.AddQuotedLine($"--sdkroot={SdkRoot}");

            args.AddQuotedLine($"--sdk={SdkVersion}");

            if (!minimumOSVersion.IsUseDefault)
            {
                args.AddQuotedLine($"--targetver={minimumOSVersion.ToString ()}");
            }

            if (UseFloat32 /* We want to compile 32-bit floating point code to use 32-bit floating point operations */)
            {
                args.AddLine("--aot-options=-O=float32");
            }
            else
            {
                args.AddLine("--aot-options=-O=-float32");
            }

            if (!EnableGenericValueTypeSharing)
            {
                args.AddLine("--gsharedvt=false");
            }

            if (LinkDescriptions != null)
            {
                foreach (var desc in LinkDescriptions)
                {
                    args.AddQuotedLine($"--xml={desc.ItemSpec}");
                }
            }

            if (EnableBitcode)
            {
                switch (Framework)
                {
                case PlatformFramework.WatchOS:
                    args.AddLine("--bitcode=full");
                    break;

                case PlatformFramework.TVOS:
                    args.AddLine("--bitcode=asmonly");
                    break;

                default:
                    throw new InvalidOperationException(string.Format("Bitcode is currently not supported on {0}.", Framework));
                }
            }

            if (!string.IsNullOrEmpty(HttpClientHandler))
            {
                args.AddLine($"--http-message-handler={HttpClientHandler}");
            }

            string thumb = UseThumb && UseLlvm ? "+thumb2" : "";
            string llvm  = UseLlvm ? "+llvm" : "";
            string abi   = "";

            if (SdkIsSimulator)
            {
                if (architectures.HasFlag(TargetArchitecture.i386))
                {
                    abi += (abi.Length > 0 ? "," : "") + "i386";
                }

                if (architectures.HasFlag(TargetArchitecture.x86_64))
                {
                    abi += (abi.Length > 0 ? "," : "") + "x86_64";
                }

                if (string.IsNullOrEmpty(abi))
                {
                    architectures = TargetArchitecture.i386;
                    abi           = "i386";
                }
            }
            else
            {
                if (architectures == TargetArchitecture.Default)
                {
                    architectures = TargetArchitecture.ARMv7;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7" + llvm + thumb;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7s))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7s" + llvm + thumb;
                }

                if (architectures.HasFlag(TargetArchitecture.ARM64))
                {
                    // Note: ARM64 does not have thumb.
                    abi += (abi.Length > 0 ? "," : "") + "arm64" + llvm;
                }

                if (architectures.HasFlag(TargetArchitecture.ARMv7k))
                {
                    abi += (abi.Length > 0 ? "," : "") + "armv7k" + llvm;
                }

                if (string.IsNullOrEmpty(abi))
                {
                    abi = "armv7" + llvm + thumb;
                }
            }

            // Output the CompiledArchitectures
            CompiledArchitectures = architectures.ToString();

            args.AddLine($"--abi={abi}");

            // output symbols to preserve when stripping
            args.AddQuotedLine($"--symbollist={Path.GetFullPath (SymbolsList)}");

            // don't have mtouch generate the dsyms...
            args.AddLine("--dsym=no");

            if (!string.IsNullOrEmpty(ArchiveSymbols) && bool.TryParse(ArchiveSymbols.Trim(), out msym))
            {
                args.AddLine($"--msym={(msym ? "yes" : "no")}");
            }

            var gcc = new GccOptions();

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var    extraArgs = CommandLineArgumentBuilder.Parse(ExtraArgs);
                var    target    = MainAssembly.ItemSpec;
                string projectDir;

                if (ProjectDir.StartsWith("~/", StringComparison.Ordinal))
                {
                    // Note: Since the Visual Studio plugin doesn't know the user's home directory on the Mac build host,
                    // it simply uses paths relative to "~/". Expand these paths to their full path equivalents.
                    var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

                    projectDir = Path.Combine(home, ProjectDir.Substring(2));
                }
                else
                {
                    projectDir = ProjectDir;
                }

                var customTags = new Dictionary <string, string> (StringComparer.OrdinalIgnoreCase)
                {
                    { "projectdir", projectDir },
                    // Apparently msbuild doesn't propagate the solution path, so we can't get it.
                    // { "solutiondir",  proj.ParentSolution != null ? proj.ParentSolution.BaseDirectory : proj.BaseDirectory },
                    { "appbundledir", AppBundleDir },
                    { "targetpath", Path.Combine(Path.GetDirectoryName(target), Path.GetFileName(target)) },
                    { "targetdir", Path.GetDirectoryName(target) },
                    { "targetname", Path.GetFileName(target) },
                    { "targetext", Path.GetExtension(target) },
                };

                for (int i = 0; i < extraArgs.Length; i++)
                {
                    var argument   = extraArgs[i];
                    int startIndex = 0;

                    while (argument.Length > startIndex && argument[startIndex] == '-')
                    {
                        startIndex++;
                    }

                    int endIndex = startIndex;
                    while (endIndex < argument.Length && argument[endIndex] != '=')
                    {
                        endIndex++;
                    }

                    int length = endIndex - startIndex;

                    if (length == 9 && string.CompareOrdinal(argument, startIndex, "gcc_flags", 0, 9) == 0)
                    {
                        // user-defined -gcc_flags argument
                        string flags = null;

                        if (endIndex < extraArgs[i].Length)
                        {
                            flags = Unquote(argument, endIndex + 1);
                        }
                        else if (i + 1 < extraArgs.Length)
                        {
                            flags = extraArgs[++i];
                        }

                        if (!string.IsNullOrEmpty(flags))
                        {
                            var gccArgs = CommandLineArgumentBuilder.Parse(flags);

                            for (int j = 0; j < gccArgs.Length; j++)
                            {
                                gcc.Arguments.Add(StringParserService.Parse(gccArgs[j], customTags));
                            }
                        }
                    }
                    else
                    {
                        // other user-defined mtouch arguments
                        unescapedArgs.Add(StringParserService.Parse(argument, customTags));
                    }
                }
            }

            BuildNativeReferenceFlags(gcc);
            BuildEntitlementFlags(gcc);

            foreach (var framework in gcc.Frameworks)
            {
                args.AddQuotedLine($"--framework={framework}");
            }

            foreach (var framework in gcc.WeakFrameworks)
            {
                args.AddQuotedLine($"--weak-framework={framework}");
            }

            if (gcc.Cxx)
            {
                args.AddLine("--cxx");
            }

            if (gcc.Arguments.Length > 0)
            {
                unescapedArgs.Add($"--gcc_flags={gcc.Arguments.ToString ()}");
            }

            foreach (var asm in References)
            {
                if (IsFrameworkItem(asm))
                {
                    args.AddQuotedLine($"-r={ResolveFrameworkFile (asm.ItemSpec)}");
                }
                else
                {
                    args.AddQuotedLine($"-r={Path.GetFullPath (asm.ItemSpec)}");
                }
            }

            foreach (var ext in AppExtensionReferences)
            {
                args.AddQuotedLine($"--app-extension={Path.GetFullPath (ext.ItemSpec)}");
            }

            args.AddLine($"--target-framework={TargetFrameworkIdentifier},{TargetFrameworkVersion}");

            args.AddQuotedLine($"--root-assembly={Path.GetFullPath (MainAssembly.ItemSpec)}");

            // We give the priority to the ExtraArgs to set the mtouch verbosity.
            if (string.IsNullOrEmpty(ExtraArgs) || (!string.IsNullOrEmpty(ExtraArgs) && !ExtraArgs.Contains("-q") && !ExtraArgs.Contains("-v")))
            {
                args.AddLine(GetVerbosityLevel(Verbosity));
            }

            if (!string.IsNullOrWhiteSpace(License))
            {
                args.AddLine($"--license={License}");
            }

            // Generate a response file
            var responseFile = Path.GetFullPath(ResponseFilePath);

            if (File.Exists(responseFile))
            {
                File.Delete(responseFile);
            }

            try {
                using (var fs = File.Create(responseFile)) {
                    using (var writer = new StreamWriter(fs))
                        writer.Write(args);
                }
            } catch (Exception ex) {
                Log.LogWarning("Failed to create response file '{0}': {1}", responseFile, ex);
            }

            // Some arguments can not safely go in the response file and are
            // added separately. They must go _after_ the response file
            // as they may override options passed in the response file
            var actualArgs = new CommandLineArgumentBuilder();

            actualArgs.AddQuoted($"@{responseFile}");

            foreach (var arg in unescapedArgs)
            {
                actualArgs.AddQuoted(arg);
            }

            return(actualArgs.ToString());
        }
Exemple #6
0
        void BuildNativeReferenceFlags(GccOptions gcc)
        {
            if (NativeReferences == null)
                return;

            foreach (var item in NativeReferences) {
                var value = item.GetMetadata ("Kind");
                NativeReferenceKind kind;
                bool boolean;

                if (string.IsNullOrEmpty (value) || !Enum.TryParse (value, out kind)) {
                    Log.LogWarning ("Unknown native reference type for '{0}'.", item.ItemSpec);
                    continue;
                }

                if (kind == NativeReferenceKind.Static) {
                    var libName = Path.GetFileName (item.ItemSpec);

                    if (libName.EndsWith (".a", StringComparison.Ordinal))
                        libName = libName.Substring (0, libName.Length - 2);

                    if (libName.StartsWith ("lib", StringComparison.Ordinal))
                        libName = libName.Substring (3);

                    if (!string.IsNullOrEmpty (Path.GetDirectoryName (item.ItemSpec)))
                        gcc.Arguments.AddQuoted ("-L" + Path.GetDirectoryName (item.ItemSpec));

                    gcc.Arguments.AddQuoted ("-l" + libName);

                    value = item.GetMetadata ("ForceLoad");

                    if (!string.IsNullOrEmpty (value) && bool.TryParse (value, out boolean) && boolean) {
                        gcc.Arguments.Add ("-force_load");
                        gcc.Arguments.AddQuoted (item.ItemSpec);
                    }

                    value = item.GetMetadata ("IsCxx");

                    if (!string.IsNullOrEmpty (value) && bool.TryParse (value, out boolean) && boolean)
                        gcc.Cxx = true;
                } else if (kind == NativeReferenceKind.Framework) {
                    gcc.Frameworks.Add (item.ItemSpec);
                } else {
                    Log.LogWarning ("Dynamic native references are not supported: '{0}'", item.ItemSpec);
                    continue;
                }

                value = item.GetMetadata ("NeedsGccExceptionHandling");
                if (!string.IsNullOrEmpty (value) && bool.TryParse (value, out boolean) && boolean) {
                    if (!gcc.Arguments.Contains ("-lgcc_eh"))
                        gcc.Arguments.Add ("-lgcc_eh");
                }

                value = item.GetMetadata ("WeakFrameworks");
                if (!string.IsNullOrEmpty (value)) {
                    foreach (var framework in value.Split (' ', '\t'))
                        gcc.WeakFrameworks.Add (framework);
                }

                value = item.GetMetadata ("Frameworks");
                if (!string.IsNullOrEmpty (value)) {
                    foreach (var framework in value.Split (' ', '\t'))
                        gcc.Frameworks.Add (framework);
                }

                // Note: these get merged into gccArgs by our caller
                value = item.GetMetadata ("LinkerFlags");
                if (!string.IsNullOrEmpty (value)) {
                    var linkerFlags = ProcessArgumentBuilder.Parse (value);

                    foreach (var flag in linkerFlags)
                        gcc.Arguments.AddQuoted (flag);
                }
            }
        }
Exemple #7
0
 void BuildEntitlementFlags(GccOptions gcc)
 {
     if (SdkIsSimulator && !string.IsNullOrEmpty (CompiledEntitlements) && EntitlementsRequireLinkerFlags (CompiledEntitlements)) {
         gcc.Arguments.AddQuoted (new [] { "-Xlinker", "-sectcreate", "-Xlinker", "__TEXT", "-Xlinker", "__entitlements" });
         gcc.Arguments.Add ("-Xlinker");
         gcc.Arguments.AddQuoted (Path.GetFullPath (CompiledEntitlements));
     }
 }
Exemple #8
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new ProcessArgumentBuilder ();
            TargetArchitecture architectures;

            if (string.IsNullOrEmpty (Architectures) || !Enum.TryParse (Architectures, out architectures))
                architectures = TargetArchitecture.Default;

            if (architectures == TargetArchitecture.ARMv6) {
                Log.LogError ("Target architecture ARMv6 is no longer supported in Xamarin.iOS. Please select a supported architecture.");
                return null;
            }

            if (IsClassic && minimumOSVersion < IPhoneSdkVersion.V3_1 && architectures.HasFlag (TargetArchitecture.ARMv7)) {
                Log.LogWarning (null, null, null, AppManifest.ItemSpec, 0, 0, 0, 0, "Deployment Target changed from iOS {0} to iOS 3.1 (minimum requirement for ARMv7)", minimumOSVersion);
                minimumOSVersion = IPhoneSdkVersion.V3_1;
            }

            if (!string.IsNullOrEmpty (IntermediateOutputPath)) {
                Directory.CreateDirectory (IntermediateOutputPath);

                args.Add ("--cache");
                args.AddQuoted (Path.GetFullPath (IntermediateOutputPath));
            }

            if (IsClassic || IPhoneSdks.MonoTouch.Version < new IPhoneSdkVersion (8, 5, 0)) {
                args.Add ("--nomanifest");
                args.Add ("--nosign");
            }

            args.Add (SdkIsSimulator ? "--sim" : "--dev");
            args.AddQuoted (Path.GetFullPath (AppBundleDir));

            if (AppleSdkSettings.XcodeVersion.Major >= 5 && IPhoneSdks.MonoTouch.Version.CompareTo (new IPhoneSdkVersion (6, 3, 7)) < 0)
                args.Add ("--compiler", "clang");

            args.Add ("--executable");
            args.AddQuoted (ExecutableName);

            if (IsAppExtension)
                args.Add ("--extension");

            if (Debug) {
                if (FastDev && IPhoneSdks.MonoTouch.SupportsFastDev)
                    args.Add ("--fastdev");

                args.Add ("--debug");
            }

            if (Profiling)
                args.Add ("--profiling");

            if (LinkerDumpDependencies)
                args.Add ("--linkerdumpdependencies");

            switch (LinkMode.ToLowerInvariant ()) {
            case "sdkonly": args.Add ("--linksdkonly"); break;
            case "none":    args.Add ("--nolink"); break;
            }

            if (!string.IsNullOrEmpty (I18n)) {
                args.Add ("--i18n");
                args.AddQuotedFormat (I18n);
            }

            args.Add ("--sdkroot");
            args.AddQuoted (SdkRoot);

            args.Add ("--sdk");
            args.AddQuoted (SdkVersion);

            if (!minimumOSVersion.IsUseDefault) {
                args.Add ("--targetver");
                args.AddQuoted (minimumOSVersion.ToString ());
            }

            if (UseFloat32 /* We want to compile 32-bit floating point code to use 32-bit floating point operations */)
                args.Add ("--aot-options=-O=float32");

            if (IPhoneSdks.MonoTouch.SupportsGenericValueTypeSharing) {
                if (!EnableGenericValueTypeSharing)
                    args.Add ("--gsharedvt=false");
            }

            if (LinkDescriptions != null) {
                foreach (var desc in LinkDescriptions)
                    args.AddQuoted (string.Format ("--xml={0}", desc.ItemSpec));
            }

            if (EnableBitcode) {
                switch (Framework) {
                case PlatformFramework.WatchOS:
                    args.Add ("--bitcode=full");
                    break;
                case PlatformFramework.TVOS:
                    args.Add ("--bitcode=asmonly");
                    break;
                default:
                    throw new InvalidOperationException (string.Format ("Bitcode is currently not supported on {0}.", Framework));
                }
            }

            if (!string.IsNullOrEmpty (HttpClientHandler))
                args.Add (string.Format ("--http-message-handler={0}", HttpClientHandler));

            if (!string.IsNullOrEmpty (TLSProvider))
                args.Add (string.Format ("--tls-provider={0}", TLSProvider.ToLowerInvariant()));

            string thumb = UseThumb && UseLlvm ? "+thumb2" : "";
            string llvm = UseLlvm ? "+llvm" : "";
            string abi = "";

            if (SdkIsSimulator) {
                if (architectures.HasFlag (TargetArchitecture.i386))
                    abi += (abi.Length > 0 ? "," : "") + "i386";

                if (architectures.HasFlag (TargetArchitecture.x86_64))
                    abi += (abi.Length > 0 ? "," : "") + "x86_64";

                if (string.IsNullOrEmpty (abi)) {
                    architectures = TargetArchitecture.i386;
                    abi = "i386";
                }
            } else {
                if (architectures == TargetArchitecture.Default)
                    architectures = TargetArchitecture.ARMv7;

                if (architectures.HasFlag (TargetArchitecture.ARMv7))
                    abi += (abi.Length > 0 ? "," : "") + "armv7" + llvm + thumb;

                if (architectures.HasFlag (TargetArchitecture.ARMv7s))
                    abi += (abi.Length > 0 ? "," : "") + "armv7s" + llvm + thumb;

                if (architectures.HasFlag (TargetArchitecture.ARM64)) {
                    // Note: ARM64 does not have thumb.
                    abi += (abi.Length > 0 ? "," : "") + "arm64" + llvm;
                }

                if (architectures.HasFlag (TargetArchitecture.ARMv7k))
                    abi += (abi.Length > 0 ? "," : "") + "armv7k";

                if (string.IsNullOrEmpty (abi))
                    abi = "armv7" + llvm + thumb;
            }

            // Output the CompiledArchitectures
            CompiledArchitectures = architectures.ToString ();

            args.Add ("--abi=" + abi);

            // output symbols to preserve when stripping
            args.Add ("--symbollist");
            args.AddQuoted (Path.GetFullPath (SymbolsList));

            // don't have mtouch generate the dsyms...
            args.Add ("--dsym=no");

            var gcc = new GccOptions ();

            if (!string.IsNullOrEmpty (ExtraArgs)) {
                var extraArgs = ProcessArgumentBuilder.Parse (ExtraArgs);
                var target = MainAssembly.ItemSpec;
                string projectDir;

                if (ProjectDir.StartsWith ("~/", StringComparison.Ordinal)) {
                    // Note: Since the Visual Studio plugin doesn't know the user's home directory on the Mac build host,
                    // it simply uses paths relative to "~/". Expand these paths to their full path equivalents.
                    var home = Environment.GetFolderPath (Environment.SpecialFolder.UserProfile);

                    projectDir = Path.Combine (home, ProjectDir.Substring (2));
                } else {
                    projectDir = ProjectDir;
                }

                var customTags = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase) {
                    { "projectdir",   projectDir },
                    // Apparently msbuild doesn't propagate the solution path, so we can't get it.
                    // { "solutiondir",  proj.ParentSolution != null ? proj.ParentSolution.BaseDirectory : proj.BaseDirectory },
                    { "appbundledir", AppBundleDir },
                    { "targetpath",   Path.Combine (Path.GetDirectoryName (target), Path.GetFileName (target)) },
                    { "targetdir",    Path.GetDirectoryName (target) },
                    { "targetname",   Path.GetFileName (target) },
                    { "targetext",    Path.GetExtension (target) },
                };

                for (int i = 0; i < extraArgs.Length; i++) {
                    if (extraArgs[i] == "-gcc_flags" || extraArgs[i] == "--gcc_flags") {
                        // user-defined -gcc_flags argument
                        if (i + 1 < extraArgs.Length && !string.IsNullOrEmpty (extraArgs[i + 1])) {
                            var gccArgs = ProcessArgumentBuilder.Parse (extraArgs[i + 1]);

                            for (int j = 0; j < gccArgs.Length; j++)
                                gcc.Arguments.Add (StringParserService.Parse (gccArgs[j], customTags));
                        }

                        i++;
                    } else {
                        // other user-defined mtouch arguments
                        args.AddQuoted (StringParserService.Parse (extraArgs[i], customTags));
                    }
                }
            }

            BuildNativeReferenceFlags (gcc);
            BuildEntitlementFlags (gcc);

            foreach (var framework in gcc.Frameworks) {
                args.Add ("-framework");
                args.AddQuoted (framework);
            }

            foreach (var framework in gcc.WeakFrameworks) {
                args.Add ("-weak-framework");
                args.AddQuoted (framework);
            }

            if (gcc.Cxx)
                args.Add ("--cxx");

            if (gcc.Arguments.Length > 0) {
                args.Add ("--gcc_flags");
                args.AddQuoted (gcc.Arguments.ToString ());
            }

            foreach (var asm in References) {
                args.Add ("-r");
                if (IsFrameworkItem(asm)) {
                    args.AddQuoted (ResolveFrameworkFile(asm.ItemSpec));
                } else {
                    args.AddQuoted (Path.GetFullPath (asm.ItemSpec));
                }
            }

            foreach (var ext in AppExtensionReferences) {
                args.Add ("--app-extension");
                args.AddQuoted (Path.GetFullPath (ext.ItemSpec));
            }

            args.Add ("--target-framework");
            args.Add (TargetFrameworkIdentifier + "," + TargetFrameworkVersion);

            args.AddQuoted (MainAssembly.ItemSpec);

            // We give the priority to the ExtraArgs to set the mtouch verbosity.
            if (string.IsNullOrEmpty (ExtraArgs) || (!string.IsNullOrEmpty (ExtraArgs) && !ExtraArgs.Contains ("-q") && !ExtraArgs.Contains ("-v")))
                args.Add (GetVerbosityLevel (Verbosity));

            if (!string.IsNullOrWhiteSpace (License))
                args.Add (string.Format("--license={0}", License));

            return args.ToString ();
        }
Exemple #9
0
        void BuildNativeReferenceFlags(GccOptions gcc)
        {
            if (NativeReferences == null)
            {
                return;
            }

            foreach (var item in NativeReferences)
            {
                var value = item.GetMetadata("Kind");
                NativeReferenceKind kind;
                bool boolean;

                if (string.IsNullOrEmpty(value) || !Enum.TryParse(value, out kind))
                {
                    Log.LogWarning(MSBStrings.W0051, item.ItemSpec);
                    continue;
                }

                if (kind == NativeReferenceKind.Static)
                {
                    var libName = Path.GetFileName(item.ItemSpec);

                    if (libName.EndsWith(".a", StringComparison.Ordinal))
                    {
                        libName = libName.Substring(0, libName.Length - 2);
                    }

                    if (libName.StartsWith("lib", StringComparison.Ordinal))
                    {
                        libName = libName.Substring(3);
                    }

                    if (!string.IsNullOrEmpty(Path.GetDirectoryName(item.ItemSpec)))
                    {
                        gcc.Arguments.AddQuoted("-L" + Path.GetDirectoryName(item.ItemSpec));
                    }

                    gcc.Arguments.AddQuoted("-l" + libName);

                    value = item.GetMetadata("ForceLoad");

                    if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean)
                    {
                        gcc.Arguments.Add("-force_load");
                        gcc.Arguments.AddQuoted(item.ItemSpec);
                    }

                    value = item.GetMetadata("IsCxx");

                    if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean)
                    {
                        gcc.Cxx = true;
                    }
                }
                else if (kind == NativeReferenceKind.Framework)
                {
                    var path = item.ItemSpec;
                    // in case the full path to the library is given (msbuild)
                    if (Path.GetExtension(path) != ".framework")
                    {
                        path = Path.GetDirectoryName(path);
                    }
                    gcc.Frameworks.Add(path);
                }
                else
                {
                    Log.LogWarning(MSBStrings.W0052, item.ItemSpec);
                    continue;
                }

                value = item.GetMetadata("NeedsGccExceptionHandling");
                if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean)
                {
                    if (!gcc.Arguments.Contains("-lgcc_eh"))
                    {
                        gcc.Arguments.Add("-lgcc_eh");
                    }
                }

                value = item.GetMetadata("WeakFrameworks");
                if (!string.IsNullOrEmpty(value))
                {
                    foreach (var framework in value.Split(' ', '\t'))
                    {
                        gcc.WeakFrameworks.Add(framework);
                    }
                }

                value = item.GetMetadata("Frameworks");
                if (!string.IsNullOrEmpty(value))
                {
                    foreach (var framework in value.Split(' ', '\t'))
                    {
                        gcc.Frameworks.Add(framework);
                    }
                }

                // Note: these get merged into gccArgs by our caller
                value = item.GetMetadata("LinkerFlags");
                if (!string.IsNullOrEmpty(value))
                {
                    var linkerFlags = CommandLineArgumentBuilder.Parse(value);

                    foreach (var flag in linkerFlags)
                    {
                        gcc.Arguments.AddQuoted(flag);
                    }
                }
            }
        }