Пример #1
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            if (Recursive)
            {
                args.Add("-r");
            }

            if (Symlinks)
            {
                args.Add("-y");
            }

            args.AddQuoted(OutputFile.GetMetadata("FullPath"));

            var root = WorkingDirectory.GetMetadata("FullPath");

            for (int i = 0; i < Sources.Length; i++)
            {
                var relative = PathUtils.AbsoluteToRelative(root, Sources[i].GetMetadata("FullPath"));
                args.AddQuoted(relative);
            }

            return(args.ToString());
        }
Пример #2
0
        protected override void AppendCommandLineArguments(IDictionary <string, string> environment, CommandLineArgumentBuilder args, ITaskItem[] items)
        {
            environment.Add("IBSC_MINIMUM_COMPATIBILITY_VERSION", minimumDeploymentTarget);
            environment.Add("IBC_MINIMUM_COMPATIBILITY_VERSION", minimumDeploymentTarget);

            if (AppleSdkSettings.XcodeVersion.Major >= 5)
            {
                args.Add("--minimum-deployment-target", minimumDeploymentTarget);
            }

            foreach (var targetDevice in GetTargetDevices(plist))
            {
                args.Add("--target-device", targetDevice);
            }

            if (AppleSdkSettings.XcodeVersion.Major >= 6 && AutoActivateCustomFonts)
            {
                args.Add("--auto-activate-custom-fonts");
            }

            if (!string.IsNullOrEmpty(SdkRoot))
            {
                args.Add("--sdk");
                args.AddQuoted(SdkRoot);
            }
        }
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("--verify");
            args.Add("-vvvv");

            switch (Platform)
            {
            case ApplePlatform.iOS:
            case ApplePlatform.TVOS:
            case ApplePlatform.WatchOS:
            case ApplePlatform.MacCatalyst:
                args.AddQuoted("-R=anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] exists and (certificate leaf[field.1.2.840.113635.100.6.1.2] exists or certificate leaf[field.1.2.840.113635.100.6.1.4] exists)");
                break;

            case ApplePlatform.MacOSX:
                args.Add("--deep");
                break;

            default:
                throw new InvalidOperationException(string.Format(MSBStrings.InvalidPlatform, Platform));
            }

            args.AddQuoted(Resource);

            return(args.ToString());
        }
        int CopySceneKitAssets(string scnassets, string output, string intermediate)
        {
            var environment = new Dictionary <string, string> ();
            var args        = new CommandLineArgumentBuilder();

            environment.Add("PATH", DeveloperRootBinDir);
            environment.Add("DEVELOPER_DIR", SdkDevPath);
            environment.Add("XCODE_DEVELOPER_USR_PATH", DeveloperRootBinDir);

            args.AddQuoted(Path.GetFullPath(scnassets));
            args.Add("-o");
            args.AddQuoted(Path.GetFullPath(output));
            args.AddQuotedFormat("--sdk-root={0}", SdkRoot);

            if (AppleSdkSettings.XcodeVersion.Major >= 10)
            {
                var platform = PlatformUtils.GetTargetPlatform(SdkPlatform, IsWatchApp);
                if (platform != null)
                {
                    args.Add("--target-platform", platform);
                }

                args.AddQuotedFormat("--target-version={0}", SdkVersion);
            }
            else
            {
                args.AddQuotedFormat("--target-version-{0}={1}", OperatingSystem, SdkVersion);
            }
            args.AddQuotedFormat("--target-build-dir={0}", Path.GetFullPath(intermediate));

            var startInfo = GetProcessStartInfo(environment, GetFullPathToTool(), args.ToString());

            try {
                using (var process = new Process()) {
                    Log.LogMessage(MessageImportance.Normal, "Tool {0} execution started with arguments: {1}", startInfo.FileName, startInfo.Arguments);

                    process.StartInfo           = startInfo;
                    process.OutputDataReceived += (sender, e) => {
                        if (e.Data == null)
                        {
                            return;
                        }

                        Log.LogMessage(MessageImportance.Low, "{0}", e.Data);
                    };

                    process.Start();
                    process.BeginOutputReadLine();
                    process.WaitForExit();

                    Log.LogMessage(MessageImportance.Low, "Tool {0} execution finished.", startInfo.FileName);

                    return(process.ExitCode);
                }
            } catch (Exception ex) {
                Log.LogError("Error executing tool '{0}': {1}", startInfo.FileName, ex.Message);
                return(-1);
            }
        }
        int Compile(ITaskItem item, string outputDir, string log, string partialPlist)
        {
            var environment = new Dictionary <string, string> ();
            var args        = new CommandLineArgumentBuilder();

            args.Add("compile");
            args.AddQuoted(item.ItemSpec);
            args.AddQuoted(Path.GetFullPath(outputDir));
            args.Add("--output-partial-info-plist");
            args.AddQuoted(partialPlist);

            var startInfo = GetProcessStartInfo(environment, GetFullPathToTool(), args.ToString());
            var errors    = new StringBuilder();
            int exitCode;

            try {
                Log.LogMessage(MessageImportance.Normal, MSBStrings.M0001, startInfo.FileName, startInfo.Arguments);

                using (var stdout = File.CreateText(log)) {
                    using (var stderr = new StringWriter(errors)) {
                        using (var process = ProcessUtils.StartProcess(startInfo, stdout, stderr)) {
                            process.Wait();

                            exitCode = process.Result;
                        }
                    }

                    Log.LogMessage(MessageImportance.Low, MSBStrings.M0002, startInfo.FileName, exitCode);
                }
            } catch (Exception ex) {
                Log.LogError("Error executing tool '{0}': {1}", startInfo.FileName, ex.Message);
                File.Delete(log);
                return(-1);
            }

            if (exitCode != 0)
            {
                // Note: coremlc exited with an error. Dump everything we can to help the user
                // diagnose the issue and then delete the log file so that rebuilding tries
                // again.
                if (errors.Length > 0)
                {
                    Log.LogError(null, null, null, item.ItemSpec, 0, 0, 0, 0, "{0}", errors);
                }

                Log.LogError(MSBStrings.E0117, ToolName, exitCode);

                // Note: If the log file exists, log those warnings/errors as well...
                if (File.Exists(log))
                {
                    Log.LogError(null, null, null, item.ItemSpec, 0, 0, 0, 0, "{0}", File.ReadAllText(log));
                    File.Delete(log);
                }
            }

            return(exitCode);
        }
        // Note: Xamarin.Mac and Xamarin.iOS should both override this method to do pass platform-specific verify rules
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("--verify");
            args.Add("-vvvv");

            args.AddQuoted(Resource);

            return(args.ToString());
        }
