示例#1
0
        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);
        }
示例#2
0
        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);
        }