From 10988a186835bdf778e9bcfb79087b4e62ec4b52 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 4 Aug 2025 15:12:35 -0700 Subject: [PATCH] Add a windows launcher program to replace the current `.bat` files This is still just an experiment but eventually I hope to remove the `.bat` files in favor of this executable. There are several reasons to want to do this: 1. Batch files are notoriously painful to work with and mis-understood. 2. Should be faster (no need to launch cmd.exe). 3. Works around several known issues with .bat files including one that is known unsolvable one (see emcc.bat for more details) --- tools/maint/win32_launcher/README.md | 11 ++ tools/maint/win32_launcher/build.bat | 1 + tools/maint/win32_launcher/build.sh | 6 + tools/maint/win32_launcher/launcher.c | 194 ++++++++++++++++++++++++ tools/maint/win32_launcher/launcher.exe | Bin 0 -> 43520 bytes 5 files changed, 212 insertions(+) create mode 100644 tools/maint/win32_launcher/README.md create mode 100644 tools/maint/win32_launcher/build.bat create mode 100755 tools/maint/win32_launcher/build.sh create mode 100644 tools/maint/win32_launcher/launcher.c create mode 100755 tools/maint/win32_launcher/launcher.exe diff --git a/tools/maint/win32_launcher/README.md b/tools/maint/win32_launcher/README.md new file mode 100644 index 0000000000000..4fbdf89c446c0 --- /dev/null +++ b/tools/maint/win32_launcher/README.md @@ -0,0 +1,11 @@ +Windows Python Script Launcher +============================== + +This directory contains a simple launcher program for windows which is used to +execute the emscripten compiler entry points using the python interpreter. It +uses the its own name (the name of the currently running executable) to +determine which python script to run and serves the same purpose as the +``run_python.sh`` script does on non-windows platforms. + +We build this executable statically using ``/MT`` so that it is maximally +portable. diff --git a/tools/maint/win32_launcher/build.bat b/tools/maint/win32_launcher/build.bat new file mode 100644 index 0000000000000..00952476cce0e --- /dev/null +++ b/tools/maint/win32_launcher/build.bat @@ -0,0 +1 @@ +cl launcher.c /Fe:launcher.exe /MT diff --git a/tools/maint/win32_launcher/build.sh b/tools/maint/win32_launcher/build.sh new file mode 100755 index 0000000000000..42f120d92913e --- /dev/null +++ b/tools/maint/win32_launcher/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") +cd ${SCRIPT_DIR} + +x86_64-w64-mingw32-gcc -municode -static-libgcc -static-libstdc++ -s -O2 launcher.c -o launcher.exe -lshlwapi -lshell32 diff --git a/tools/maint/win32_launcher/launcher.c b/tools/maint/win32_launcher/launcher.c new file mode 100644 index 0000000000000..92bfcf426019e --- /dev/null +++ b/tools/maint/win32_launcher/launcher.c @@ -0,0 +1,194 @@ +/* + * Copyright 2025 The Emscripten Authors. All rights reserved. + * Emscripten is available under two separate licenses, the MIT license and the + * University of Illinois/NCSA Open Source License. Both these licenses can be + * found in the LICENSE file. + * + * Small win32 application that is used to launcher emscripten via python.exe. + * On non-windows platforms this is done via the run_pyton.sh shell script. + * + * The binary will look for a python script that matches its own name and run + * that using python.exe. + */ + +// Define _WIN32_WINNT to Windows 7 for max portability +#define _WIN32_WINNT 0x0601 + +#include +#include +#include +#include +#include + +#pragma comment(lib, "shlwapi.lib") +#pragma comment(lib, "shell32.lib") + +wchar_t* get_python_executable() { + wchar_t* python_exe_w = _wgetenv(L"EMSDK_PYTHON"); + if (!python_exe_w) { + return L"python"; + } + return python_exe_w; +} + +wchar_t* get_long_path(const wchar_t* path) { + DWORD path_len = GetFullPathNameW(path, 0, NULL, NULL); + if (path_len == 0) + abort(); + + wchar_t* full_path = malloc(sizeof(wchar_t) * (path_len + 4)); + if (!full_path) + abort(); + + wcscpy_s(full_path, path_len + 4, L"\\\\?\\"); + if (GetFullPathNameW(path, path_len, full_path + 4, NULL) == 0) + abort(); + return full_path; +} + +// Get the name of the currently running executable (module) +wchar_t* get_module_path() { + DWORD buffer_size = MAX_PATH; + wchar_t* module_path_w = malloc(sizeof(wchar_t) * buffer_size); + if (!module_path_w) + abort(); + + DWORD path_len = GetModuleFileNameW(NULL, module_path_w, buffer_size); + while (path_len > 0 && path_len == buffer_size) { + buffer_size *= 2; + module_path_w = realloc(module_path_w, sizeof(wchar_t) * buffer_size); + if (!module_path_w) + abort(); + path_len = GetModuleFileNameW(NULL, module_path_w, buffer_size); + } + + if (path_len == 0) + abort(); + + return module_path_w; +} + +// Handle the _EMCC_CCACHE environment variable which essentially re-executes +// the lauccher command with `cacche.exe` prefixed. +BOOL handle_ccache(wchar_t** application_name, wchar_t** command_line, const wchar_t* launcher_path_w) { + const wchar_t* ccache_env = _wgetenv(L"_EMCC_CCACHE"); + if (!ccache_env || !*ccache_env) { + return FALSE; + } + + _wputenv_s(L"_EMCC_CCACHE", L""); + *application_name = L"ccache.exe"; + + size_t command_line_len = wcslen(*application_name) + wcslen(launcher_path_w) + 5; + *command_line = malloc(sizeof(wchar_t) * command_line_len); + if (!*command_line) + abort(); + + swprintf(*command_line, command_line_len, L"\"%s\" \"%s\"", *application_name, launcher_path_w); + return TRUE; +} + +// A custom replacement for PathGetArgsW that is safe for command lines +// longer than MAX_PATH. +const wchar_t* find_args(const wchar_t* command_line) { + const wchar_t* p = command_line; + + // Skip past the executable name, which can be quoted. + if (*p == L'"') { + // The path is quoted, find the closing quote. + p++; + while (*p) { + if (*p == L'"') { + p++; + break; + } + p++; + } + } else { + // The path is not quoted, find the first space. + while (*p && *p != L' ' && *p != L'\t') { + p++; + } + } + + // Skip any whitespace between the executable and the first argument. + while (*p && (*p == L' ' || *p == L'\t')) { + p++; + } + + return p; +} + +int wmain(int argc, wchar_t** argv) { + wchar_t* launcher_path_w = get_module_path(); + + wchar_t* launcher_dir = wcsdup(launcher_path_w); + PathRemoveFileSpecW(launcher_dir); + + size_t path_len = wcslen(launcher_path_w); + wchar_t* launcher_name_w = malloc((path_len + 1) * sizeof(wchar_t)); + if (!launcher_name_w) + abort(); + wcscpy_s(launcher_name_w, path_len + 1, launcher_path_w); + PathStripPathW(launcher_name_w); + PathRemoveExtensionW(launcher_name_w); + + size_t script_path_len = wcslen(launcher_dir) + wcslen(launcher_name_w) + 6; + wchar_t* script_path_w = malloc(sizeof(wchar_t) * script_path_len); + swprintf(script_path_w, script_path_len, L"%s\%s.py", launcher_dir, launcher_name_w); + + wchar_t* application_name = NULL; + wchar_t* command_line = NULL; + + if (!handle_ccache(&application_name, &command_line, launcher_path_w)) { + application_name = get_python_executable(); + wchar_t* long_script_path = get_long_path(script_path_w); + size_t command_line_len = wcslen(application_name) + wcslen(long_script_path) + 10; + command_line = malloc(sizeof(wchar_t) * command_line_len); + swprintf(command_line, command_line_len, L"\"%s\" -E \"%s\"", application_name, long_script_path); + free(long_script_path); + // -E will not ignore _PYTHON_SYSCONFIGDATA_NAME an internal + // of cpython used in cross compilation via setup.py. + _wputenv_s(L"_PYTHON_SYSCONFIGDATA_NAME", L""); + } + + // Build the final command line by appending the original arguments + const wchar_t* all_args = find_args(GetCommandLineW()); + if (all_args && *all_args) { + size_t current_len = wcslen(command_line); + size_t args_len = wcslen(all_args); + // +2 for the space and the null terminator + command_line = realloc(command_line, (current_len + args_len + 2) * sizeof(wchar_t)); + if (!command_line) + abort(); + wcscat_s(command_line, current_len + args_len + 2, L" "); + wcscat_s(command_line, current_len + args_len + 2, all_args); + } + + + // Work around python bug 34780 by closing stdin, so that it is not inherited + // by the python subprocess. + wchar_t* workaround_env = _wgetenv(L"EM_WORKAROUND_PYTHON_BUG_34780"); + if (workaround_env) { + CloseHandle(GetStdHandle(STD_INPUT_HANDLE)); + } + + STARTUPINFOW si; + PROCESS_INFORMATION pi; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + if (!CreateProcessW(application_name, command_line, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + wprintf(L"CreateProcess failed (%d).\n", GetLastError()); + abort(); + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exit_code; + GetExitCodeProcess(pi.hProcess, &exit_code); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return exit_code; +} diff --git a/tools/maint/win32_launcher/launcher.exe b/tools/maint/win32_launcher/launcher.exe new file mode 100755 index 0000000000000000000000000000000000000000..1449aac9bbdfb4f83bfa0c2c5abc334752aeba59 GIT binary patch literal 43520 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