Пример #7
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("--verify");
            args.Add("-vvvv");
            args.Add("-R='anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] exists and (certificate leaf[field.1.2.840.113635.100.6.1.2] exists or certificate leaf[field.1.2.840.113635.100.6.1.4] exists)'");

            args.AddQuoted(Resource);

            return(args.ToString());
        }
Пример #8
0
        string GenerateCommandLineArguments(ITaskItem item)
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("-v");
            args.Add("--force");

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

            if (UseHardenedRuntime)
            {
                args.Add("-o runtime");
            }

            args.Add("--sign");
            args.AddQuoted(SigningKey);

            if (!string.IsNullOrEmpty(Keychain))
            {
                args.Add("--keychain");
                args.AddQuoted(Path.GetFullPath(Keychain));
            }

            if (!string.IsNullOrEmpty(ResourceRules))
            {
                args.Add("--resource-rules");
                args.AddQuoted(Path.GetFullPath(ResourceRules));
            }

            if (!string.IsNullOrEmpty(Entitlements))
            {
                args.Add("--entitlements");
                args.AddQuoted(Path.GetFullPath(Entitlements));
            }

            if (DisableTimestamp)
            {
                args.Add("--timestamp=none");
            }

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                args.Add(ExtraArgs);
            }

            args.AddQuoted(Path.GetFullPath(item.ItemSpec));

            return(args.ToString());
        }
Пример #9
0
        protected override string GenerateCommandLineCommands()
        {
            var prefixes     = BundleResource.SplitResourcePrefixes(ResourcePrefix);
            var intermediate = Path.Combine(IntermediateOutputPath, ToolName);
            var logicalName  = BundleResource.GetLogicalName(ProjectDir, prefixes, SourceFile, !string.IsNullOrEmpty(SessionId));
            var path         = Path.Combine(intermediate, logicalName);
            var args         = new CommandLineArgumentBuilder();
            var dir          = Path.GetDirectoryName(path);

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            OutputFile = new TaskItem(Path.ChangeExtension(path, ".air"));
            OutputFile.SetMetadata("LogicalName", Path.ChangeExtension(logicalName, ".air"));

            args.Add("-arch", "air64");
            args.Add("-emit-llvm");
            args.Add("-c");
            args.Add("-gline-tables-only");
            args.Add("-ffast-math");
            args.Add(string.Format("-std={0}-metal1.0", OperatingSystem));

            args.Add("-serialize-diagnostics");
            args.AddQuoted(Path.ChangeExtension(path, ".dia"));

            args.Add("-o");
            args.AddQuoted(Path.ChangeExtension(path, ".air"));

            args.AddQuoted(SourceFile.ItemSpec);

            return(args.ToString());
        }
