Esempio n. 1
0
        public override bool Execute()
        {
            Log.LogMessage($"Emitting winmd...");

            string dllPath        = Path.Combine(this.ToolsBinDir, "ClangSharpSourceToWinmd.dll");
            string interopPath    = Path.Combine(this.Win32WinmdBinDir, "Windows.Win32.Interop.dll");
            string win32WinmdPath = Path.Combine(this.Win32WinmdBinDir, "Windows.Win32.winmd");

            string outputWinmd = this.OutputWinmd;

            if (!Path.IsPathRooted(outputWinmd))
            {
                outputWinmd = Path.Combine(this.MSBuildProjectDirectory, outputWinmd);
            }

            var args     = new StringBuilder($"{dllPath} --sourceDir \"{this.EmitterSourceDir}\" --arch x64 --interopFileName \"{interopPath}\" --ref \"{win32WinmdPath}\" --version {this.WinmdVersion} --outputFileName \"{outputWinmd}\"");
            int exitCode = TaskUtils.ExecuteCmd("dotnet", args.ToString(), out var output, this.Log);

            if (exitCode < 0)
            {
                Log.LogError($"ClangSharpSourceToWinmd.dll failed: {output}");
                return(false);
            }

            Log.LogMessage(MessageImportance.High, $"Winmd emitted at: {outputWinmd}");
            this.FileWrites = new ITaskItem[] { new TaskItem(outputWinmd) };

            return(true);
        }
Esempio n. 2
0
        public override bool Execute()
        {
#if DEBUG
            if (System.Environment.GetEnvironmentVariable("DEBUG_TASKS") == "1")
            {
                System.Diagnostics.Debugger.Launch();
            }
#endif

            Log.LogMessage($"Scanning libs...");

            string[]         libFiles      = GetLibs();
            string           dumpBinPath   = Path.Combine(this.LibToolsBinDir, "dumpbin.exe");
            StringBuilder    libLines      = new StringBuilder();
            Regex            libRegex      = new Regex(@"DLL name     : (\S+)\s+Symbol name  : (\S+)");
            HashSet <string> functionNames = new HashSet <string>(System.StringComparer.OrdinalIgnoreCase);
            foreach (var lib in libFiles)
            {
                string dbinArgs = $"/headers \"{lib}\"";
                TaskUtils.ExecuteCmd(dumpBinPath, dbinArgs, out var dbinOutput, this.Log);
                foreach (Match match in libRegex.Matches(dbinOutput))
                {
                    var dllName      = Path.GetFileNameWithoutExtension(match.Groups[1].Value);
                    var functionName = match.Groups[2].Value;

                    if (!functionNames.Contains(functionName))
                    {
                        if (libLines.Length == 0)
                        {
                            libLines.AppendLine("--with-librarypath");
                        }

                        libLines.AppendLine($"{functionName}={dllName}");
                        functionNames.Add(functionName);
                    }
                }
            }

            if (libLines.Length != 0)
            {
                var objDir = Path.Combine(this.MSBuildProjectDirectory, "obj");
                Directory.CreateDirectory(objDir);

                string rspFile = Path.Combine(objDir, $"withLibs.generated.rsp");
                File.WriteAllText(rspFile, libLines.ToString());

                this.OutputLibRsp = new TaskItem(rspFile);
            }

            return(true);
        }
Esempio n. 3
0
        public static string GetVcDirPath(string scriptsDir, TaskLoggingHelper log)
        {
            string scriptPath = Path.Combine(scriptsDir, "GetVcDirPath.ps1");
            string scriptArgs = $"-File \"{scriptPath}\" x86 x86";

            int ret = TaskUtils.ExecuteCmd("powershell.exe", scriptArgs, out var scriptOutput, log);

            if (ret != 0)
            {
                log.LogError($"GetVcDirPath.ps1 failed: {scriptOutput}");
                return(null);
            }

            return(scriptOutput);
        }
