8000 bpo-40280: Add --with-emscripten-target to build for browser or node … · python/cpython@43839ba · GitHub
[go: up one dir, main page]

Skip to content

Commit 43839ba

Browse files
tiranemmatyping
andauthored
bpo-40280: Add --with-emscripten-target to build for browser or node (GH-30552)
Co-authored-by: Ethan Smith <ethan@ethanhs.me>
1 parent be578e0 commit 43839ba

File tree

7 files changed

+164
-22
lines changed

7 files changed

+164
-22
lines changed

Makefile.pre.in

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ SRCDIRS= @SRCDIRS@
246246
# Other subdirectories
247247
SUBDIRSTOO= Include Lib Misc
248248

249+
# assets for Emscripten browser builds
250+
WASM_ASSETS_DIR=".$(prefix)"
251+
WASM_STDLIB="$(WASM_ASSETS_DIR)/local/lib/python$(VERSION)/os.py"
252+
249253
# Files and directories to be distributed
250254
CONFIGFILES= configure configure.ac acconfig.h pyconfig.h.in Makefile.pre.in
251255
DISTFILES= README.rst ChangeLog $(CONFIGFILES)
@@ -601,6 +605,7 @@ LIBEXPAT_HEADERS= \
601605
all: @DEF_MAKE_ALL_RULE@
602606
build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks \
603607
Programs/_testembed python-config
608+
build_platform: check-clean-src $(BUILDPYTHON) platform
604609

605610
# Check that the source is clean when building out of source.
606611
check-clean-src:
@@ -833,19 +838,12 @@ $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS)
833838
# wasm32-emscripten build
834839
# wasm assets directory is relative to current build dir, e.g. "./usr/local".
835840
# --preload-file turns a relative asset path into an absolute path.
836-
WASM_ASSETS_DIR=".$(prefix)"
837-
WASM_STDLIB="$(WASM_ASSETS_DIR)/local/lib/python$(VERSION)/os.py"
838841

839842
$(WASM_STDLIB): $(srcdir)/Lib/*.py $(srcdir)/Lib/*/*.py \
840843
pybuilddir.txt $(srcdir)/Tools/wasm/wasm_assets.py
841844
$(PYTHON_FOR_BUILD) $(srcdir)/Tools/wasm/wasm_assets.py \
842845
--builddir . --prefix $(prefix)
843846