Пример #10
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("--compress");
            args.AddQuoted(InputScene);
            args.Add("-o");
            args.AddQuoted(OutputScene);
            args.AddQuotedFormat("--sdk-root={0}", SdkRoot);
            args.AddQuotedFormat("--target-version-{0}={1}", OperatingSystem, SdkVersion);
            args.AddQuotedFormat("--target-build-dir={0}", IntermediateOutputPath);

            return(args.ToString());
        }
Пример #11
0
        protected override string GenerateCommandLineCommands()
        {
            var    prefixes     = BundleResource.SplitResourcePrefixes(ResourcePrefix);
            var    intermediate = Path.Combine(IntermediateOutputPath, ToolName);
            var    logicalName  = BundleResource.GetLogicalName(ProjectDir, prefixes, SourceFile, !string.IsNullOrEmpty(SessionId));
            var    path         = Path.Combine(intermediate, logicalName);
            var    args         = new CommandLineArgumentBuilder();
            var    dir          = Path.GetDirectoryName(path);
            string minimumDeploymentTarget;

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

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

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

            OutputFile = new TaskItem(Path.ChangeExtension(path, ".air"));
            OutputFile.SetMetadata("LogicalName", Path.ChangeExtension(logicalName, ".air"));

            args.Add("-arch", "air64");
            args.Add("-emit-llvm");
            args.Add("-c");
            args.Add("-gline-tables-only");
            args.Add("-ffast-math");

            args.Add("-serialize-diagnostics");
            args.AddQuoted(Path.ChangeExtension(path, ".dia"));

            args.Add("-o");
            args.AddQuoted(Path.ChangeExtension(path, ".air"));

            args.Add(string.Format("-m{0}-version-min={1}", OperatingSystem, minimumDeploymentTarget));

            args.AddQuoted(SourceFile.ItemSpec);

            return(args.ToString());
        }
        protected override string GenerateCommandLineCommands()
        {
            Log.LogMessage("Creating installer package");

            var args = new CommandLineArgumentBuilder();

            if (!string.IsNullOrEmpty(ProductDefinition))
            {
                args.Add("--product");
                args.AddQuoted(Path.GetFullPath(ProductDefinition));
            }

            args.Add("--component");
            args.AddQuoted(Path.Combine(OutputDirectory, Path.GetFileName(AppBundleDir)));
            args.Add("/Applications");

            if (EnablePackageSigning)
            {
                args.Add("--sign");
                args.AddQuoted(GetPackageSigningCertificateCommonName());
            }

            if (!string.IsNullOrEmpty(PackagingExtraArgs))
            {
                try {
                    AppendExtraArgs(args, PackagingExtraArgs);
                } catch (FormatException) {
                    Log.LogError(MSBStrings.E0123);
                    return(string.Empty);
                }
            }

            if (string.IsNullOrEmpty(PkgPackagePath))
            {
                string projectVersion = GetProjectVersion();
                string target         = string.Format("{0}{1}.pkg", Name, String.IsNullOrEmpty(projectVersion) ? "" : "-" + projectVersion);
                PkgPackagePath = Path.Combine(OutputDirectory, target);
            }
            args.AddQuoted(PkgPackagePath);

            return(args.ToString());
        }
Пример #13
0
        protected override string GenerateCommandLineCommands()
        {
            var prefixes     = BundleResource.SplitResourcePrefixes(ResourcePrefix);
            var intermediate = Path.Combine(IntermediateOutputPath, ToolName);
            var logicalName  = BundleResource.GetLogicalName(ProjectDir, prefixes, SourceFile, !string.IsNullOrEmpty(SessionId));
            var path         = Path.Combine(intermediate, logicalName);
            var args         = new CommandLineArgumentBuilder();
            var dir          = Path.GetDirectoryName(path);

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            OutputFile = new TaskItem(Path.ChangeExtension(path, ".air"));
            OutputFile.SetMetadata("LogicalName", Path.ChangeExtension(logicalName, ".air"));

            args.Add("-arch", "air64");
            args.Add("-emit-llvm");
            args.Add("-c");
            args.Add("-gline-tables-only");
            args.Add("-ffast-math");

            args.Add("-serialize-diagnostics");
            args.AddQuoted(Path.ChangeExtension(path, ".dia"));

            args.Add("-o");
            args.AddQuoted(Path.ChangeExtension(path, ".air"));

            if (Platform == ApplePlatform.MacCatalyst)
            {
                args.Add($"-target");
                args.Add($"air64-apple-ios{MinimumOSVersion}-macabi");
            }
            else
            {
                args.Add(PlatformFrameworkHelper.GetMinimumVersionArgument(TargetFrameworkMoniker, SdkIsSimulator, MinimumOSVersion));
            }
            args.AddQuoted(SourceFile.ItemSpec);

            return(args.ToString());
        }
