public override bool Execute() { if (!Enum.TryParse(TargetArchitectures, out architectures)) { Log.LogError(12, null, MSBStrings.E0012, TargetArchitectures); return(false); } var inputs = new List <string> (Assemblies.Length); for (var i = 0; i < Assemblies.Length; i++) { inputs.Add(Path.GetFullPath(Assemblies [i].ItemSpec)); } // All the assemblies to AOT must be in the same directory var assemblyDirectories = inputs.Select(v => Path.GetDirectoryName(Path.GetFullPath(v))).Distinct().ToArray(); if (assemblyDirectories.Length > 1) { // The assemblies are not in the same directory, so copy them somewhere else (to InputDirectory) Directory.CreateDirectory(InputDirectory); for (var i = 0; i < inputs.Count; i++) { var newInput = Path.Combine(InputDirectory, Path.GetFileName(inputs [i])); File.Copy(inputs [i], newInput, true); inputs [i] = newInput; } } else { // The assemblies are all in the same directory, we can just use that as input. InputDirectory = assemblyDirectories [0]; } Directory.CreateDirectory(OutputDirectory); var aotAssemblyFiles = new List <ITaskItem> (); var aotDataFiles = new List <ITaskItem> (); var processes = new Task <Execution> [Assemblies.Length]; var objectFiles = new List <ITaskItem> (); var environment = new Dictionary <string, string> { { "MONO_PATH", Path.GetFullPath(InputDirectory) }, }; foreach (var arch in architectures.ToArray()) { for (var i = 0; i < Assemblies.Length; i++) { var asm = Assemblies [i]; var input = inputs [i]; var abi = arch.ToNativeArchitecture(); var aotData = Path.Combine(OutputDirectory, Path.GetFileNameWithoutExtension(input) + ".aotdata." + abi); var aotAssembly = Path.Combine(OutputDirectory, Path.GetFileName(input) + ".s"); var aotAssemblyItem = new TaskItem(aotAssembly); aotAssemblyItem.SetMetadata("Arguments", "-Xlinker -rpath -Xlinker @executable_path/ -Qunused-arguments -x assembler -D DEBUG"); aotAssemblyItem.SetMetadata("Arch", abi); aotAssemblyFiles.Add(aotAssemblyItem); aotDataFiles.Add(new TaskItem(aotData)); var aotArg = new StringBuilder(); aotArg.Append($"--aot=mtriple={abi}-{PlatformName.ToLowerInvariant ()},"); aotArg.Append($"data-outfile={aotData},"); aotArg.Append($"static,asmonly,direct-icalls,full,dwarfdebug,no-direct-calls,"); aotArg.Append($"soft-debug,"); aotArg.Append($"outfile={aotAssembly}"); var arguments = new List <string> (); arguments.Add(aotArg.ToString()); arguments.Add("--debug"); arguments.Add("-O=gsharedvt"); arguments.Add("-O=-float32"); arguments.Add(input); processes [i] = ExecuteAsync(AOTCompilerPath, arguments, environment: environment, sdkDevPath: SdkDevPath, showErrorIfFailure: false /* we show our own error below */) .ContinueWith((v) => { if (v.Result.ExitCode != 0) { Log.LogError("Failed to AOT compile {0}, the AOT compiler exited with code {1}", Path.GetFileName(input), v.Result.ExitCode); } return(System.Threading.Tasks.Task.FromResult <Execution> (v.Result)); }).Unwrap(); } } System.Threading.Tasks.Task.WaitAll(processes); AOTData = aotDataFiles.ToArray(); AssemblyFiles = aotAssemblyFiles.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { if (!Enum.TryParse(TargetArchitectures, out architectures)) { Log.LogError(12, null, MSBStrings.E0012, TargetArchitectures); return(false); } var abis = architectures.ToArray(); if (abis.Count != 1) { Log.LogError(7070, null, MSBStrings.E7070, /* Invalid architecture ({0}): can't link more than one architecture at a time. */ TargetArchitectures); return(false); } var abi = abis [0].ToNativeArchitecture(); var arguments = new List <string> (); arguments.Add("clang"); switch (Platform) { case ApplePlatform.iOS: case ApplePlatform.WatchOS: case ApplePlatform.TVOS: case ApplePlatform.MacOSX: arguments.Add(PlatformFrameworkHelper.GetMinimumVersionArgument(TargetFrameworkMoniker, SdkIsSimulator, MinimumOSVersion)); arguments.Add("-isysroot"); arguments.Add(SdkRoot); arguments.Add("-arch"); arguments.Add(abi); break; case ApplePlatform.MacCatalyst: arguments.Add($"-target"); arguments.Add($"{abi}-apple-ios{MinimumOSVersion}-macabi"); arguments.Add("-isysroot"); arguments.Add(SdkRoot); arguments.Add("-iframework"); arguments.Add(Path.Combine(SdkRoot, "System", "iOSSupport", "System", "Library", "Frameworks")); arguments.Add($"-L{Path.Combine (SdkRoot, "System", "iOSSupport", "usr", "lib")}"); break; default: throw new InvalidOperationException(string.Format(MSBStrings.InvalidPlatform, Platform)); } bool hasDylibs = false; if (LinkWithLibraries != null) { foreach (var libSpec in LinkWithLibraries) { var lib = Path.GetFullPath(libSpec.ItemSpec); var libExtension = Path.GetExtension(lib).ToLowerInvariant(); switch (libExtension) { case ".a": case ".o": var forceLoad = string.Equals(libSpec.GetMetadata("ForceLoad"), "true", StringComparison.OrdinalIgnoreCase); if (forceLoad) { arguments.Add("-force_load"); } arguments.Add(lib); break; case ".dylib": arguments.Add("-L" + Path.GetDirectoryName(lib)); var libName = Path.GetFileNameWithoutExtension(lib); if (libName.StartsWith("lib", StringComparison.Ordinal)) { libName = libName.Substring(3); } arguments.Add("-l" + libName); hasDylibs = true; break; case ".framework": arguments.Add("-F" + Path.GetDirectoryName(lib)); arguments.Add("-framework"); arguments.Add(Path.GetFileNameWithoutExtension(lib)); break; default: Log.LogError($"Unknown library extension {libExtension} to link with for {lib}."); return(false); } } } if (hasDylibs) { arguments.Add("-rpath"); arguments.Add(DylibRPath ?? "@executable_path"); } if (Frameworks != null) { foreach (var fw in Frameworks) { var is_weak = fw.GetMetadata("IsWeak") == "true"; var framework = fw.ItemSpec; if (framework.EndsWith(".framework", StringComparison.Ordinal)) { // user framework, we need to pass -F to the linker so that the linker finds the user framework. arguments.Add("-F"); arguments.Add(Path.GetDirectoryName(Path.GetFullPath(framework))); framework = Path.GetFileNameWithoutExtension(framework); } arguments.Add(is_weak ? "-weak_framework" : "-framework"); arguments.Add(framework); } } if (ObjectFiles != null) { foreach (var obj in ObjectFiles) { arguments.Add(Path.GetFullPath(obj.ItemSpec)); } } arguments.AddRange(GetEmbedEntitlementsInExecutableLinkerFlags(EntitlementsInExecutable)); arguments.Add("-o"); arguments.Add(Path.GetFullPath(OutputFile)); if (LinkerFlags != null) { foreach (var flag in LinkerFlags) { arguments.Add(flag.ItemSpec); } } ExecuteAsync("xcrun", arguments, sdkDevPath: SdkDevPath).Wait(); return(!Log.HasLoggedErrors); }
public override bool Execute() { PDictionary plist; if (File.Exists(ProductDefinition)) { try { plist = PDictionary.FromFile(ProductDefinition); } catch (Exception ex) { LogProductDefinitionError(MSBStrings.E0010, ProductDefinition, ex.Message); return(false); } } else { plist = new PDictionary(); } if (!string.IsNullOrEmpty(TargetArchitectures) && !Enum.TryParse(TargetArchitectures, out architectures)) { LogProductDefinitionError(MSBStrings.E0012, TargetArchitectures); return(false); } // productbuild can do a guess of the targeted architectures if not provided, but the guess // is very simple : on Catalina and lower, it will suppose it's x86_64 (even with an arm64 slice). HashSet <string> archStrings = new HashSet <string> (architectures.ToArray().Select(a => a.ToNativeArchitecture())); if (plist.TryGetValue(ProductDefinitionKeys.Architectures, out PArray archArray)) { var existingArchs = archArray.ToStringArray(); if (!archStrings.SetEquals(existingArchs)) { LogProductDefinitionWarning(MSBStrings.E7072, string.Join(", ", existingArchs), string.Join(", ", archStrings)); } } if (archArray == null) { archArray = new PArray(); foreach (var arch in archStrings) { archArray.Add(new PString(arch)); } } plist [ProductDefinitionKeys.Architectures] = archArray; if (!plist.TryGetValue(ProductDefinitionKeys.MinimumSystemVersion, out PArray osVersionArray)) { var minOSVersion = GetMinimumOSVersion(); if (minOSVersion != null) { osVersionArray = new PArray(); osVersionArray.Add(new PString(minOSVersion)); } } if (osVersionArray != null) { plist [ProductDefinitionKeys.MinimumSystemVersion] = osVersionArray; } CompiledProductDefinition = new TaskItem(Path.Combine(OutputDirectory, "Product.plist")); plist.Save(CompiledProductDefinition.ItemSpec, true, false); return(!Log.HasLoggedErrors); }