Skip to content

Commit bc0f059

Browse files
authored
Add native windows launcher to replace the current .bat files. NFC (#24858)
This change does not start using the executable launcher by default. That can happen later once we get more feedback on it. For example, its not clear if this will lead to issues with virus/security scanners. Assuming we don't run into any issues I hope to eventually completely remove support for the `.bat` files. 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) 4. In the future we could potentially launch clang directly, bypassing the python completely (or at least only invoking python for the link stage). See: #26229 See: #19207
1 parent d27a842 commit bc0f059

File tree

11 files changed

+335
-11
lines changed

11 files changed

+335
-11
lines changed

.circleci/config.yml

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,30 @@ jobs:
12491249
steps:
12501250
- test-sockets-chrome
12511251

1252+
build-windows-launcher:
1253+
executor:
1254+
name: win/server-2022
1255+
shell: bash.exe -eo pipefail
1256+
steps:
1257+
- checkout
1258+
- run:
1259+
name: "build pylauncher"
1260+
shell: cmd.exe
1261+
command: .circleci\setup_vs2022.bat && cd tools\pylauncher && call build.bat
1262+
- store_artifacts:
1263+
path: tools/pylauncher/pylauncher.exe
1264+
destination: pylauncher.exe
1265+
- install-emsdk
1266+
- pip-install:
1267+
python: "$EMSDK_PYTHON"
1268+
- run:
1269+
name: "create_entry_points"
1270+
command: $EMSDK_PYTHON tools/maint/create_entry_points.py --exe-files
1271+
- run:
1272+
name: "crossplatform tests"
1273+
command: test/runner.exe core0.test_hello_world
1274+
1275+
12521276
# windows and mac do not have separate build and test jobs, as they only run
12531277
# a limited set of tests; it is simpler and faster to do it all in one job.
12541278
test-windows:
@@ -1275,6 +1299,10 @@ jobs:
12751299
EMTEST_BROWSER: "0"
12761300
steps:
12771301
- checkout
1302+
- run:
1303+
name: Build launcher
1304+
command: call .circleci\setup_vs2019.bat && cd tools\pylauncher && call build.bat
1305+
shell: cmd.exe
12781306
- run:
12791307
name: Install packages
12801308
command: |
@@ -1284,9 +1312,6 @@ jobs:
12841312
- install-emsdk
12851313
- pip-install:
12861314
python: "$EMSDK_PYTHON"
1287-
# run-tests depends on the ./test/runner script which is normally only
1288-
# created on UNIX systems (windows uses runner.bat)
1289-
- run: $EMSDK_PYTHON tools/maint/create_entry_points.py --all
12901315
- run:
12911316
name: "crossplatform tests"
12921317
command: test/runner.bat --crossplatform-only
@@ -1391,6 +1416,7 @@ workflows:
13911416
- test-node-compat
13921417
- test-windows
13931418
- test-windows-browser-firefox
1419+
- build-windows-launcher
13941420
- test-mac-arm64:
13951421
requires:
13961422
- build-linux

.circleci/setup_vs2019.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
echo "setting up x64 toolchain"
2+
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64
3+
where cl.exe
4+
echo "done"

.circleci/setup_vs2022.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
echo "setting up x64 toolchain"
2+
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
3+
where cl.exe
4+
echo "done"

.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ coverage.xml
3939
!/tools/run_python.ps1
4040
!/tools/run_python_compiler.ps1
4141

42+
/tools/maint/pylauncher/pylauncher.obj
43+
4244
# Shell scripts (created by ./tools/maint/create_entry_points.py)
4345
em++
4446
emcc
@@ -88,3 +90,28 @@ emsymbolizer.bat
8890
test/runner.bat
8991
tools/file_packager.bat
9092
tools/webidl_binder.bat
93+
94+
bootstrap.exe
95+
em++.exe
96+
emcc.exe
97+
em-config.exe
98+
emar.exe
99+
embuilder.exe
100+
emcmake.exe
101+
emconfigure.exe
102+
emdump.exe
103+
emdwp.exe
104+
emmake.exe
105+
emnm.exe
106+
empath-split.exe
107+
emprofile.exe
108+
emranlib.exe
109+
emrun.exe
110+
emscan-deps.exe
111+
emscons.exe
112+
emsize.exe
113+
emstrip.exe
114+
emsymbolizer.exe
115+
tools/file_packager.exe
116+
tools/webidl_binder.exe
117+
test/runner.exe

cmake/Modules/Platform/Emscripten.cmake

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,13 @@ get_filename_component(EMSCRIPTEN_ROOT_PATH "${EMSCRIPTEN_ROOT_PATH}" ABSOLUTE)
6666
list(APPEND CMAKE_MODULE_PATH "${EMSCRIPTEN_ROOT_PATH}/cmake/Modules")
6767

6868
if (CMAKE_HOST_WIN32)
69-
set(EMCC_SUFFIX ".bat")
69+
# We use windows executables these days rather than `.bat` files, but we
70+
# still support a fallback of using `.bat` files.
71+
if (EXISTS "${EMSCRIPTEN_ROOT_PATH}/emcc.exe")
72+
set(EMCC_SUFFIX ".exe")
73+
else()
74+
set(EMCC_SUFFIX ".bat")
75+
endif()
7076
else()
7177
set(EMCC_SUFFIX "")
7278
endif()

tools/maint/create_entry_points.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"""
1515

1616
import os
17+
import shutil
1718
import stat
1819
import sys
1920

@@ -61,12 +62,20 @@
6162
}
6263

6364

65+
windows_exe = os.path.join(__rootdir__, 'tools/pylauncher/pylauncher.exe')
66+
67+
6468
def make_executable(filename):
6569
old_mode = stat.S_IMODE(os.stat(filename).st_mode)
6670
os.chmod(filename, old_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
6771

6872

69-
def main(all_platforms):
73+
def maybe_remove(filename):
74+
if os.path.exists(filename):
75+
os.remove(filename)
76+
77+
78+
def main(all_platforms, use_exe_files):
7079
is_windows = sys.platform.startswith('win')
7180
is_msys2 = 'MSYSTEM' in os.environ
7281
do_unix = all_platforms or not is_windows or is_msys2
@@ -99,15 +108,20 @@ def generate_entry_points(cmd, path):
99108
make_executable(launcher)
100109

101110
if do_windows:
102-
with open(launcher + '.bat', 'w') as f:
103-
f.write(bat_data)
104-
105-
with open(launcher + '.ps1', 'w') as f:
106-
f.write(ps1_data)
111+
maybe_remove(launcher + '.bat')
112+
maybe_remove(launcher + '.ps1')
113+
maybe_remove(launcher + '.exe')
114+
if use_exe_files:
115+
shutil.copyfile(windows_exe, launcher + '.exe')
116+
else:
117+
with open(launcher + '.bat', 'w') as f:
118+
f.write(bat_data)
119+
with open(launcher + '.ps1', 'w') as f:
120+
f.write(ps1_data)
107121

108122
generate_entry_points(entry_points, os.path.join(__scriptdir__, 'run_python'))
109123
generate_entry_points(compiler_entry_points, os.path.join(__scriptdir__, 'run_python_compiler'))
110124

111125

112126
if __name__ == '__main__':
113-
sys.exit(main('--all' in sys.argv))
127+
sys.exit(main('--all' in sys.argv, '--exe-files' in sys.argv))

tools/pylauncher/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Windows Python Script Launcher
2+
==============================
3+
4+
This directory contains a simple launcher program for windows which is used to
5+
execute the emscripten compiler entry points using the python interpreter. It
6+
uses the its own name (the name of the currently running executable) to
7+
determine which python script to run and serves the same purpose as the
8+
``run_python.sh`` script does on non-windows platforms.
9+
10+
We build this executable statically using ``/MT`` so that it is maximally
11+
portable.

tools/pylauncher/build.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:: /MT : Statically link to the C runtime library for max portability
2+
:: /O1 : Favor small code (optimization for size)
3+
4+
cl pylauncher.c /Fe:pylauncher.exe /MT /O1

tools/pylauncher/build.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
3+
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
4+
cd ${SCRIPT_DIR}
5+
6+
x86_64-w64-mingw32-gcc -Werror -static-libgcc -static-libstdc++ -s -Os pylauncher.c -o pylauncher.exe -lshlwapi -lshell32

0 commit comments

Comments
 (0)