Пример #14
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("-rsrc");

            args.AddQuoted(Source.ItemSpec);
            args.AddQuoted(Destination.ItemSpec);

            return(args.ToString());
        }
        string GenerateCommandLineArguments(string dylib)
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("-v");
            args.Add("--force");

            args.Add("--sign");
            args.AddQuoted(SigningKey);

            if (!string.IsNullOrEmpty(Keychain))
            {
                args.Add("--keychain");
                args.AddQuoted(Path.GetFullPath(Keychain));
            }

            if (DisableTimestamp)
            {
                args.Add("--timestamp=none");
            }

            if (!string.IsNullOrEmpty(ExtraArgs))
            {
                args.Add(ExtraArgs);
            }

            args.AddQuoted(dylib);

            return(args.ToString());
        }
Пример #16
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.AddQuoted(Source !.ItemSpec);
            args.AddQuoted(Destination !.ItemSpec);
            if (!string.IsNullOrEmpty(AdditionalArguments))
            {
                args.Add(AdditionalArguments);
            }

            return(args.ToString());
        }
Пример #17
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("-r");
            args.AddQuoted(Archive.ItemSpec);

            foreach (var item in Items)
            {
                args.AddQuoted(item.ItemSpec);
            }

            return(args.ToString());
        }
Пример #18
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("--compress");
            args.AddQuoted(InputScene);
            args.Add("-o");
            args.AddQuoted(OutputScene);
            args.AddQuotedFormat("--sdk-root={0}", SdkRoot);
            args.AddQuotedFormat("--target-build-dir={0}", IntermediateOutputPath);
            if (AppleSdkSettings.XcodeVersion.Major >= 13)
            {
                // I'm not sure which Xcode version these options are available in, but it's at least Xcode 13+
                args.AddQuotedFormat("--target-version={0}", SdkVersion);
                args.AddQuotedFormat("--target-platform={0}", PlatformUtils.GetTargetPlatform(SdkPlatform, IsWatchApp));
            }
            else
            {
                args.AddQuotedFormat("--target-version-{0}={1}", OperatingSystem, SdkVersion);
            }

            return(args.ToString());
        }
Пример #19
0
        static bool IsCodesigned(string path)
        {
            var psi  = new ProcessStartInfo("/usr/bin/codesign");
            var args = new CommandLineArgumentBuilder();

            args.Add("--verify");
            args.AddQuoted(path);

            psi.Arguments = args.ToString();

            var process = Process.Start(psi);

            process.WaitForExit();

            return(process.ExitCode == 0);
        }
Пример #20
0
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add(ALToolAction);
            args.Add("--file");
            args.AddQuoted(FilePath);
            args.Add("--type");
            args.AddQuoted(GetFileTypeValue());
            args.Add("--username");
            args.AddQuoted(Username);
            args.Add("--password");
            args.AddQuoted(Password);
            args.Add("--output-format");
            args.Add("xml");

            return(args.ToString());
        }
        protected override string GenerateCommandLineCommands()
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("-r", "-y");
            args.AddQuoted(OutputFile.GetMetadata("FullPath"));
            args.AddQuoted("META-INF");

            long size  = 0;
            int  count = 0;

            foreach (var path in Directory.EnumerateFileSystemEntries(Source.ItemSpec))
            {
                if (Directory.Exists(path))
                {
                    foreach (var item in Directory.EnumerateFiles(path))
                    {
                        var info = new FileInfo(item);

                        size += info.Length;
                        count++;
                    }
                }
                else
                {
                    var info = new FileInfo(path);

                    size += info.Length;
                }

                args.AddQuoted(Path.GetFileName(path));
                count++;
            }

            SaveMetaFile(count, size);

            return(args.ToString());
        }