Esempio n. 4
0
        private bool ScrapeConstants()
        {
            Log.LogMessage($"Scraping constants...");

            string constantsScraperDll = Path.Combine(this.ToolsBinDir, "ConstantsScraper.dll");
            string constantsHeaderTxt  = Path.Combine(this.Win32MetadataScraperAssetsDir, "ConstantsHeader.txt");
            var    args     = new StringBuilder($"{constantsScraperDll} --repoRoot {this.objDir} --arch x64 --headerTextFile {constantsHeaderTxt}");
            int    exitCode = TaskUtils.ExecuteCmd("dotnet", args.ToString(), out var output, this.Log);

            if (exitCode < 0)
            {
                Log.LogError($"ConstantsScraper.dll failed: {output}");
                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        public override bool Execute()
        {
#if DEBUG
            if (System.Environment.GetEnvironmentVariable("DEBUG_COMPILE_IDLS_TASK") == "1")
            {
                System.Diagnostics.Debugger.Launch();
            }
#endif

            string[] idls = this.GetIdls();
            if (idls.Length == 0)
            {
                return(true);
            }

            Directory.CreateDirectory(this.ObjDir);
            Directory.CreateDirectory(this.CompiledHeadersDir);

            string vcPath = TaskUtils.GetVcDirPath(this.ScriptsDir, this.Log);
            if (string.IsNullOrEmpty(vcPath))
            {
                return(false);
            }

            vcPath = vcPath.Trim();

            string scriptPath     = Path.Combine(this.ScriptsDir, "ConvertMidlAttributesToSalAnnotations.ps1");
            string midlPath       = Path.Combine(this.SdkBinDir, "x86", "midl.exe");
            string umDir          = Path.Combine(this.SdkIncRoot, "um");
            string sharedDir      = Path.Combine(this.SdkIncRoot, "shared");
            string winrtDir       = Path.Combine(this.SdkIncRoot, "winrt");
            string commonMidlArgs = $"/out \"{this.ObjDir}\" /no_warn /DUNICODE /D_UNICODE /DWINVER=0x0A00 -D_APISET_MINWIN_VERSION=0x010F /DNTDDI_VERSION=0x0A00000B /DBUILD_UMS_ENABLED=0 /DBUILD_WOW64_ENABLED=0 /DBUILD_ARM64X_ENABLED=0 /DEXECUTABLE_WRITES_SUPPORT=0 -D_USE_DECLSPECS_FOR_SAL=1 -D_CONTROL_FLOW_GUARD_SVCTAB=1  /Di386 /D_X86_ /D_WCHAR_T_DEFINED /no_stamp /nologo  /no_settings_comment /lcid 1033 -sal /win32 -target NT100 /Zp8 /I\"{umDir}\" /I\"{sharedDir}\" /I\"{winrtDir}\"";

            if (!string.IsNullOrEmpty(this.AdditionalIncludes))
            {
                commonMidlArgs += $" /I\"{this.AdditionalIncludes}\"";
            }

            foreach (var idl in idls)
            {
                string fixedIdlFile = Path.Combine(this.ObjDir, Path.GetFileName(idl));
                string scriptArgs   = $"-File \"{scriptPath}\" -inputFileName \"{idl}\" -outputFileName \"{fixedIdlFile}\"";
                if (File.Exists(fixedIdlFile))
                {
                    File.Delete(fixedIdlFile);
                }

                int ret = TaskUtils.ExecuteCmd("powershell.exe", scriptArgs, out var scriptOutput, this.Log);
                if (ret != 0)
                {
                    this.Log.LogError($"powershell.exe {scriptArgs} failed: {scriptOutput}");
                    return(false);
                }

                string compiledHeader = Path.Combine(this.CompiledHeadersDir, Path.ChangeExtension(Path.GetFileName(idl), ".h"));
                string midlArgs       = $"\"{fixedIdlFile}\" /header \"{compiledHeader}\" {commonMidlArgs}";
                ret = TaskUtils.ExecuteCmd(midlPath, midlArgs, out var midlOutput, this.Log, vcPath);
                if (ret != 0)
                {
                    this.Log.LogError($"midl.exe failed: {midlOutput}");
                    return(false);
                }

                this.Log.LogMessage(midlOutput);
            }

            return(true);
        }
Esempio n. 6
0
        private bool ProcessPartitionItem(ITaskItem partitionItem)
        {
            // TODO: Do we want to do this for all architectures?
            string arch = "x64";

            string[] traverseFiles = GetTraverseFiles(partitionItem);

            string ns   = partitionItem.GetMetadata("Namespace");
            string name = partitionItem.GetMetadata("Name");

            if (string.IsNullOrEmpty(name))
            {
                name = ns.Split('.').Last();
            }

            Log.LogMessage($"Scanning partition {name}...");

            string partitionDir = Path.Combine(this.partitionsDir, name);

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

            string file        = partitionItem.ItemSpec;
            string settingsRsp = Path.Combine(partitionDir, "settings.rsp");

            string currentGeneratedDir = Path.Combine(this.generatedDir, arch);

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

            string outputFile = Path.Combine(currentGeneratedDir, $"{name}.cs");

            if (File.Exists(outputFile))
            {
                File.Delete(outputFile);
            }

            HashSet <string> includeDirHash = new HashSet <string>();
            List <string>    includeDirs    = new List <string>();

            // For sal.h, etc.
            includeDirs.Add(this.Win32MetadataScraperAssetsDir);

            foreach (var traverseFile in traverseFiles)
            {
                string dir = Path.GetDirectoryName(traverseFile);
                if (!includeDirHash.Contains(dir))
                {
                    includeDirHash.Add(dir);
                    includeDirs.Add(dir);
                }
            }

            includeDirs.Add($"{this.WinSDKIncludeRoot}/shared");
            includeDirs.Add($"{this.WinSDKIncludeRoot}/um");
            includeDirs.Add($"{this.WinSDKIncludeRoot}/winrt");

            string headerTextFile = Path.Combine(this.Win32MetadataScraperAssetsDir, "header.txt");

            using (StreamWriter rspWriter = new StreamWriter(settingsRsp))
            {
                rspWriter.WriteLine(
                    $@"--file
{file}
--output
{outputFile}
--namespace
{ns}
--headerFile
{headerTextFile}
--include-directory");

                foreach (var include in includeDirs)
                {
                    rspWriter.WriteLine(include);
                }

                rspWriter.WriteLine("--traverse");

                foreach (var traverseFile in traverseFiles)
                {
                    rspWriter.WriteLine(traverseFile);
                }

                var exclusions = this.GetExclusions(partitionItem);
                if (exclusions.Any())
                {
                    rspWriter.WriteLine("--exclude");
                    foreach (var exclude in exclusions)
                    {
                        rspWriter.WriteLine(exclude);
                    }
                }
            }

            string currentScraperOutputDir = Path.Combine(this.scraperDir, $"obj\\{arch}");

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

            string        scrapeToolOutput = Path.Combine(currentScraperOutputDir, $"{name}.generation.output.txt");
            StringBuilder args             = new StringBuilder($"\"@{settingsRsp}\"");

            AddWin32Rsp(args, "baseRemap.rsp");
            AddWin32Rsp(args, "baseSettings.64.rsp");
            AddWin32Rsp(args, "baseSettings.rsp");
            AddWin32GeneratedRsp(args, "autoTypes.generated.rsp");
            AddWin32GeneratedRsp(args, "functionPointerFixups.generated.rsp");

            foreach (var rspItem in this.Rsps)
            {
                var rspPath = rspItem.ItemSpec;
                if (!Path.IsPathRooted(rspPath))
                {
                    rspPath = Path.Combine(this.MSBuildProjectDirectory, rspPath);
                }

                args.Append($" \"@{rspPath}\"");
            }

            int exitCode = TaskUtils.ExecuteCmd("ClangSharpPInvokeGenerator", args.ToString(), out var output, this.Log);

            if (output == null)
            {
                output = string.Empty;
            }

            File.WriteAllText(scrapeToolOutput, output);

            if (exitCode < 0 || !File.Exists(outputFile))
            {
                Log.LogError($"ClangSharpPInvokeGenerator.exe failed, full output at {scrapeToolOutput}.");
                return(false);
                // TODO: Output errors
            }

            return(true);
        }