예제 #1
0
        string GetMonoBundleDirName()
        {
            if (!string.IsNullOrEmpty(ExtraArguments))
            {
                var args = CommandLineArgumentBuilder.Parse(ExtraArguments);

                for (int i = 0; i < args.Length; i++)
                {
                    string arg;

                    if (string.IsNullOrEmpty(args[i]))
                    {
                        continue;
                    }

                    if (args[i][0] == '/')
                    {
                        arg = args[i].Substring(1);
                    }
                    else if (args[i][0] == '-')
                    {
                        if (args[i].Length >= 2 && args[i][1] == '-')
                        {
                            arg = args[i].Substring(2);
                        }
                        else
                        {
                            arg = args[i].Substring(1);
                        }
                    }
                    else
                    {
                        continue;
                    }

                    if (arg.StartsWith("custom_bundle_name:", StringComparison.Ordinal) ||
                        arg.StartsWith("custom_bundle_name=", StringComparison.Ordinal))
                    {
                        return(arg.Substring("custom_bundle_name=".Length));
                    }

                    if (arg == "custom_bundle_name" && i + 1 < args.Length)
                    {
                        return(args[i + 1]);
                    }
                }
            }

            return("MonoBundle");
        }
        void AppendExtraArgs(CommandLineArgumentBuilder args, string extraArgs)
        {
            var target = this.MainAssembly.ItemSpec;

            string[] argv       = CommandLineArgumentBuilder.Parse(extraArgs);
            var      customTags = new Dictionary <string, string> (StringComparer.OrdinalIgnoreCase)
            {
                { "projectdir", Path.GetDirectoryName(this.ProjectPath) },
                // Apparently msbuild doesn't propagate the solution path, so we can't get it. - MTouchTaskBase.cs
                //  { "solutiondir",  proj.ParentSolution != null ? proj.ParentSolution.BaseDirectory : proj.BaseDirectory },
                { "appbundledir", this.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 < argv.Length; i++)
            {
                args.AddQuoted(StringParserService.Parse(argv[i], customTags));
            }
        }
예제 #3
0
        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));
        }
예제 #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(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)
                {
                    gcc.Frameworks.Add(item.ItemSpec);
                }
                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);
                    }
                }
            }
        }
예제 #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());
        }
예제 #6
0
        protected override string GenerateCommandLineCommands()
        {
            var args = GenerateCommandLineArguments();

            if (!string.IsNullOrEmpty(OutputPath))
            {
                args.AddQuotedLine("/output:" + Path.GetFullPath(OutputPath));
            }

            if (!string.IsNullOrEmpty(ApplicationName))
            {
                args.AddQuotedLine("/name:" + ApplicationName);
            }

            XamMacArch arch;

            if (!Enum.TryParse(Architecture, true, out arch))
            {
                arch = XamMacArch.Default;
            }

            if (arch == XamMacArch.Default)
            {
                arch = XamMacArch.x86_64;
            }

            if (arch.HasFlag(XamMacArch.i386))
            {
                args.AddLine("/arch:i386");
            }

            if (arch.HasFlag(XamMacArch.x86_64))
            {
                args.AddLine("/arch:x86_64");
            }

            switch ((LinkMode ?? string.Empty).ToLower())
            {
            case "full":
                break;

            case "sdkonly":
                args.AddLine("/linksdkonly");
                break;

            case "platform":
                args.AddLine("/linkplatform");
                break;

            default:
                args.AddLine("/nolink");
                break;
            }

            if (!string.IsNullOrEmpty(AotMode) && AotMode != "None")
            {
                var aot = $"--aot:{AotMode.ToLower ()}";
                if (HybridAOT)
                {
                    aot += "|hybrid";
                }

                if (!string.IsNullOrEmpty(ExplicitAotAssemblies))
                {
                    aot += $",{ExplicitAotAssemblies}";
                }

                args.AddLine(aot);
            }

            if (References != null)
            {
                foreach (var asm in References)
                {
                    args.AddQuotedLine("/reference:" + Path.GetFullPath(asm.ItemSpec));
                }
            }

            if (NativeReferences != null)
            {
                foreach (var nr in NativeReferences)
                {
                    args.AddQuotedLine("/native-reference:" + Path.GetFullPath(nr.ItemSpec));
                }
            }

            if (IsAppExtension)
            {
                args.AddQuotedLine("/extension");
            }
            if (IsXPCService)
            {
                args.AddQuotedLine("/xpc");
            }

            return(CreateResponseFile(args, ExtraArgs == null ? null : CommandLineArgumentBuilder.Parse(ExtraArgs)));
        }
