From abe7a325bb7510568e4360f1d5739cde26d2f619 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 26 Mar 2026 13:52:13 +0100 Subject: [PATCH 1/4] EmccCompile: prefer TryRunProcess over RunShellCommand. A shell is not needed to run emcc. --- src/tasks/WasmAppBuilder/EmccCompile.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/tasks/WasmAppBuilder/EmccCompile.cs b/src/tasks/WasmAppBuilder/EmccCompile.cs index e93e77203ae30b..d8f70ff6722513 100644 --- a/src/tasks/WasmAppBuilder/EmccCompile.cs +++ b/src/tasks/WasmAppBuilder/EmccCompile.cs @@ -209,19 +209,21 @@ bool ProcessSourceFile(string srcFile, string objFile) string tmpObjFile = Path.GetTempFileName(); try { - string command = $"\"{CompilerBinaryPath}\" {Arguments} -c -o \"{tmpObjFile}\" \"{srcFile}\""; + string args = $"{Arguments} -c -o \"{tmpObjFile}\" \"{srcFile}\""; var startTime = DateTime.Now; // Log the command in a compact format which can be copy pasted StringBuilder envStr = new StringBuilder(string.Empty); foreach (var key in envVarsDict.Keys) envStr.Append($"{key}={envVarsDict[key]} "); - Log.LogMessage(MessageImportance.Low, $"Exec: {envStr}{command}"); - (int exitCode, string output) = Utils.RunShellCommand( + Log.LogMessage(MessageImportance.Low, $"Exec: {envStr}\"{CompilerBinaryPath}\" {args}"); + (int exitCode, string output) = Utils.TryRunProcess( Log, - command, + CompilerBinaryPath, + args, envVarsDict, workingDir: Environment.CurrentDirectory, + silent: false, logStdErrAsMessage: true, debugMessageImportance: messageImportance, label: Path.GetFileName(srcFile)); From b9863bf8d8177377c8ffb4873197dc3bd88efb93 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 26 Mar 2026 16:47:00 +0100 Subject: [PATCH 2/4] Remove RunShellCommand. --- src/tasks/Common/Utils.cs | 55 --------------------------------------- 1 file changed, 55 deletions(-) diff --git a/src/tasks/Common/Utils.cs b/src/tasks/Common/Utils.cs index 97be25c8559d38..20c7c98d26c6a3 100644 --- a/src/tasks/Common/Utils.cs +++ b/src/tasks/Common/Utils.cs @@ -48,61 +48,6 @@ public static bool IsNewerThan(string inFile, string outFile) => !File.Exists(inFile) || !File.Exists(outFile) || (File.GetLastWriteTimeUtc(inFile) > File.GetLastWriteTimeUtc(outFile)); - public static (int exitCode, string output) RunShellCommand( - TaskLoggingHelper logger, - string command, - IDictionary envVars, - string workingDir, - bool silent=false, - bool logStdErrAsMessage=false, - MessageImportance debugMessageImportance=MessageImportance.Low, - string? label=null) - { - string scriptFileName = CreateTemporaryBatchFile(command); - (string shell, string args) = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? ("cmd", $"/c \"{scriptFileName}\"") - : ("/bin/sh", $"\"{scriptFileName}\""); - - string msgPrefix = label == null ? string.Empty : $"[{label}] "; - logger.LogMessage(debugMessageImportance, $"{msgPrefix}Running {command} via script {scriptFileName}:", msgPrefix); - logger.LogMessage(debugMessageImportance, File.ReadAllText(scriptFileName), msgPrefix); - - return TryRunProcess(logger, - shell, - args, - envVars, - workingDir, - silent: silent, - logStdErrAsMessage: logStdErrAsMessage, - label: label, - debugMessageImportance: debugMessageImportance); - - static string CreateTemporaryBatchFile(string command) - { - string extn = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".cmd" : ".sh"; - string file = Path.Combine(Path.GetTempPath(), $"tmp{Guid.NewGuid():N}{extn}"); - - using StreamWriter sw = new(file); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - // set encoding to UTF-8 -> full Unicode support is needed for usernames - - // `command` contains tmp dir path with the username - sw.WriteLine(@"%SystemRoot%\System32\chcp.com 65001>nul"); - sw.WriteLine("setlocal"); - sw.WriteLine("set errorlevel=dummy"); - sw.WriteLine("set errorlevel="); - } - else - { - // Use sh rather than bash, as not all 'nix systems necessarily have Bash installed - sw.WriteLine("#!/bin/sh"); - } - - sw.WriteLine(command); - return file; - } - } - public static string RunProcess( TaskLoggingHelper logger, string path, From be862f8518431363c9f682aeefacbaf0000f5aed Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Fri, 27 Mar 2026 14:16:17 +0100 Subject: [PATCH 3/4] Fix Windows invocation. --- src/tasks/WasmAppBuilder/EmccCompile.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/tasks/WasmAppBuilder/EmccCompile.cs b/src/tasks/WasmAppBuilder/EmccCompile.cs index d8f70ff6722513..3209eb4956663b 100644 --- a/src/tasks/WasmAppBuilder/EmccCompile.cs +++ b/src/tasks/WasmAppBuilder/EmccCompile.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -217,9 +218,18 @@ bool ProcessSourceFile(string srcFile, string objFile) foreach (var key in envVarsDict.Keys) envStr.Append($"{key}={envVarsDict[key]} "); Log.LogMessage(MessageImportance.Low, $"Exec: {envStr}\"{CompilerBinaryPath}\" {args}"); + + // On Windows, the emsdk ships emcc.bat to invoke emcc. Use 'cmd' to execute the batch file. + string processPath = CompilerBinaryPath; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + args = $"/c \"{CompilerBinaryPath}\" {args}"; + processPath = "cmd"; + } + (int exitCode, string output) = Utils.TryRunProcess( Log, - CompilerBinaryPath, + processPath, args, envVarsDict, workingDir: Environment.CurrentDirectory, From a86a5b04c9e826e007bbdd7a2a8e041616f70222 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Fri, 27 Mar 2026 15:45:03 +0100 Subject: [PATCH 4/4] Try fix cmd for Windows. --- src/tasks/WasmAppBuilder/EmccCompile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/WasmAppBuilder/EmccCompile.cs b/src/tasks/WasmAppBuilder/EmccCompile.cs index 3209eb4956663b..a310a7eca6837c 100644 --- a/src/tasks/WasmAppBuilder/EmccCompile.cs +++ b/src/tasks/WasmAppBuilder/EmccCompile.cs @@ -223,7 +223,7 @@ bool ProcessSourceFile(string srcFile, string objFile) string processPath = CompilerBinaryPath; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - args = $"/c \"{CompilerBinaryPath}\" {args}"; + args = $"/c \"\"{CompilerBinaryPath}\" {args}\""; processPath = "cmd"; }