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); } } } }
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)); 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 (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 LinkerOptions(); 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)); } } } gcc.BuildNativeReferenceFlags(Log, NativeReferences); gcc.Arguments.AddQuoted(LinkNativeCodeTaskBase.GetEmbedEntitlementsInExecutableLinkerFlags(CompiledEntitlements)); foreach (var framework in gcc.Frameworks) { args.AddQuotedLine($"--framework={Path.GetFullPath (framework)}"); } foreach (var framework in gcc.WeakFrameworks) { args.AddQuotedLine($"--weak-framework={Path.GetFullPath (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(args.CreateResponseFile(this, ResponseFilePath, unescapedArgs)); }
public LinkerOptions() { Arguments = new CommandLineArgumentBuilder(); WeakFrameworks = new HashSet <string> (); Frameworks = new HashSet <string> (); }
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"); } if (UseSecureTimestamp) { args.Add("--timestamp"); } else { args.Add("--timestamp=none"); } 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()); }
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 (FormatException) { } File.Delete(manifest.ItemSpec); } } return(exitCode); }
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()); }
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 fileName = GetFullPathToTool(); var arguments = args.ToList(); var rv = ExecuteAsync(fileName, 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); }
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); 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); } }
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); }
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()); }
protected override string GenerateCommandLineCommands() { var cmd = new CommandLineBuilder(); #if DEBUG cmd.AppendSwitch("/v"); #endif if (NoStdLib) { cmd.AppendSwitch("/nostdlib"); } cmd.AppendSwitchIfNotNull("/compiler:", CompilerPath); cmd.AppendSwitchIfNotNull("/baselib:", BaseLibDll); cmd.AppendSwitchIfNotNull("/out:", OutputAssembly); if (NoStdLib) { string dir; if (!string.IsNullOrEmpty(BaseLibDll)) { dir = Path.GetDirectoryName(BaseLibDll); } else { dir = null; } cmd.AppendSwitchIfNotNull("/lib:", dir); cmd.AppendSwitchIfNotNull("/r:", Path.Combine(dir, "mscorlib.dll")); } 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(GetTargetFrameworkArgument()); 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 }, { "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]; cmd.AppendTextUnquoted(StringParserService.Parse(argument, customTags)); } } return(cmd.ToString()); }
protected override string GenerateCommandLineCommands() { var args = new CommandLineArgumentBuilder(); bool msym; 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); } var verbosity = VerbosityUtils.Merge(ExtraArguments, (LoggerVerbosity)Verbosity); // for compatibility with earlier versions nothing means one /v actualArgs.AddLine(verbosity.Length > 0 ? verbosity : "/verbose"); return(actualArgs.ToString()); }
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; var envVariables = 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; 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 "setenv": 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> (); } 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(); } if (envVariables.Count > 0) { if (EnvironmentVariables != null) { envVariables.AddRange(EnvironmentVariables); } EnvironmentVariables = envVariables.ToArray(); } } return(!Log.HasLoggedErrors); }
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); } args.AddLine($"/profile:{TargetFrameworkMoniker}"); 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); 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); }
void BuildNativeReferenceFlags(GccOptions gcc) { if (NativeReferences == null) { return; } foreach (var item in NativeReferences) { var value = item.GetMetadata("Kind"); NativeReferenceKind kind; bool boolean; if (string.IsNullOrEmpty(value) || !Enum.TryParse(value, out kind)) { Log.LogWarning("Unknown native reference type for '{0}'.", item.ItemSpec); continue; } if (kind == NativeReferenceKind.Static) { var libName = Path.GetFileName(item.ItemSpec); if (libName.EndsWith(".a", StringComparison.Ordinal)) { libName = libName.Substring(0, libName.Length - 2); } if (libName.StartsWith("lib", StringComparison.Ordinal)) { libName = libName.Substring(3); } if (!string.IsNullOrEmpty(Path.GetDirectoryName(item.ItemSpec))) { gcc.Arguments.AddQuoted("-L" + Path.GetDirectoryName(item.ItemSpec)); } gcc.Arguments.AddQuoted("-l" + libName); value = item.GetMetadata("ForceLoad"); if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean) { gcc.Arguments.Add("-force_load"); gcc.Arguments.AddQuoted(item.ItemSpec); } value = item.GetMetadata("IsCxx"); if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean) { gcc.Cxx = true; } } else if (kind == NativeReferenceKind.Framework) { gcc.Frameworks.Add(item.ItemSpec); } else { Log.LogWarning("Dynamic native references are not supported: '{0}'", item.ItemSpec); continue; } value = item.GetMetadata("NeedsGccExceptionHandling"); if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out boolean) && boolean) { if (!gcc.Arguments.Contains("-lgcc_eh")) { gcc.Arguments.Add("-lgcc_eh"); } } value = item.GetMetadata("WeakFrameworks"); if (!string.IsNullOrEmpty(value)) { foreach (var framework in value.Split(' ', '\t')) { gcc.WeakFrameworks.Add(framework); } } value = item.GetMetadata("Frameworks"); if (!string.IsNullOrEmpty(value)) { foreach (var framework in value.Split(' ', '\t')) { gcc.Frameworks.Add(framework); } } // Note: these get merged into gccArgs by our caller value = item.GetMetadata("LinkerFlags"); if (!string.IsNullOrEmpty(value)) { var linkerFlags = CommandLineArgumentBuilder.Parse(value); foreach (var flag in linkerFlags) { gcc.Arguments.AddQuoted(flag); } } } }
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; } List <string> allSupportedArchs = new List <string> (); if (arch.HasFlag(XamMacArch.i386)) { allSupportedArchs.Add("i386"); } if (arch.HasFlag(XamMacArch.x86_64)) { allSupportedArchs.Add("x86_64"); } if (arch.HasFlag(XamMacArch.ARM64)) { allSupportedArchs.Add("arm64"); } args.AddLine($"/abi:{string.Join (",", allSupportedArchs)}"); 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))); }
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.AddLine($"--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 (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"); 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)}"); var v = VerbosityUtils.Merge(ExtraArgs, (LoggerVerbosity)Verbosity); if (v.Length > 0) { foreach (var arg in v) { args.AddLine(arg); } } 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()); }
protected abstract void AppendCommandLineArguments(IDictionary <string, string> environment, CommandLineArgumentBuilder args, ITaskItem[] items);
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); } }
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); }
protected override string GenerateCommandLineCommands() { var args = new CommandLineArgumentBuilder(); bool msym; args.Add("/verbose"); if (Debug) { args.Add("/debug"); } if (!string.IsNullOrEmpty(OutputPath)) { args.AddQuoted("/output:" + Path.GetFullPath(OutputPath)); } if (!string.IsNullOrEmpty(ApplicationName)) { args.AddQuoted("/name:" + ApplicationName); } if (TargetFrameworkIdentifier == "Xamarin.Mac") { args.Add("/profile:Xamarin.Mac,Version=v2.0,Profile=Mobile"); } else if (UseXamMacFullFramework) { args.Add($"/profile:Xamarin.Mac,Version={TargetFrameworkVersion},Profile=Full"); } else { args.Add($"/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.Add("/arch:i386"); } if (arch.HasFlag(XamMacArch.x86_64)) { args.Add("/arch:x86_64"); } if (!string.IsNullOrEmpty(ArchiveSymbols) && bool.TryParse(ArchiveSymbols.Trim(), out msym)) { args.Add("--msym:" + (msym ? "yes" : "no")); } args.Add(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.Add(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.Add("/profiling"); } if (EnableSGenConc) { args.Add("/sgen-conc"); } switch ((LinkMode ?? string.Empty).ToLower()) { case "full": break; case "sdkonly": args.Add("/linksdkonly"); break; case "platform": args.Add("/linkplatform"); break; default: args.Add("/nolink"); break; } if (!string.IsNullOrEmpty(AotScope) && AotScope != "None") { var aot = $"--aot:{AotScope.ToLower ()}"; if (HybridAotOption) { aot += "|hybrid"; } if (!string.IsNullOrEmpty(ExplicitAotAssemblies)) { aot += $",{ExplicitAotAssemblies}"; } args.Add(aot); } if (!string.IsNullOrEmpty(I18n)) { args.AddQuoted("/i18n:" + I18n); } if (ExplicitReferences != null) { foreach (var asm in ExplicitReferences) { args.AddQuoted("/assembly:" + Path.GetFullPath(asm.ItemSpec)); } } if (!string.IsNullOrEmpty(ApplicationAssembly.ItemSpec)) { args.AddQuoted("/root-assembly:" + Path.GetFullPath(ApplicationAssembly.ItemSpec)); } if (!string.IsNullOrWhiteSpace(ExtraArguments)) { args.Add(ExtraArguments); } if (NativeReferences != null) { foreach (var nr in NativeReferences) { args.AddQuoted("/native-reference:" + Path.GetFullPath(nr.ItemSpec)); } } if (IsAppExtension) { args.AddQuoted("/extension"); } args.AddQuoted("/sdkroot:" + SdkRoot); if (!string.IsNullOrEmpty(IntermediateOutputPath)) { Directory.CreateDirectory(IntermediateOutputPath); args.AddQuoted("--cache:" + Path.GetFullPath(IntermediateOutputPath)); } return(args.ToString()); }