예제 #7
0
        protected override string GenerateCommandLineCommands()
        {
            var cmd = new CommandLineBuilder();

                        #if DEBUG
            cmd.AppendSwitch("/v");
                        #endif

            cmd.AppendSwitch("/nostdlib");
            cmd.AppendSwitchIfNotNull("/baselib:", BaseLibDll);
            cmd.AppendSwitchIfNotNull("/out:", OutputAssembly);

            cmd.AppendSwitchIfNotNull("/attributelib:", AttributeAssembly);

            string dir;
            if (!string.IsNullOrEmpty(BaseLibDll))
            {
                dir = Path.GetDirectoryName(BaseLibDll);
                cmd.AppendSwitchIfNotNull("/lib:", dir);
            }

            if (ProcessEnums)
            {
                cmd.AppendSwitch("/process-enums");
            }

            if (EmitDebugInformation)
            {
                cmd.AppendSwitch("/debug");
            }

            if (AllowUnsafeBlocks)
            {
                cmd.AppendSwitch("/unsafe");
            }

            cmd.AppendSwitchIfNotNull("/ns:", Namespace);

            if (!string.IsNullOrEmpty(DefineConstants))
            {
                var strv      = DefineConstants.Split(new [] { ';' });
                var sanitized = new List <string> ();

                foreach (var str in strv)
                {
                    if (str != string.Empty)
                    {
                        sanitized.Add(str);
                    }
                }

                if (sanitized.Count > 0)
                {
                    cmd.AppendSwitchIfNotNull("/d:", string.Join(";", sanitized.ToArray()));
                }
            }

            //cmd.AppendSwitch ("/e");

            foreach (var item in ApiDefinitions)
            {
                cmd.AppendFileNameIfNotNull(Path.GetFullPath(item.ItemSpec));
            }

            if (CoreSources != null)
            {
                foreach (var item in CoreSources)
                {
                    cmd.AppendSwitchIfNotNull("/s:", Path.GetFullPath(item.ItemSpec));
                }
            }

            if (Sources != null)
            {
                foreach (var item in Sources)
                {
                    cmd.AppendSwitchIfNotNull("/x:", Path.GetFullPath(item.ItemSpec));
                }
            }

            if (AdditionalLibPaths != null)
            {
                foreach (var item in AdditionalLibPaths)
                {
                    cmd.AppendSwitchIfNotNull("/lib:", Path.GetFullPath(item.ItemSpec));
                }
            }

            HandleReferences(cmd);

            if (Resources != null)
            {
                foreach (var item in Resources)
                {
                    var    args = new List <string> ();
                    string id;

                    args.Add(item.ToString());
                    id = item.GetMetadata("LogicalName");
                    if (!string.IsNullOrEmpty(id))
                    {
                        args.Add(id);
                    }

                    cmd.AppendSwitchIfNotNull("/res:", args.ToArray(), ",");
                }
            }

            if (NativeLibraries != null)
            {
                foreach (var item in NativeLibraries)
                {
                    var    args = new List <string> ();
                    string id;

                    args.Add(item.ToString());
                    id = item.GetMetadata("LogicalName");
                    if (string.IsNullOrEmpty(id))
                    {
                        id = Path.GetFileName(args[0]);
                    }
                    args.Add(id);

                    cmd.AppendSwitchIfNotNull("/link-with:", args.ToArray(), ",");
                }
            }

            if (GeneratedSourcesDir != null)
            {
                cmd.AppendSwitchIfNotNull("/tmpdir:", Path.GetFullPath(GeneratedSourcesDir));
            }

            if (GeneratedSourcesFileList != null)
            {
                cmd.AppendSwitchIfNotNull("/sourceonly:", Path.GetFullPath(GeneratedSourcesFileList));
            }

            cmd.AppendSwitch($"/target-framework={TargetFrameworkMoniker}");

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var    extraArgs = CommandLineArgumentBuilder.Parse(ExtraArgs);
                var    target    = OutputAssembly;
                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 },
                };
                // OutputAssembly is optional so it can be null
                if (target != null)
                {
                    var d = Path.GetDirectoryName(target);
                    var n = Path.GetFileName(target);
                    customTags.Add("targetpath", Path.Combine(d, n));
                    customTags.Add("targetdir", d);
                    customTags.Add("targetname", n);
                    customTags.Add("targetext", Path.GetExtension(target));
                }

                for (int i = 0; i < extraArgs.Length; i++)
                {
                    var argument = extraArgs[i];
                    cmd.AppendTextUnquoted(" ");
                    cmd.AppendTextUnquoted(StringParserService.Parse(argument, customTags));
                }
            }

            var v = VerbosityUtils.Merge(ExtraArgs, (LoggerVerbosity)Verbosity);
            if (v.Length > 0)
            {
                foreach (var arg in v)
                {
                    cmd.AppendTextUnquoted(" ");
                    cmd.AppendTextUnquoted(arg);
                }
            }

            return(cmd.ToString());
        }