844-
python.html: Programs/python.o $(LIBRARY_DEPS) $(WASM_STDLIB)
845-
$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o \
846-
$(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) \
847-
-s ASSERTIONS=1 --preload-file $(WASM_ASSETS_DIR)
848-
849847
##########################################################################
850848
# Build static libmpdec.a
851849
LIBMPDEC_CFLAGS=$(PY_STDMODULE_CFLAGS) $(CCSHARED) @LIBMPDEC_CFLAGS@
@@ -2396,7 +2394,7 @@ clean-retain-profile: pycremoval
23962394
-rm -f pybuilddir.txt
23972395
-rm -f Lib/lib2to3/*Grammar*.pickle
23982396
-rm -f _bootstrap_python
2399-
-rm -f python.html python.js python.data
2397+
-rm -f python.html python*.js python.data
24002398
-rm -f Programs/_testembed Programs/_freeze_module
24012399
-rm -f Python/deepfreeze/*.[co]
24022400
-rm -f Python/frozen_modules/*.h
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The ``configure`` script has a new option ``--with-emscripten-target`` to
2+
select browser or node as Emscripten build target.

Modules/socketmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7931,7 +7931,7 @@ PyInit__socket(void)
79317931
#ifdef IPPROTO_VRRP
79327932
PyModule_AddIntMacro(m, IPPROTO_VRRP);
79337933
#endif
7934-
#ifdef IPPROTO_SCTP
7934+
#if defined(IPPROTO_SCTP) && !defined(__EMSCRIPTEN__)
79357935
PyModule_AddIntMacro(m, IPPROTO_SCTP);
79367936
#endif
79377937
#ifdef IPPROTO_BIP

Tools/wasm/README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ embuilder build zlib
2727

2828
### Cross compile to wasm32-emscripten
2929

30+
For browser:
31+
3032
```shell
3133
mkdir -p builddir/emscripten
3234
pushd builddir/emscripten
@@ -35,9 +37,23 @@ CONFIG_SITE=../../Tools/wasm/config.site-wasm32-emscripten \
3537
emconfigure ../../configure -C \
3638
--host=wasm32-unknown-emscripten \
3739
--build=$(../../config.guess) \
40+
--with-emscripten-target=browser \
41+
--with-build-python=$(pwd)/../build/python
42+
43+
emmake make -j$(nproc)
44+
```
45+
46+
For node:
47+
48+
```
49+
CONFIG_SITE=../../Tools/wasm/config.site-wasm32-emscripten \
50+
emconfigure ../../configure -C \
51+
--host=wasm32-unknown-emscripten \
52+
--build=$(../../config.guess) \
53+
--with-emscripten-target=node \
3854
--with-build-python=$(pwd)/../build/python
3955
40-
emmake make -j$(nproc) python.html
56+
emmake make -j$(nproc)
4157
```
4258

4359
### Test in browser

Tools/wasm/config.site-wasm32-emscripten

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ ac_cv_func_shutdown=no
3030
# breaks build, see https://github.com/ethanhs/python-wasm/issues/16
3131
ac_cv_lib_bz2_BZ2_bzCompress=no
3232

33+
# clock_nanosleep() causes time.sleep() to sleep forever.
34+
# nanosleep() works correctly
35+
ac_cv_func_clock_nanosleep=no
36+
ac_cv_lib_rt_clock_nanosleep=no
37+
3338
# The rest is based on pyodide
3439
# https://github.com/pyodide/pyodide/blob/main/cpython/pyconfig.undefs.h
3540

configure

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,8 @@ SHLIB_SUFFIX
846846
LIBTOOL_CRUFT
847847
OTHER_LIBTOOL_OPT
848848
UNIVERSAL_ARCH_FLAGS
849+
WASM_STDLIB
850+
WASM_ASSETS_DIR
849851
LDFLAGS_NOLTO
850852
LDFLAGS_NODIST
851853
CFLAGS_NODIST
@@ -1002,6 +1004,7 @@ with_universal_archs
10021004
with_framework_name
10031005
enable_framework
10041006
with_cxx_main
1007+
with_emscripten_target
10051008
with_suffix
10061009
enable_shared
10071010
enable_profiling
@@ -1751,6 +1754,8 @@ Optional Packages:
17511754
--with-cxx-main[=COMPILER]
17521755
compile main() and link Python executable with C++
17531756
compiler specified in COMPILER (default is $CXX)
1757+
--with-emscripten-target=[browser|node]
1758+
Emscripten platform
17541759
--with-suffix=SUFFIX set executable suffix to SUFFIX (default is empty,
17551760
yes is mapped to '.exe')
17561761
--with-pydebug build with Py_DEBUG defined (default is no)
@@ -6205,6 +6210,41 @@ case $ac_sys_system/$ac_sys_release in #(
62056210
;;
62066211
esac
62076212

6213+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-emscripten-target" >&5
6214+
$as_echo_n "checking for --with-emscripten-target... " >&6; }
6215+
6216+
# Check whether --with-emscripten-target was given.
6217+
if test "${with_emscripten_target+set}" = set; then :
6218+
withval=$with_emscripten_target;
6219+
if test "x$ac_sys_system" = xEmscripten; then :
6220+
6221+
case $with_emscripten_target in #(
6222+
browser) :
6223+
ac_sys_emscripten_target=browser ;; #(
6224+
node) :
6225+
ac_sys_emscripten_target=node ;; #(
6226+
*) :
6227+
as_fn_error $? "Invalid argument: --with-emscripten-target=browser|node" "$LINENO" 5
6228+
;;
6229+
esac
6230+
6231+
else
6232+
6233+
as_fn_error $? "--with-emscripten-target only applies to Emscripten" "$LINENO" 5
6234+
6235+
fi
6236+
6237+
else
6238+
6239+
if test "x$ac_sys_system" = xEmscripten; then :
6240+
ac_sys_emscripten_target=browser
6241+
fi
6242+
6243+
fi
6244+< F987 div class="diff-text-inner">
6245+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_sys_emscripten_target" >&5
6246+
$as_echo "$ac_sys_emscripten_target" >&6; }
6247+
62086248
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-suffix" >&5
62096249
$as_echo_n "checking for --with-suffix... " >&6; }
62106250

@@ -6223,8 +6263,12 @@ esac
62236263

62246264
else
62256265

6226-
case $ac_sys_system in #(
6227-
Emscripten) :
6266+
case $ac_sys_system/$ac_sys_emscripten_target in #(
6267+
Emscripten/browser) :
6268+
EXEEXT=.html ;; #(
6269+
Emscripten/node) :
6270+
EXEEXT=.js ;; #(
6271+
wasi/*) :
62286272
EXEEXT=.wasm ;; #(
62296273
*) :
62306274
EXEEXT=
@@ -7003,6 +7047,7 @@ else
70037047
$as_echo "no" >&6; }
70047048
fi
70057049

7050+
70067051
if test "$Py_OPT" = 'true' ; then
70077052
# Intentionally not forcing Py_LTO='true' here. Too many toolchains do not
70087053
# compile working code using it and both test_distutils and test_gdb are
@@ -7053,8 +7098,10 @@ fi
70537098

70547099
;;
70557100
esac
7056-
7057-
7101+
elif test "$ac_sys_system" = "Emscripten"; then
7102+
DEF_MAKE_ALL_RULE="build_platform"
7103+
REQUIRE_PGO="no"
7104+
DEF_MAKE_RULE="all"
70587105
else
70597106
DEF_MAKE_ALL_RULE="build_all"
70607107
REQUIRE_PGO="no"
@@ -7567,6 +7614,25 @@ then
75677614
esac
75687615
fi
75697616

7617+
# WASM flags
7618+
case $ac_sys_system/$ac_sys_emscripten_target in #(
7619+
Emscripten/browser) :
7620+
7621+
LDFLAGS_NODIST="$(LDFLAGS_NODIST) -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1 --preload-file \$(WASM_ASSETS_DIR)"
7622+
WASM_ASSETS_DIR=".\$(prefix)"
7623+
WASM_STDLIB="\$(WASM_ASSETS_DIR)/local/lib/python\$(VERSION)/os.py"
7624+
;; #(
7625+
Emscripten/node) :
7626+
7627+
LDFLAGS_NODIST="$(LDFLAGS_NODIST) -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1 -s NODERAWFS=1 -s EXIT_RUNTIME=1 -s USE_PTHREADS -s PROXY_TO_PTHREAD"
7628+
CFLAGS_NODIST="$(CFLAGS_NODIST) -pthread"
7629+
;; #(
7630+
*) :
7631+
;;
7632+
esac
7633+
7634+
7635+
75707636

75717637

75727638

@@ -21170,6 +21236,14 @@ else
2117021236
LIBRARY_DEPS="\$(LIBRARY) $LIBRARY_DEPS"
2117121237
fi
2117221238

21239+
case $ac_sys_system/$ac_sys_emscripten_target in #(
21240+
Emscripten/browser) :
21241+
LIBRARY_DEPS="$LIBRARY_DEPS \$(WASM_STDLIB)" ;; #(
21242+
*) :
21243+
;;
21244+
esac
21245+
21246+
2117321247

2117421248

2117521249
# Check whether to disable test modules. Once set, setup.py will not build
@@ -23458,7 +23532,7 @@ $as_echo_n "checking for stdlib extension module xxlimited... " >&6; }
2345823532
*xxlimited*) :
2345923533
py_cv_module_xxlimited=n/a ;; #(
2346023534
*) :
23461-
if test "$with_trace_refs" = "no"; then :
23535+
if test "$with_trace_refs" = "no" -a "$ac_sys_system" != "Emscripten"; then :
2346223536
if true; then :
2346323537
py_cv_module_xxlimited=yes
2346423538
else
@@ -23494,7 +23568,7 @@ $as_echo_n "checking for stdlib extension module xxlimited_35... " >&6; }
2349423568
*xxlimited_35*) :
2349523569
py_cv_module_xxlimited_35=n/a ;; #(
2349623570
*) :
23497-
if test "$with_trace_refs" = "no"; then :
23571+
if test "$with_trace_refs" = "no" -a "$ac_sys_system" != "Emscripten"; then :
2349823572
if true; then :
2349923573
py_cv_module_xxlimited_35=yes
2350023574
else

configure.ac

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,24 @@ AS_CASE([$ac_sys_system/$ac_sys_release],
10621062
]
10631063
)
10641064

1065+
AC_MSG_CHECKING([for --with-emscripten-target])
1066+
AC_ARG_WITH([emscripten-target],
1067+
[AS_HELP_STRING([--with-emscripten-target=@<:@browser|node@:>@], [Emscripten platform])],
1068+
[
1069+
AS_VAR_IF([ac_sys_system], [Emscripten], [
1070+
AS_CASE([$with_emscripten_target],
1071+
[browser], [ac_sys_emscripten_target=browser],
1072+
[node], [ac_sys_emscripten_target=node],
1073+
[AC_MSG_ERROR([Invalid argument: --with-emscripten-target=browser|node])]
1074+
)
1075+
], [
1076+
AC_MSG_ERROR([--with-emscripten-target only applies to Emscripten])
1077+
])
1078+
], [
1079+
AS_VAR_IF([ac_sys_system], [Emscripten], [ac_sys_emscripten_target=browser])
1080+
])
1081+
AC_MSG_RESULT([$ac_sys_emscripten_target])
1082+
10651083
AC_MSG_CHECKING([for --with-suffix])
10661084
AC_ARG_WITH([suffix],
10671085
[AS_HELP_STRING([--with-suffix=SUFFIX], [set executable suffix to SUFFIX (default is empty, yes is mapped to '.exe')])],
@@ -1072,8 +1090,10 @@ AC_ARG_WITH([suffix],
10721090
[EXEEXT=$with_suffix]
10731091
)
10741092
], [
1075-
AS_CASE([$ac_sys_system],
1076-
[Emscripten], [EXEEXT=.wasm],
1093+
AS_CASE([$ac_sys_system/$ac_sys_emscripten_target],
1094+
[Emscripten/browser], [EXEEXT=.html],
1095+
[Emscripten/node], [EXEEXT=.js],
1096+
[wasi/*], [EXEEXT=.wasm],
10771097
[EXEEXT=]
10781098
)
10791099
])
@@ -1446,6 +1466,7 @@ else
14461466
AC_MSG_RESULT(no);
14471467
fi],
14481468
[AC_MSG_RESULT(no)])
1469+
14491470
if test "$Py_OPT" = 'true' ; then
14501471
# Intentionally not forcing Py_LTO='true' here. Too many toolchains do not
14511472
# compile working code using it and both test_distutils and test_gdb are
@@ -1462,8 +1483,12 @@ if test "$Py_OPT" = 'true' ; then
14621483
])
14631484
;;
14641485
esac
1465-
1466-
1486+
elif test "$ac_sys_system" = "Emscripten"; then
1487+
dnl Emscripten does not support shared extensions yet. Build
1488+
dnl "python.[js,html,wasm]", "pybuilddir.txt", and "platform" files.
1489+
DEF_MAKE_ALL_RULE="build_platform"
1490+
REQUIRE_PGO="no"
1491+
DEF_MAKE_RULE="all"
14671492
else
14681493
DEF_MAKE_ALL_RULE="build_all"
14691494
REQUIRE_PGO="no"
@@ -1769,10 +1794,25 @@ then
17691794
esac
17701795
fi
17711796

1797+
# WASM flags
1798+
AS_CASE([$ac_sys_system/$ac_sys_emscripten_target],
1799+
[Emscripten/browser], [
1800+
LDFLAGS_NODIST="$(LDFLAGS_NODIST) -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1 --preload-file \$(WASM_ASSETS_DIR)"
1801+
WASM_ASSETS_DIR=".\$(prefix)"
1802+
WASM_STDLIB="\$(WASM_ASSETS_DIR)/local/lib/python\$(VERSION)/os.py"
1803+
],
1804+
[Emscripten/node], [
1805+
LDFLAGS_NODIST="$(LDFLAGS_NODIST) -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1 -s NODERAWFS=1 -s EXIT_RUNTIME=1 -s USE_PTHREADS -s PROXY_TO_PTHREAD"
1806+
CFLAGS_NODIST="$(CFLAGS_NODIST) -pthread"
1807+
],
1808+
)
1809+
17721810
AC_SUBST(BASECFLAGS)
17731811
AC_SUBST(CFLAGS_NODIST)
17741812
AC_SUBST(LDFLAGS_NODIST)
17751813
AC_SUBST(LDFLAGS_NOLTO)
1814+
AC_SUBST([WASM_ASSETS_DIR])
1815+
AC_SUBST([WASM_STDLIB])
17761816

17771817
# The -arch flags for universal builds on macOS
17781818
UNIVERSAL_ARCH_FLAGS=
@@ -6252,6 +6292,12 @@ if test "$PY_ENABLE_SHARED" = 1 || test "$enable_framework" ; then
62526292
else
62536293
LIBRARY_DEPS="\$(LIBRARY) $LIBRARY_DEPS"
62546294
fi
6295+
6296+
dnl browser needs a WASM assets stdlib bundle
6297+
AS_CASE([$ac_sys_system/$ac_sys_emscripten_target],
6298+
[Emscripten/browser], [LIBRARY_DEPS="$LIBRARY_DEPS \$(WASM_STDLIB)"],
6299+
)
6300+
62556301
AC_SUBST(STATIC_LIBPYTHON)
62566302
AC_SUBST(LIBRARY_DEPS)
62576303

@@ -6520,8 +6566,9 @@ PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [], [], [-lm])
65206566

65216567
dnl Limited API template modules.
65226568
dnl The limited C API is not compatible with the Py_TRACE_REFS macro.
6523-
PY_STDLIB_MOD([xxlimited], [test "$with_trace_refs" = "no"])
6524-
PY_STDLIB_MOD([xxlimited_35], [test "$with_trace_refs" = "no"])
6569+
dnl Emscripten does not support shared libraries yet.
6570+
PY_STDLIB_MOD([xxlimited], [test "$with_trace_refs" = "no" -a "$ac_sys_system" != "Emscripten"])
6571+
PY_STDLIB_MOD([xxlimited_35], [test "$with_trace_refs" = "no" -a "$ac_sys_system" != "Emscripten"])
65256572

65266573
# substitute multiline block, must come after last PY_STDLIB_MOD()
65276574
AC_SUBST([MODULE_BLOCK])

0 commit comments

Comments
 (0)
0