Пример #22
0
        protected static int Ditto(string source, string destination)
        {
            var args = new CommandLineArgumentBuilder();

            args.Add("-rsrc");

            args.AddQuoted(source);
            args.AddQuoted(destination);

            var psi = new ProcessStartInfo("/usr/bin/ditto", args.ToString())
            {
                RedirectStandardOutput = false,
                RedirectStandardError  = false,
                UseShellExecute        = false,
                CreateNoWindow         = true,
            };

            using (var process = Process.Start(psi)) {
                process.WaitForExit();

                return(process.ExitCode);
            }
        }
Пример #23
0
        protected int Compile(ITaskItem[] items, string output, ITaskItem manifest)
        {
            var environment = new Dictionary <string, string> ();
            var args        = new CommandLineArgumentBuilder();

            if (!string.IsNullOrEmpty(SdkBinPath))
            {
                environment.Add("PATH", SdkBinPath);
            }

            if (!string.IsNullOrEmpty(SdkUsrPath))
            {
                environment.Add("XCODE_DEVELOPER_USR_PATH", SdkUsrPath);
            }

            if (!string.IsNullOrEmpty(SdkDevPath))
            {
                environment.Add("DEVELOPER_DIR", SdkDevPath);
            }

            // workaround for ibtool[d] bug / asserts if Intel version is loaded
            string tool;

            if (IsTranslated())
            {
                // we force the Intel (translated) msbuild process to launch ibtool as "Apple"
                tool = "arch";
                args.Add("-arch", "arm64e");
                args.Add("/usr/bin/xcrun");
            }
            else
            {
                tool = "/usr/bin/xcrun";
            }
            args.Add(ToolName);
            args.Add("--errors", "--warnings", "--notices");
            args.Add("--output-format", "xml1");

            AppendCommandLineArguments(environment, args, items);

            if (Link)
            {
                args.Add("--link");
            }
            else if (UseCompilationDirectory)
            {
                args.Add("--compilation-directory");
            }
            else
            {
                args.Add("--compile");
            }

            args.AddQuoted(Path.GetFullPath(output));

            foreach (var item in items)
            {
                args.AddQuoted(item.GetMetadata("FullPath"));
            }

            var arguments = args.ToList();
            var rv        = ExecuteAsync(tool, arguments, sdkDevPath, environment: environment, mergeOutput: false).Result;
            var exitCode  = rv.ExitCode;
            var messages  = rv.StandardOutput.ToString();

            File.WriteAllText(manifest.ItemSpec, messages);

            if (exitCode != 0)
            {
                // Note: ibtool or actool exited with an error. Dump everything we can to help the user
                // diagnose the issue and then delete the manifest log file so that rebuilding tries
                // again (in case of ibtool's infamous spurious errors).
                var errors = rv.StandardError.ToString();
                if (errors.Length > 0)
                {
                    Log.LogError(null, null, null, items[0].ItemSpec, 0, 0, 0, 0, "{0}", errors);
                }

                Log.LogError(MSBStrings.E0117, ToolName, exitCode);

                // Note: If the log file exists and is parseable, log those warnings/errors as well...
                if (File.Exists(manifest.ItemSpec))
                {
                    try {
                        var plist = PDictionary.FromFile(manifest.ItemSpec);

                        LogWarningsAndErrors(plist, items[0]);
                    } catch (Exception ex) {
                        Log.LogError(MSBStrings.E0094, ToolName, manifest.ItemSpec, ex.Message);
                    }

                    File.Delete(manifest.ItemSpec);
                }
            }

            return(exitCode);
        }