예제 #8
0
        protected override string GenerateCommandLineCommands()
        {
            var args = GenerateCommandLineArguments();

            if (!string.IsNullOrEmpty(OutputPath))
            {
                args.AddQuotedLine("/output:" + Path.GetFullPath(OutputPath));
            }

            if (!string.IsNullOrEmpty(ApplicationName))
            {
                args.AddQuotedLine("/name:" + ApplicationName);
            }

            XamMacArch arch;

            if (!Enum.TryParse(Architecture, true, out arch))
            {
                arch = XamMacArch.Default;
            }

            if (arch == XamMacArch.Default)
            {
                arch = XamMacArch.x86_64;
            }

            if (arch.HasFlag(XamMacArch.i386))
            {
                args.AddLine("/arch:i386");
            }

            if (arch.HasFlag(XamMacArch.x86_64))
            {
                args.AddLine("/arch:x86_64");
            }

            if (AppManifest != null)
            {
                try {
                    var plist = PDictionary.FromFile(AppManifest.ItemSpec);

                    PString v;
                    string  minimumDeploymentTarget;

                    if (!plist.TryGetValue(ManifestKeys.LSMinimumSystemVersion, out v) || string.IsNullOrEmpty(v.Value))
                    {
                        minimumDeploymentTarget = SdkVersion;
                    }
                    else
                    {
                        minimumDeploymentTarget = v.Value;
                    }

                    args.AddLine(string.Format("/minos={0}", minimumDeploymentTarget));
                }
                catch (Exception ex) {
                    Log.LogWarning(null, null, null, AppManifest.ItemSpec, 0, 0, 0, 0, MSBStrings.E0010, AppManifest.ItemSpec, ex.Message);
                }
            }

            switch ((LinkMode ?? string.Empty).ToLower())
            {
            case "full":
                break;

            case "sdkonly":
                args.AddLine("/linksdkonly");
                break;

            case "platform":
                args.AddLine("/linkplatform");
                break;

            default:
                args.AddLine("/nolink");
                break;
            }

            if (!string.IsNullOrEmpty(AotMode) && AotMode != "None")
            {
                var aot = $"--aot:{AotMode.ToLower ()}";
                if (HybridAOT)
                {
                    aot += "|hybrid";
                }

                if (!string.IsNullOrEmpty(ExplicitAotAssemblies))
                {
                    aot += $",{ExplicitAotAssemblies}";
                }

                args.AddLine(aot);
            }

            if (References != null)
            {
                foreach (var asm in References)
                {
                    args.AddQuotedLine("/assembly:" + Path.GetFullPath(asm.ItemSpec));
                }
            }

            if (NativeReferences != null)
            {
                foreach (var nr in NativeReferences)
                {
                    args.AddQuotedLine("/native-reference:" + Path.GetFullPath(nr.ItemSpec));
                }
            }

            if (IsAppExtension)
            {
                args.AddQuotedLine("/extension");
            }
            if (IsXPCService)
            {
                args.AddQuotedLine("/xpc");
            }

            return(CreateResponseFile(args, ExtraArgs == null ? null : CommandLineArgumentBuilder.Parse(ExtraArgs)));
        }
        public override bool Execute()
        {
            if (string.IsNullOrEmpty(NoSymbolStrip))
            {
                NoSymbolStrip = "false";
            }

            if (string.IsNullOrEmpty(NoDSymUtil))
            {
                NoDSymUtil = "false";
            }

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var           args = CommandLineArgumentBuilder.Parse(ExtraArgs);
                List <string> xml  = null;

                for (int i = 0; i < args.Length; i++)
                {
                    var arg = args [i];

                    if (string.IsNullOrEmpty(arg))
                    {
                        continue;
                    }

                    var index = 1;
                    if (arg [0] == '/')
                    {
                        // nothing to do
                    }
                    else if (arg [0] == '-')
                    {
                        if (arg.Length >= 2 && arg [1] == '-')
                        {
                            index++;
                        }
                    }
                    else
                    {
                        continue;
                    }
                    arg = arg.Substring(index);

                    var eq    = arg.IndexOfAny(new char [] { ':', '=' });
                    var value = string.Empty;
                    var name  = arg;
                    if (eq >= 0)
                    {
                        name  = arg.Substring(0, eq);
                        value = arg.Substring(eq + 1);
                    }

                    switch (name)
                    {
                    case "nosymbolstrip":
                        // There's also a version that takes symbols as arguments:
                        // --nosymbolstrip:symbol1,symbol2
                        // in that case we do want to run the SymbolStrip target, so we
                        // do not set the MtouchNoSymbolStrip property to 'true' in that case.
                        NoSymbolStrip = string.IsNullOrEmpty(value) ? "true" : "false";
                        break;

                    case "dsym":
                        NoDSymUtil = ParseBool(value) ? "false" : "true";
                        break;

                    case "verbose":
                    case "v":
                        Verbosity++;
                        break;

                    case "quiet":
                    case "q":
                        Verbosity--;
                        break;

                    case "marshal-managed-exceptions":
                        MarshalManagedExceptionMode = value;
                        break;

                    case "marshal-objectivec-exceptions":
                        MarshalObjectiveCExceptionMode = value;
                        break;

                    case "custom_bundle_name":
                        CustomBundleName = value;
                        break;

                    case "optimize":
                        if (!string.IsNullOrEmpty(Optimize))
                        {
                            Optimize += ",";
                        }
                        Optimize += value;
                        break;

                    case "registrar":
                        Registrar = value;
                        break;

                    case "xml":
                        if (xml == null)
                        {
                            xml = new List <string> ();
                        }
                        xml.Add(value);
                        break;

                    default:
                        break;
                    }
                }

                if (xml != null)
                {
                    var defs = new List <ITaskItem> ();
                    if (XmlDefinitions != null)
                    {
                        defs.AddRange(XmlDefinitions);
                    }
                    foreach (var x in xml)
                    {
                        defs.Add(new TaskItem(x));
                    }
                    XmlDefinitions = defs.ToArray();
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            if (string.IsNullOrEmpty(NoSymbolStrip))
            {
                NoSymbolStrip = "false";
            }

            if (string.IsNullOrEmpty(NoDSymUtil))
            {
                NoDSymUtil = "false";
            }

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var args = CommandLineArgumentBuilder.Parse(ExtraArgs);

                for (int i = 0; i < args.Length; i++)
                {
                    var arg = args [i];

                    if (string.IsNullOrEmpty(arg))
                    {
                        continue;
                    }

                    var index = 1;
                    if (arg [0] == '/')
                    {
                        // nothing to do
                    }
                    else if (arg [0] == '-')
                    {
                        if (arg.Length >= 2 && arg [1] == '-')
                        {
                            index++;
                        }
                    }
                    else
                    {
                        continue;
                    }
                    arg = arg.Substring(index);

                    var eq    = arg.IndexOfAny(new char [] { ':', '=' });
                    var value = string.Empty;
                    var name  = arg;
                    if (eq >= 0)
                    {
                        name  = arg.Substring(0, eq);
                        value = arg.Substring(eq + 1);
                    }

                    switch (name)
                    {
                    case "nosymbolstrip":
                        // There's also a version that takes symbols as arguments:
                        // --nosymbolstrip:symbol1,symbol2
                        // in that case we do want to run the SymbolStrip target, so we
                        // do not set the MtouchNoSymbolStrip property to 'true' in that case.
                        NoSymbolStrip = string.IsNullOrEmpty(value) ? "true" : "false";
                        break;

                    case "dsym":
                        NoDSymUtil = ParseBool(value) ? "false" : "true";
                        break;

                    case "verbose":
                    case "v":
                        Verbosity++;
                        break;

                    case "quiet":
                    case "q":
                        Verbosity--;
                        break;

                    default:
                        break;
                    }
                }
            }

            return(!Log.HasLoggedErrors);
        }
예제 #11
0
        public override bool Execute()
        {
            if (string.IsNullOrEmpty(NoSymbolStrip))
            {
                NoSymbolStrip = "false";
            }

            if (string.IsNullOrEmpty(NoDSymUtil))
            {
                NoDSymUtil = "false";
            }

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var args = CommandLineArgumentBuilder.Parse(ExtraArgs);

                for (int i = 0; i < args.Length; i++)
                {
                    string arg;

                    if (string.IsNullOrEmpty(args[i]))
                    {
                        continue;
                    }

                    if (args[i][0] == '/')
                    {
                        arg = args[i].Substring(1);
                    }
                    else if (args[i][0] == '-')
                    {
                        if (args[i].Length >= 2 && args[i][1] == '-')
                        {
                            arg = args[i].Substring(2);
                        }
                        else
                        {
                            arg = args[i].Substring(1);
                        }
                    }
                    else
                    {
                        continue;
                    }

                    switch (arg)
                    {
                    case "nosymbolstrip":
                        NoSymbolStrip = "true";
                        // There's also a version that takes symbols as arguments:
                        // --nosymbolstrip:symbol1,symbol2
                        // in that case we do want to run the SymbolStrip target, so we
                        // do not set the MtouchNoSymbolStrip property to 'true' in that case.
                        break;

                    case "dsym":
                        NoDSymUtil = "false";
                        break;

                    default:
                        if (arg.StartsWith("dsym:", StringComparison.Ordinal) || arg.StartsWith("dsym=", StringComparison.Ordinal))
                        {
                            NoDSymUtil = ParseBool(arg.Substring(5)) ? "false" : "true";
                        }
                        break;
                    }
                }
            }

            Log.LogTaskProperty("NoSymbolStrip Output", NoSymbolStrip);
            Log.LogTaskProperty("NoDSymUtil Output", NoDSymUtil);

            return(!Log.HasLoggedErrors);
        }