Пример #24
0
        protected override string GenerateCommandLineCommands()
        {
            var  args = new CommandLineArgumentBuilder();
            bool msym;

            args.AddLine("/verbose");

            if (Debug)
            {
                args.AddLine("/debug");
            }

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

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

            if (TargetFrameworkIdentifier == "Xamarin.Mac")
            {
                args.AddLine("/profile:Xamarin.Mac,Version=v2.0,Profile=Mobile");
            }
            else if (UseXamMacFullFramework)
            {
                args.AddLine($"/profile:Xamarin.Mac,Version={TargetFrameworkVersion},Profile=Full");
            }
            else
            {
                args.AddLine($"/profile:Xamarin.Mac,Version={TargetFrameworkVersion},Profile=System");
            }

            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 (!string.IsNullOrEmpty(ArchiveSymbols) && bool.TryParse(ArchiveSymbols.Trim(), out msym))
            {
                args.AddLine("--msym:" + (msym ? "yes" : "no"));
            }

            args.AddLine(string.Format("--http-message-handler={0}", HttpClientHandler));

            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, "Error loading '{0}': {1}", AppManifest.ItemSpec, ex.Message);
                }
            }

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

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

            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 (!string.IsNullOrEmpty(I18n))
            {
                args.AddQuotedLine("/i18n:" + I18n);
            }

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

            if (!string.IsNullOrEmpty(ApplicationAssembly.ItemSpec))
            {
                args.AddQuotedLine("/root-assembly:" + Path.GetFullPath(ApplicationAssembly.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");
            }

            args.AddQuotedLine("/sdkroot:" + SdkRoot);

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

                args.AddQuotedLine("--cache:" + Path.GetFullPath(IntermediateOutputPath));
            }

            // 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}");

            if (!string.IsNullOrWhiteSpace(ExtraArguments))
            {
                actualArgs.Add(ExtraArguments);
            }

            return(actualArgs.ToString());
        }
        protected string GenerateCommandLineCommands()
        {
            var sb = new CommandLineArgumentBuilder();

            if (!string.IsNullOrEmpty(LaunchApp))
            {
                sb.Add(SdkIsSimulator ? "--launchsim" : "--launchdev");
                sb.AddQuoted(LaunchApp);
            }

            if (!string.IsNullOrEmpty(InstallApp))
            {
                sb.Add(SdkIsSimulator ? "--installsim" : "--installdev");
                sb.AddQuoted(InstallApp);
            }

            if (SdkIsSimulator && string.IsNullOrEmpty(DeviceName))
            {
                var    simruntime     = $"com.apple.CoreSimulator.SimRuntime.{PlatformName}-{SdkVersion.Replace ('.', '-')}";
                var    simdevicetypes = GetDeviceTypes();
                string simdevicetype;

                if (simdevicetypes?.Count > 0)
                {
                    // Use the latest device type we can find. This seems to be what Xcode does by default.
                    simdevicetype = simdevicetypes.Last();
                }
                else
                {
                    // We couldn't find any device types, so pick one.
                    switch (Platform)
                    {
                    case ApplePlatform.iOS:
                        // Don't try to launch an iPad-only app on an iPhone
                        if (DeviceType == IPhoneDeviceType.IPad)
                        {
                            simdevicetype = "com.apple.CoreSimulator.SimDeviceType.iPad--7th-generation-";
                        }
                        else
                        {
                            simdevicetype = "com.apple.CoreSimulator.SimDeviceType.iPhone-11";
                        }
                        break;

                    case ApplePlatform.TVOS:
                        simdevicetype = "com.apple.CoreSimulator.SimDeviceType.Apple-TV-4K-1080p";
                        break;

                    case ApplePlatform.WatchOS:
                        simdevicetype = "com.apple.CoreSimulator.SimDeviceType.Apple-Watch-Series-5-40mm";
                        break;

                    default:
                        throw new InvalidOperationException($"Invalid platform: {Platform}");
                    }
                }
                DeviceName = $":v2:runtime={simruntime},devicetype={simdevicetype}";
            }

            if (!string.IsNullOrEmpty(DeviceName))
            {
                if (SdkIsSimulator)
                {
                    sb.Add("--device");
                }
                else
                {
                    sb.Add("--devname");
                }
                sb.AddQuoted(DeviceName);
            }

            if (CaptureOutput && string.IsNullOrEmpty(StandardOutputPath))
            {
                StandardOutputPath = GetTerminalName(1);
            }

            if (CaptureOutput && string.IsNullOrEmpty(StandardErrorPath))
            {
                StandardErrorPath = GetTerminalName(2);
            }

            if (!string.IsNullOrEmpty(StandardOutputPath))
            {
                sb.Add("--stdout");
                sb.AddQuoted(StandardOutputPath);
            }

            if (!string.IsNullOrEmpty(StandardErrorPath))
            {
                sb.Add("--stderr");
                sb.AddQuoted(StandardErrorPath);
            }

            if (WaitForExit)
            {
                sb.Add("--wait-for-exit");
            }

            return(sb.ToString());
        }