예제 #12
0
        public void BuildNativeReferenceFlags(TaskLoggingHelper Log, ITaskItem[] NativeReferences)
        {
            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)
                {
                    value = item.GetMetadata("ForceLoad");

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

                    Arguments.AddQuoted(item.ItemSpec);

                    value = item.GetMetadata("IsCxx");

                    if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean)
                    {
                        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);
                    }
                    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 (!Arguments.Contains("-lgcc_eh"))
                    {
                        Arguments.Add("-lgcc_eh");
                    }
                }

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

                value = item.GetMetadata("Frameworks");
                if (!string.IsNullOrEmpty(value))
                {
                    foreach (var framework in value.Split(' ', '\t'))
                    {
                        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)
                    {
                        Arguments.AddQuoted(flag);
                    }
                }
            }
        }
예제 #13
0
        public override bool Execute()
        {
            if (string.IsNullOrEmpty(NoSymbolStrip))
            {
                NoSymbolStrip = "false";
            }

            if (string.IsNullOrEmpty(NoDSymUtil))
            {
                NoDSymUtil = "false";
            }

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                var           args            = CommandLineArgumentBuilder.Parse(ExtraArgs);
                List <string> xml             = null;
                List <string> customLinkFlags = null;
                var           envVariables    = new List <ITaskItem> ();
                var           dlsyms          = new List <ITaskItem> ();

                for (int i = 0; i < args.Length; i++)
                {
                    var arg = args [i];

                    if (string.IsNullOrEmpty(arg))
                    {
                        continue;
                    }

                    var index = 1;
                    if (arg [0] == '/')
                    {
                        // nothing to do
                    }
                    else if (arg [0] == '-')
                    {
                        if (arg.Length >= 2 && arg [1] == '-')
                        {
                            index++;
                        }
                    }
                    else
                    {
                        continue;
                    }
                    arg = arg.Substring(index);

                    var separators = new char [] { ':', '=' };
                    var eq         = arg.IndexOfAny(separators);
                    var value      = string.Empty;
                    var name       = arg;
                    var nextValue  = string.Empty;
                    var hasValue   = false;
                    if (eq >= 0)
                    {
                        name     = arg.Substring(0, eq);
                        value    = arg.Substring(eq + 1);
                        hasValue = true;
                    }
                    else if (i < args.Length - 1)
                    {
                        nextValue = args [i + 1];
                    }

                    switch (name)
                    {
                    case "nosymbolstrip":
                        // There's also a version that takes symbols as arguments:
                        // --nosymbolstrip:symbol1,symbol2
                        // in that case we do want to run the SymbolStrip target, so we
                        // do not set the MtouchNoSymbolStrip property to 'true' in that case.
                        NoSymbolStrip = string.IsNullOrEmpty(value) ? "true" : "false";
                        break;

                    case "dlsym":
                        dlsyms.Add(new TaskItem(string.IsNullOrEmpty(value) ? "true" : value));
                        break;

                    case "dsym":
                        NoDSymUtil = ParseBool(value) ? "false" : "true";
                        break;

                    case "verbose":
                    case "v":
                        Verbosity++;
                        break;

                    case "quiet":
                    case "q":
                        Verbosity--;
                        break;

                    case "marshal-managed-exceptions":
                        value = hasValue ? value : nextValue;                         // requires a value, which might be the next option
                        MarshalManagedExceptionMode = value;
                        break;

                    case "marshal-objectivec-exceptions":
                        value = hasValue ? value : nextValue;                         // requires a value, which might be the next option
                        MarshalObjectiveCExceptionMode = value;
                        break;

                    case "custom_bundle_name":
                        value            = hasValue ? value : nextValue;              // requires a value, which might be the next option
                        CustomBundleName = value;
                        break;

                    case "optimize":
                        if (!string.IsNullOrEmpty(Optimize))
                        {
                            Optimize += ",";
                        }
                        Optimize += value;
                        break;

                    case "package-debug-symbols":
                        PackageDebugSymbols = string.IsNullOrEmpty(value) ? "true" : value;
                        break;

                    case "registrar":
                        value     = hasValue ? value : nextValue;                     // requires a value, which might be the next option
                        Registrar = value;
                        break;

                    case "setenv":
                        value = hasValue ? value : nextValue;                         // requires a value, which might be the next option
                        var colon = value.IndexOfAny(separators);
                        var item  = new TaskItem(value.Substring(0, colon));
                        item.SetMetadata("Value", value.Substring(colon + 1));
                        envVariables.Add(item);
                        break;

                    case "xml":
                        if (xml == null)
                        {
                            xml = new List <string> ();
                        }
                        value = hasValue ? value : nextValue;                         // requires a value, which might be the next option
                        xml.Add(value);
                        break;

                    case "nostrip":
                        // Output is EnableAssemblyILStripping so we enable if --nostrip=false and disable if true
                        NoStrip = ParseBool(value) ? "false" : "true";
                        break;

                    case "gcc_flags":                     // mtouch uses gcc_flags
                    case "link_flags":                    // mmp uses link_flags
                        if (!StringUtils.TryParseArguments(value, out var lf, out var ex))
                        {
                            Log.LogError(MSBStrings.E0189 /* Could not parse the custom linker argument(s) '-{0}': {1} */, $"-{name}={value}", ex.Message);
                            continue;
                        }
                        if (customLinkFlags is null)
                        {
                            customLinkFlags = new List <string> ();
                        }
                        customLinkFlags.AddRange(lf);
                        break;

                    default:
                        Log.LogMessage(MessageImportance.Low, "Skipping unknown argument '{0}' with value '{1}'", name, value);
                        break;
                    }
                }

                if (xml != null)
                {
                    var defs = new List <ITaskItem> ();
                    if (XmlDefinitions != null)
                    {
                        defs.AddRange(XmlDefinitions);
                    }
                    foreach (var x in xml)
                    {
                        defs.Add(new TaskItem(x));
                    }
                    XmlDefinitions = defs.ToArray();
                }

                if (customLinkFlags is not null)
                {
                    var defs = new List <ITaskItem> ();
                    if (CustomLinkFlags is not null)
                    {
                        defs.AddRange(CustomLinkFlags);
                    }
                    foreach (var lf in customLinkFlags)
                    {
                        defs.Add(new TaskItem(lf));
                    }
                    CustomLinkFlags = defs.ToArray();
                }

                if (envVariables.Count > 0)
                {
                    if (EnvironmentVariables != null)
                    {
                        envVariables.AddRange(EnvironmentVariables);
                    }
                    EnvironmentVariables = envVariables.ToArray();
                }

                if (dlsyms.Count > 0)
                {
                    if (DlSym != null)
                    {
                        dlsyms.AddRange(DlSym);
                    }
                    DlSym = dlsyms.ToArray();
                }
            }

            return(!Log.HasLoggedErrors);
        }