Пример #26
0
        protected override void AppendCommandLineArguments(IDictionary <string, string> environment, CommandLineArgumentBuilder args, ITaskItem[] items)
        {
            if (plist != null)
            {
                PString value;

                var assetDirs = new HashSet <string> (items.Select(x => BundleResource.GetVirtualProjectPath(ProjectDir, x, !string.IsNullOrEmpty(SessionId))));

                if (plist.TryGetValue(ManifestKeys.XSAppIconAssets, out value) && !string.IsNullOrEmpty(value.Value))
                {
                    int    index    = value.Value.IndexOf(".xcassets" + Path.DirectorySeparatorChar, StringComparison.Ordinal);
                    string assetDir = null;
                    var    rpath    = value.Value;

                    if (index != -1)
                    {
                        assetDir = rpath.Substring(0, index + ".xcassets".Length);
                    }

                    if (assetDirs != null && assetDirs.Contains(assetDir))
                    {
                        var assetName = Path.GetFileNameWithoutExtension(rpath);

                        if (PartialAppManifest == null)
                        {
                            args.Add("--output-partial-info-plist");
                            args.AddQuoted(partialAppManifest.GetMetadata("FullPath"));

                            PartialAppManifest = partialAppManifest;
                        }

                        args.Add("--app-icon");
                        args.AddQuoted(assetName);

                        if (IsMessagesExtension(plist))
                        {
                            args.Add("--product-type com.apple.product-type.app-extension.messages");
                        }
                    }
                }

                if (plist.TryGetValue(ManifestKeys.XSLaunchImageAssets, out value) && !string.IsNullOrEmpty(value.Value))
                {
                    int    index    = value.Value.IndexOf(".xcassets" + Path.DirectorySeparatorChar, StringComparison.Ordinal);
                    string assetDir = null;
                    var    rpath    = value.Value;

                    if (index != -1)
                    {
                        assetDir = rpath.Substring(0, index + ".xcassets".Length);
                    }

                    if (assetDirs != null && assetDirs.Contains(assetDir))
                    {
                        var assetName = Path.GetFileNameWithoutExtension(rpath);

                        if (PartialAppManifest == null)
                        {
                            args.Add("--output-partial-info-plist");
                            args.AddQuoted(partialAppManifest.GetMetadata("FullPath"));

                            PartialAppManifest = partialAppManifest;
                        }

                        args.Add("--launch-image");
                        args.AddQuoted(assetName);
                    }
                }

                if (plist.TryGetValue(ManifestKeys.CLKComplicationGroup, out value) && !string.IsNullOrEmpty(value.Value))
                {
                    args.Add("--complication", value);
                }
            }

            if (OptimizePNGs)
            {
                args.Add("--compress-pngs");
            }

            if (AppleSdkSettings.XcodeVersion.Major >= 7)
            {
                if (!string.IsNullOrEmpty(outputSpecs))
                {
                    args.Add("--enable-on-demand-resources", EnableOnDemandResources ? "YES" : "NO");
                }

                if (!string.IsNullOrEmpty(DeviceModel))
                {
                    args.Add("--filter-for-device-model", DeviceModel);
                }

                if (!string.IsNullOrEmpty(DeviceOSVersion))
                {
                    args.Add("--filter-for-device-os-version", DeviceOSVersion);
                }

                if (!string.IsNullOrEmpty(outputSpecs))
                {
                    args.Add("--asset-pack-output-specifications");
                    args.AddQuoted(Path.GetFullPath(outputSpecs));
                }
            }

            if (plist != null)
            {
                foreach (var targetDevice in GetTargetDevices(plist))
                {
                    args.Add("--target-device", targetDevice);
                }
            }

            args.Add("--minimum-deployment-target", MinimumOSVersion);

            var platform = PlatformUtils.GetTargetPlatform(SdkPlatform, IsWatchApp);

            if (platform != null)
            {
                args.Add("--platform", platform);
            }
        }
Пример #27
0
        protected override string GenerateCommandLineCommands()
        {
            var cmd = new CommandLineArgumentBuilder();

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

            cmd.Add("/nostdlib");
            cmd.AddQuotedSwitchIfNotNull("/baselib:", BaseLibDll);
            cmd.AddQuotedSwitchIfNotNull("/out:", OutputAssembly);

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

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

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

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

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

            if (!string.IsNullOrEmpty(DotNetCscCompiler))
            {
                var compileCommand = new string [] {
                    DotNetPath,
                    DotNetCscCompiler,
                };
                cmd.AddQuoted("/compile-command:" + string.Join(" ", StringUtils.QuoteForProcess(compileCommand)));
            }

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

            if (NoNFloatUsing)
            {
                cmd.Add("/no-nfloat-using:true");
            }

            if (!string.IsNullOrEmpty(DefineConstants))
            {
                var strv = DefineConstants.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var str in strv)
                {
                    cmd.AddQuoted("/d:" + str);
                }
            }

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

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

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

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

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

            HandleReferences(cmd);

            if (Resources != null)
            {
                foreach (var item in Resources)
                {
                    var argument = item.ToString();
                    var id       = item.GetMetadata("LogicalName");
                    if (!string.IsNullOrEmpty(id))
                    {
                        argument += "," + id;
                    }

                    cmd.AddQuoted("/res:" + argument);
                }
            }

            if (NativeLibraries != null)
            {
                foreach (var item in NativeLibraries)
                {
                    var argument = item.ToString();
                    var id       = item.GetMetadata("LogicalName");
                    if (string.IsNullOrEmpty(id))
                    {
                        id = Path.GetFileName(argument);
                    }

                    cmd.AddQuoted("/res:" + argument + "," + id);
                }
            }

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

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

            cmd.Add($"/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.Add(StringParserService.Parse(argument, customTags));
                }
            }

            cmd.Add(VerbosityUtils.Merge(ExtraArgs, (LoggerVerbosity)Verbosity));

            var commandLine = cmd.CreateResponseFile(this, ResponseFilePath, null);
            if (IsDotNet)
            {
                commandLine = StringUtils.Quote(Path.Combine(BTouchToolPath, BTouchToolExe)) + " " + commandLine;
            }

            return(commandLine.ToString());
        }
Пример #28
0
        protected int Compile(ITaskItem[] items, string output, ITaskItem manifest)
        {
            var environment = new Dictionary <string, string> ();
            var args        = new CommandLineArgumentBuilder();

            if (!string.IsNullOrEmpty(SdkBinPath))
            {
                environment.Add("PATH", SdkBinPath);
            }

            if (!string.IsNullOrEmpty(SdkUsrPath))
            {
                environment.Add("XCODE_DEVELOPER_USR_PATH", SdkUsrPath);
            }

            args.Add("--errors", "--warnings", "--notices");
            args.Add("--output-format", "xml1");

            AppendCommandLineArguments(environment, args, items);

            if (Link)
            {
                args.Add("--link");
            }
            else if (UseCompilationDirectory)
            {
                args.Add("--compilation-directory");
            }
            else
            {
                args.Add("--compile");
            }

            args.AddQuoted(Path.GetFullPath(output));

            foreach (var item in items)
            {
                args.AddQuoted(item.GetMetadata("FullPath"));
            }

            var startInfo = GetProcessStartInfo(environment, GetFullPathToTool(), args.ToString());
            var errors    = new StringBuilder();
            int exitCode;

            try {
                Log.LogMessage(MessageImportance.Normal, "Tool {0} execution started with arguments: {1}", startInfo.FileName, startInfo.Arguments);

                using (var stdout = File.CreateText(manifest.ItemSpec)) {
                    using (var stderr = new StringWriter(errors)) {
                        using (var process = ProcessUtils.StartProcess(startInfo, stdout, stderr)) {
                            process.Wait();

                            exitCode = process.Result;
                        }
                    }

                    Log.LogMessage(MessageImportance.Low, "Tool {0} execution finished (exit code = {1}).", startInfo.FileName, exitCode);
                }
            } catch (Exception ex) {
                Log.LogError("Error executing tool '{0}': {1}", startInfo.FileName, ex.Message);
                File.Delete(manifest.ItemSpec);
                return(-1);
            }

            if (exitCode != 0)
            {
                // Note: ibtool or actool exited with an error. Dump everything we can to help the user
                // diagnose the issue and then delete the manifest log file so that rebuilding tries
                // again (in case of ibtool's infamous spurious errors).
                if (errors.Length > 0)
                {
                    Log.LogError(null, null, null, items[0].ItemSpec, 0, 0, 0, 0, "{0}", errors);
                }

                Log.LogError("{0} exited with code {1}", ToolName, exitCode);

                // Note: If the log file exists and is parseable, log those warnings/errors as well...
                if (File.Exists(manifest.ItemSpec))
                {
                    try {
                        var plist = PDictionary.FromFile(manifest.ItemSpec);

                        LogWarningsAndErrors(plist, items[0]);
                    } catch (Exception ex) {
                        Log.LogError("Failed to load {0} log file `{1}`: {2}", ToolName, manifest.ItemSpec, ex.Message);
                    }

                    File.Delete(manifest.ItemSpec);
                }
            }

            return(exitCode);
        }
Пример #29
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());
        }