Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
ed4c9a8
re-edited library files, adding NC
cdwensley May 20, 2026
1f6bbaf
added non-NC methods so that tests pass
cdwensley May 20, 2026
5b98560
adjust documentation in mapping.gd
cdwensley May 20, 2026
9fd6948
replace items deleted in error in alghom.gi
cdwensley May 21, 2026
8481a39
applied fix from stertooy
cdwensley May 21, 2026
a8e5012
minor correction
cdwensley May 21, 2026
168d917
another adjustment to bugfix test
cdwensley May 21, 2026
e61b7cb
PackageVariablesInfo: better support variadic functions (#6404)
fingolfin May 19, 2026
f496cda
kernel: strengthen vecgf2 and vec8bit validation, reject empty vector…
fingolfin May 21, 2026
fb67a5c
Document SemiSimpleType field restriction (#6408)
fingolfin May 22, 2026
36f7f08
Clarify IsomorphismPcGroup docs (#6405)
fingolfin May 22, 2026
7d9c9f0
Reformat and refactor StructureDescription code (#6403)
fingolfin May 22, 2026
1c6c7ff
Add new logo to banner (B&W) (#6357)
mtorpey May 23, 2026
707c955
Switch banner to fully compact mode
fingolfin May 23, 2026
8a57dea
Turn LoadPackageDocumentation into a unary function (#6411)
fingolfin May 26, 2026
b49098a
doc: describe OrbitStabilizer return value (closes #6324) (#6410)
mvanhorn May 26, 2026
2fd8c10
Run --bare testinstall test in CI (#6354)
fingolfin May 27, 2026
06bb20b
Prepare release notes for GAP 4.16.0 (#6414)
fingolfin May 27, 2026
f14734d
Start work on GAP 4.17
fingolfin May 27, 2026
9f5c520
emscripten: add Docker-based one-stop build and polish demo page (#6385)
ChrisJefferson Jun 1, 2026
9de742a
Update COPYRIGHT
fingolfin Jun 1, 2026
cb25fa7
Fix RingGeneralMappingByImages for non-SCRing (#6418)
fingolfin Jun 1, 2026
ac1d8e9
Update CHANGES.md
fingolfin Jun 1, 2026
9490b09
Normalize release archive permissions (#6420)
fingolfin Jun 1, 2026
8ae5f61
julia-gc: introduce DISABLE_STACK_SCAN (#6421)
fingolfin Jun 5, 2026
2485080
Miscellaneous kernel tweaks (#6422)
fingolfin Jun 6, 2026
77f8ab0
More kernel tweaks (#6428)
fingolfin Jun 6, 2026
f1710d2
kernel: remove `ErrorReturnObj`, `C_NEW_STRING` (#6415)
fingolfin Jun 6, 2026
871d4fc
Fix ConjugateGroup for matrix groups not defined over a field (#6425)
fingolfin Jun 6, 2026
834868e
kernel: improve `ErrorReturnVoid` break-loop message (#6416)
fingolfin Jun 8, 2026
dece204
kernel: refactor FuncPRINT_CURRENT_STATEMENT (#6424)
fingolfin Jun 8, 2026
4e09c08
Adjust when 'Stack trace:' message is printed (#6432)
fingolfin Jun 8, 2026
a124678
build(deps): bump codecov/codecov-action from 6 to 7 (#6430)
dependabot[bot] Jun 8, 2026
ba5ed0c
Adjust conway polynomial error message (#6433)
fingolfin Jun 9, 2026
5dcc98e
Widen declaration for many matrix related functions (#6095)
fingolfin Jun 9, 2026
51da696
Further unify messages before break loop (#6434)
fingolfin Jun 10, 2026
0ad351b
Remove dev/migratedoc.tex and doc/tut/migrat.xml (#6431)
fingolfin Jun 10, 2026
f7afbcc
Remove SingleCollector_CollectWordRunning (#6426)
fingolfin Jun 11, 2026
4fea974
kernel: cleanup CRC code (#6436)
fingolfin Jun 11, 2026
3cd543f
doc: fix typo (#6438)
fingolfin Jun 11, 2026
f49b3f8
replaced 'return []' by 'return fail'
cdwensley Jun 18, 2026
f3dd617
build(deps): bump actions/checkout from 6 to 7 (#6444)
dependabot[bot] Jun 23, 2026
8532737
Remove InfoData, make INFO_CLASSES readonly (#6443)
fingolfin Jun 23, 2026
16256d1
Move over changes to the GAP.jl-CI job (#6445)
lgoettgens Jun 24, 2026
bd1a466
Perfect groups data is licensed under GPL 2.0 or later (#6450)
Jul 1, 2026
29814ef
Add an argument check to `CodePcgs` (#6451)
ThomasBreuer Jul 1, 2026
19f7a2e
kernel: make FormatOutput handle %g with null pointer (#6446)
fingolfin Jul 1, 2026
d22a930
turn the global variable `RUN_IN_GGMBI` into a global option `Run_In_…
ThomasBreuer Jul 1, 2026
18001cd
Document the encoding used by CodePcGroup & PcGroupCode (#6441)
mvanhorn Jul 1, 2026
4a30040
re-edited library files, adding NC
cdwensley May 20, 2026
15f971e
Merge branch 'master' into preimrep2
ThomasBreuer Jul 6, 2026
ca8a6ca
removed unwanted .changed file
cdwensley Jul 6, 2026
59dd0ef
fix a ref in mapping.gd, line 980
cdwensley Jul 6, 2026
9c97dd2
Merge branch 'master' into preimrep2
cdwensley Jul 8, 2026
c6d4f4e
made changes suggested by Thomas
cdwensley Jul 8, 2026
4a39d24
made changes suggested by Thomas
cdwensley Jul 8, 2026
f28660d
made changes suggested by Thomas
cdwensley Jul 8, 2026
01360af
added many error messages and a few methods
cdwensley Jul 9, 2026
fc31d4e
added many error messages and a few methods
cdwensley Jul 9, 2026
cb7672c
Change deprecated RUN_IN_GGMBI to `fail` (#6458)
fingolfin Jul 13, 2026
8a364fe
Add `ChiefLength` (length of any chief series) (#6455)
ThomasBreuer Jul 14, 2026
181f489
re-edited library files, adding NC
cdwensley May 20, 2026
94a8ca6
kernel: improve `ErrorReturnVoid` break-loop message (#6416)
fingolfin Jun 8, 2026
3c72620
Adjust when 'Stack trace:' message is printed (#6432)
fingolfin Jun 8, 2026
5ed2b08
turn the global variable `RUN_IN_GGMBI` into a global option `Run_In_…
ThomasBreuer Jul 1, 2026
5bd2601
adjusted the documentation in 32.5
cdwensley Jul 9, 2026
93ab537
using Intersection(elms,Range(map)) in PreImagesSet
cdwensley Jul 15, 2026
510aae3
addition to tst/testinstall/mapphomo.tst
cdwensley Jul 15, 2026
4348a34
using Intersection(elms,Range(map)) in PreImagesSet
cdwensley Jul 15, 2026
8dcf46e
revise the documentation for PreImagesSet
cdwensley Jul 15, 2026
aa5a67c
revise the documentation for PreImagesSet
cdwensley Jul 15, 2026
5e7c1cf
Update lib/field.gi
cdwensley Jul 17, 2026
866331f
Update lib/fldabnum.gi
cdwensley Jul 17, 2026
bdab1a8
Update lib/ghom.gi
cdwensley Jul 17, 2026
0fadf64
Update lib/ghomfp.gi
cdwensley Jul 17, 2026
425e88f
Update lib/ghomperm.gi
cdwensley Jul 17, 2026
208dbcf
Update lib/mapprep.gi
cdwensley Jul 17, 2026
c187191
Update lib/mapprep.gi
cdwensley Jul 17, 2026
6b40948
Update lib/mapprep.gi
cdwensley Jul 17, 2026
58b8c93
Update lib/mapprep.gi
cdwensley Jul 17, 2026
a84b430
Update lib/mapprep.gi
cdwensley Jul 17, 2026
5df23f7
Update lib/ghomperm.gi
cdwensley Jul 17, 2026
76b5357
Update lib/ghomperm.gi
cdwensley Jul 17, 2026
d600804
Update lib/mapphomo.gi
cdwensley Jul 17, 2026
ed90c7a
Update lib/mapphomo.gi
cdwensley Jul 17, 2026
fee4027
Update lib/mapphomo.gi
cdwensley Jul 17, 2026
c76bae6
Update lib/mapphomo.gi
cdwensley Jul 17, 2026
275940a
Update lib/mapphomo.gi
cdwensley Jul 17, 2026
994ef08
Update lib/mapping.gi
cdwensley Jul 17, 2026
0adad7d
Update lib/mapping.gd
cdwensley Jul 17, 2026
648454f
Update lib/mapphomo.gi
cdwensley Jul 17, 2026
ff611b0
Update lib/mapping.gi
cdwensley Jul 17, 2026
5ccc37d
Update lib/mapping.gi
cdwensley Jul 17, 2026
a122e74
Update lib/mapping.gi
cdwensley Jul 17, 2026
994c6b2
query in mapprep.gi answered by Thomas
cdwensley Jul 17, 2026
93b86b0
Update lib/mapprep.gi
cdwensley Jul 20, 2026
fbb579f
adjusted the documentation in 32.5
cdwensley Jul 20, 2026
2d68eea
Fix `BaumClausenInfo` when the pcgs is not G-invariant (#6459)
ThomasBreuer Jul 16, 2026
e817c22
Automorphism cleanup (#6462)
hulpke Jul 17, 2026
5ddc87f
Add SpeedupDataPcHom (#6449)
hulpke Jul 18, 2026
1885aa5
Fix a bug that could lead to `ContainedConjugates` returning too many…
hulpke Jul 19, 2026
a4c85fc
FIX: solvable steps in FittingFree classes (#6466)
hulpke Jul 23, 2026
a24cbd5
FIX: Typos and grammatical errors in comments across Hulpke-authored …
hulpke Jul 23, 2026
58d546e
re-edited library files, adding NC
cdwensley May 20, 2026
836425e
kernel: improve `ErrorReturnVoid` break-loop message (#6416)
fingolfin Jun 8, 2026
e686be5
Further unify messages before break loop (#6434)
fingolfin Jun 10, 2026
eb1b3b7
Remove dev/migratedoc.tex and doc/tut/migrat.xml (#6431)
fingolfin Jun 10, 2026
bfcd6a2
turn the global variable `RUN_IN_GGMBI` into a global option `Run_In_…
ThomasBreuer Jul 1, 2026
dedd030
Merge branch 'master' into preimrep2
fingolfin Jul 23, 2026
f491120
New emscripten polish (#6439)
ChrisJefferson Jul 23, 2026
32b58b6
re-edited library files, adding NC
cdwensley May 20, 2026
87c75ac
fixing a manual reference (again)
cdwensley Jul 27, 2026
5e20028
remove PreImagesNC from lib/
cdwensley Jul 28, 2026
0ec5b91
remove PreImagesNC from lib/
cdwensley Jul 28, 2026
8a55094
PreImageElm now returns an error if elm not in the image of map
cdwensley Jul 28, 2026
57913ec
more edits to PreImages documentation
cdwensley Jul 29, 2026
c1762a4
more edits to PreImages documentation
cdwensley Jul 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion doc/ref/mloop.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<!-- %%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
<!-- %% -->
<!-- %A mloop.xml GAP documentation Martin Schönert -->
<!-- %% -->
Expand Down Expand Up @@ -477,6 +478,7 @@ indicate that you are in a break loop.
<Log><![CDATA[
gap> 1/0;
Error, Rational operations: <divisor> must not be zero
Stack trace:
not in any function at *stdin*:2
you can enter 'quit;' to quit to outer loop
]]></Log>
Expand Down
89 changes: 84 additions & 5 deletions etc/emscripten/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

Build GAP as a WebAssembly module and serve it as a self-contained website.
The terminal interface uses [xterm-pty](https://github.com/mame/xterm-pty),
so the resulting page behaves like a normal GAP REPL.
so the resulting page behaves like a normal GAP REPL. The page is styled
to match <https://www.gap-system.org> (Ubuntu fonts, GAP logo, crimson
accents, dark-mode support) and adds a side panel for moving files in and
out of the browser session, an examples menu, and a restart button.

## Quick start

Expand Down Expand Up @@ -50,6 +53,81 @@ TTY device so `tcsetattr()` reaches the line discipline. Both are sensitive
to the toolchain version (a newer emsdk leaves `tcsetattr` unhonoured, so
typed input is echoed twice), so re-test the REPL when changing emsdk.

## The `io` package

The wasm build has no `dlopen`, so a package kernel extension cannot be
loaded the usual way. `build.sh` works around this for `io` by compiling
its single C file into the GAP kernel and registering it in the
static-module table (`src/compstat.c`), so `LoadKernelExtension("io")`
finds it without `dlopen`. This is the GASMAN-safe approach: `io` ends up
in the one wasm module, so ASYNCIFY's link-time pass instruments it
uniformly and `emscripten_scan_registers()` sees its frames (unlike a
dynamically loaded side module). The mechanism is detailed in the
comments in `build.sh` around the `IO_OBJ` block, with the registration
helper in `register_static_module.py`.

`io` is the kernel dependency of several otherwise pure-GAP packages
(simpcomp, fr, rcwa, unitlib, …), so linking it in lets them load. Its
file/directory/time functions work; its socket/fork/select functions
compile but fail at runtime, since wasm has no such facilities.

## The page: file transfer, examples, restart

GAP runs with its working directory set to `/home/web_user` in the
virtual filesystem (the GAP tree itself sits at `/`, passed via `-l /`).
That directory starts empty, so everything in it is the user's: uploads
land there, and anything GAP creates there (`PrintTo`, `LogTo`, …) shows
up in the page's Files panel for download.

The design is shaped by one constraint. Once GAP's `main()` starts, the
worker thread never returns to its event loop: every terminal operation
blocks in `Atomics.wait` inside xterm-pty's `TtyClient` until the main
thread responds. So `postMessage` *to* the worker is never delivered
after startup, while `postMessage` *from* the worker (the tty request
channel itself) always works. Hence:

- **Uploads** go through a `SharedArrayBuffer` mailbox (chunked, see the
protocol comment in `gap-worker.js`; the sending side is in
`gap-ui.js`). The worker drains it at the start of every terminal
operation — the moments it is provably awake. An upload made while GAP
sits idle at its prompt therefore completes on the next terminal
activity; in particular, the Files panel's "insert `Read("file");`"
button pastes keystrokes whose processing drains the mailbox before
GAP ever sees the Enter, so the file is always in place in time.
- **Downloads** are pushed: when GAP asks for input (output has settled,
files are complete), the worker rescans `/home/web_user` and posts new
or changed files to the page, which caches the bytes. A download click
is served from that cache — it never has to ask the possibly-blocked
worker. This is also why a freshly written file only appears in the
panel once GAP is back at a prompt (or asks for input).
- Inserted commands (file hints and the examples menu) are pasted
*without* a newline; the user always presses Enter, so nothing is
auto-executed.

### Cache invalidation across redeployments

Library files are cached in the browser's IndexedDB and reused on later
visits without revalidation. To stop a redeployment from pairing a new
kernel with stale cached library files, `assemble-website.sh` writes a
fresh `build-id` file into the site; `gap-fs.js` compares it (fetched
with `cache: no-cache`) against the copy stored in the cache and
discards the cache when it differs. The page footer also has a "Reset
cached data" link that drops the cache and any registered service
worker and reloads — the escape hatch for any stuck client state.

Known limitations, all consequences of the same architecture:

- Ctrl-C cannot interrupt a running computation: there are no signals,
the main thread cannot reach the worker's wasm heap, and GAP cannot
poll JavaScript state while computing. The Restart button (which
terminates and respawns the worker) is the only escape from a runaway
computation. The Files panel keeps its cached entries across a
restart, still downloadable; inserting one re-uploads it first.
- User files do not persist across reloads or restarts (syncing them to
IndexedDB would need the worker's event loop, which is starved).
- The terminal is sized to the window before GAP starts; GAP does not
notice later resizes (no SIGWINCH), though xterm itself reflows.

## Hosting

The xterm-pty terminal uses `SharedArrayBuffer`, which browsers only allow
Expand All @@ -71,12 +149,13 @@ re-fetches resources through a service worker that adds the headers).
| ---- | ---- |
| `build-in-docker.sh` | One-stop entry point. Builds the image, runs `build.sh` inside, then `assemble-website.sh`. |
| `Dockerfile` | Pinned `emscripten/emsdk:3.1.23` with autotools, python3, bison/byacc/m4, and a baked-in copy of the GAP package distribution tarball at `/opt/gap-packages.tar.gz`. |
| `build.sh` | Configures and builds GMP, zlib, and GAP itself for wasm. |
| `build.sh` | Configures and builds GMP, zlib, and GAP itself for wasm. Also statically links the `io` package's kernel module into the kernel (see below). |
| `assemble-website.sh` | Copies the build outputs and data directories (`pkg`, `lib`, `grp`, …) into `web-example/`. |
| `generate_gap_fs_json.py` | Reads file paths on stdin, writes `gap-fs.json` (the manifest of every file in the virtual FS). |
| `startup_manifest.json` | List of files to fetch eagerly at startup, captured from a real GAP run. Anything not in this list is fetched lazily on first read. See "Updating the startup manifest" below for how to refresh it. |
| `serve.py` | Local server that adds the COOP/COEP headers. |
| `web-template/` | Static UI: `index.html`, the worker scripts, the FS init shim, and the COOP/COEP service worker for hosts where you can't set headers. |
| `web-template/` | Static UI: `index.html`, the page logic (`gap-ui.js`), the worker scripts, the FS init shim, and the COOP/COEP service worker for hosts where you can't set headers. |
| `web-template/vendor/` | Pinned local copies of xterm, xterm-pty, the fit addon, the GAP logo and the Ubuntu fonts, so the deployed site has no CDN dependency. See `web-template/vendor/README.md` for versions and how to update them. |

## Updating the startup manifest

Expand Down Expand Up @@ -111,8 +190,8 @@ To regenerate it after such changes:
`window.fetchedUrls` is an array of every unique URL the worker
requested. Chrome/Firefox provide a `copy()` console helper:
`copy(JSON.stringify(fetchedUrls))` puts the JSON on your clipboard.
5. Strip non-GAP-FS entries (`gap.js`, `gap.wasm`, `gap-fs.json`, the
xterm CDN URLs) and write the result to
5. Strip non-GAP-FS entries (`gap.js`, `gap.wasm`, `gap-fs.json`, and any
`vendor/` assets) and write the result to
`etc/emscripten/startup_manifest.json` (so it's checked in and gets
picked up by the next `assemble-website.sh`). A `jq` filter that
keeps just GAP filesystem paths:
Expand Down
23 changes: 15 additions & 8 deletions etc/emscripten/assemble-website.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ done
rm -rf "$OUT_DIR"
mkdir -p "$OUT_DIR"

cp "$SCRIPT_DIR"/web-template/* "$OUT_DIR"/
cp -R "$SCRIPT_DIR"/web-template/* "$OUT_DIR"/
cp "$SCRIPT_DIR"/startup_manifest.json "$OUT_DIR"/
cp gap.js gap.wasm gap-fs.json "$OUT_DIR"/
# Emscripten only emits a separate gap.worker.js for pthread builds; this
Expand All @@ -41,20 +41,27 @@ cp LICENSE COPYRIGHT "$OUT_DIR"/
# loaded (if listed in startup_manifest.json) or lazily fetched on first
# read by Emscripten's createLazyFile.
#
# -L dereferences symlinks so the output tree is self-contained (a setup
# where pkg/X is a symlink into a separate checkout still works). Some
# packages ship dangling symlinks as build artefacts (e.g. pkg/vole's
# rust/target/*.dSYM); cp prints those and exits non-zero but still copies
# everything else, so we don't let that abort the run. The assertion below
# catches a genuinely incomplete copy.
# tar -h dereferences symlinks so the output tree is self-contained (a
# setup where pkg/X is a symlink into a separate checkout still works);
# --exclude .git keeps such checkouts' git internals out of the shipped
# site. Some packages ship dangling symlinks as build artefacts (e.g.
# pkg/vole's rust/target/*.dSYM); tar reports those and exits non-zero
# but still copies everything else, so we don't let that abort the run.
# The assertion below catches a genuinely incomplete copy.
for d in pkg lib grp tst doc hpcgap dev benchmark; do
cp -RL "$d" "$OUT_DIR"/ 2>/dev/null || true
tar -c -h --exclude '.git' -f - "$d" 2>/dev/null | tar -x -C "$OUT_DIR" -f - || true
done

# pkg/log holds package test logs (.log/.err/.out) that are never read at
# runtime; keep them out of the shipped site.
rm -rf "$OUT_DIR/pkg/log"

# A fresh id per assembled site. gap-fs.js compares it against the copy
# stored in the browser's IndexedDB cache and discards the cache when it
# differs, so a redeployment can never pair a new kernel with stale
# cached library files.
echo "$(date -u +%Y%m%dT%H%M%SZ)-$$" > "$OUT_DIR/build-id"

# The library bootstrap must be present, or GAP 404s during startup.
if [[ ! -f "$OUT_DIR/lib/init.g" ]]; then
echo "Error: lib/init.g missing from $OUT_DIR after copy." >&2
Expand Down
73 changes: 72 additions & 1 deletion etc/emscripten/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,17 @@ if [[ ! -f GNUmakefile ]] || ! grep -q '/emcc' GNUmakefile; then
# emcc would be regenerated by a non-executable JS shim; stale .o
# files have the wrong architecture. Configure regenerates build/.
rm -rf build ffgen
# PTHREAD_CFLAGS/PTHREAD_LIBS: configure unconditionally adopts
# -pthread (for the sake of native kernel extensions, see configure.ac),
# but under emcc that flag enables full USE_PTHREADS mode — shared
# wasm memory, a helper worker, and a slow path when combined with
# ALLOW_MEMORY_GROWTH. GAP itself is single-threaded here, and
# emscripten's libc provides single-threaded pthread API stubs, so
# pre-seeding the variables makes AX_PTHREAD settle on "no flags".
emconfigure ./configure ABI=32 \
--with-gmp="$AUX_PREFIX" \
--with-zlib="$AUX_PREFIX" \
PTHREAD_CFLAGS=" " PTHREAD_LIBS=" " \
LDFLAGS="-s ASYNCIFY=1 -O2"
fi

Expand All @@ -125,13 +133,76 @@ fi
# Copy host-built generated sources into place
cp native-build/build/c_*.c native-build/build/ffdata.* src/

# Statically link the 'io' package's kernel module into the GAP kernel.
#
# The wasm build has no dlopen, so a package kernel extension cannot be
# loaded the usual way. But GAP's loader already supports STATIC modules:
# LoadKernelExtension("io") (in io's init.g) checks SHOW_STAT() -- the
# list of names in CompInitFuncs[] (src/compstat.c) -- and loads a match
# without dlopen (see lib/files.gd). So we compile io's single C file into
# the kernel and add it to that table; no change to GAP's loader or io's
# GAP code is needed. This is the safe approach for GASMAN: io ends up in
# the one wasm module, so ASYNCIFY's link-time pass instruments it
# uniformly with the rest of the kernel and emscripten_scan_registers
# sees its frames (unlike a dlopen'd side module).
#
# io is the kernel dependency of several otherwise pure-GAP packages
# (simpcomp, fr, rcwa, unitlib, ...). Its socket/fork/select-based
# functions compile (emscripten declares the symbols) but fail at runtime
# under wasm; its file/directory/time functions work.
IO_OBJ=""
if [[ -d pkg/io ]]; then
IO_PKG="$PWD/pkg/io"
# io's configure (autoconf feature probe) writes gen/pkgconfig.h, which
# io.c needs. FIND_GAP may fail without a fully built GAP in $BASEDIR
# and exit non-zero, but pkgconfig.h is still generated by then, so we
# tolerate the exit code and assert on the file instead.
(
cd "$IO_PKG"
[[ -f configure ]] || ./autogen.sh
emconfigure ./configure --with-gaproot="$BASEDIR" || true
)
if [[ ! -f "$IO_PKG/gen/pkgconfig.h" ]]; then
echo "Error: io's pkgconfig.h was not generated; cannot link io." >&2
exit 1
fi
# io.c (via gap_all.h) includes generated kernel headers. The normal
# build generates these before compiling any object; since we compile
# io.o ahead of that, generate them first.
emmake make build/version.h build/config.h
# Compile io.c, renaming its generic Init__Dynamic to the unique
# Init__io that the static-module table references. ASYNCIFY is a
# link-time pass, so it is not (and must not be) given here.
emcc -m32 -c "$IO_PKG/src/io.c" -o "$AUX_BUILD/io.o" \
-DInit__Dynamic=Init__io \
-Isrc -Ibuild -Isrc/extra \
-I"$IO_PKG/gen" -I"$IO_PKG/src" \
-I"$AUX_PREFIX/include" \
-fPIC -fno-strict-aliasing -O2
python3 etc/emscripten/register_static_module.py io src/compstat.c
IO_OBJ="$AUX_BUILD/io.o"
fi

# Build the file list that will be served. -L follows symlinks so that
# users' local development setups (e.g. replacing pkg/foo with a symlink
# to a git checkout under git/foo) are picked up; -type f then drops any
# symlinks themselves.
find -L pkg lib grp tst doc hpcgap dev benchmark -type f ! -path 'pkg/log/*' \
! -path '*/.git/*' \
| python3 etc/emscripten/generate_gap_fs_json.py

# Emscripten only emits gap.worker.js for pthread builds; remove any
# leftover from a previous configuration so assemble-website.sh can't
# ship a stale one.
rm -f gap.worker.js

# Memory: start small and grow on demand (sbrk stays contiguous, which
# GASMAN's workspace extension requires, since wasm memory grows in
# place). A 2GB up-front allocation was refused outright on iOS.
# $IO_OBJ (if set) is the statically-linked io module object; it goes on
# the link line, where the Init__io reference from src/compstat.c pulls it
# in. LDFLAGS flows into GAP_LDFLAGS (see Makefile.rules), which is part of
# the final link command.
emmake make -j"$JOBS" \
LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=2048mb -O2" \
LDFLAGS="-lidbfs.js -s ASYNCIFY=1 -sTOTAL_STACK=32mb -sASYNCIFY_STACK_SIZE=32000000 -sINITIAL_MEMORY=256mb -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2048mb $IO_OBJ -O2" \
EXEEXT=".html"
36 changes: 36 additions & 0 deletions etc/emscripten/register_static_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
"""Register a package kernel module as a static module in src/compstat.c.

GAP's static-module table (CompInitFuncs[] in src/compstat.c) is the list
of init functions that SHOW_STAT() reports; LoadKernelExtension finds a
module there and loads it without dlopen (which the wasm build lacks).
This adds an entry for a module whose init function has been renamed to
Init__<name> (via -DInit__Dynamic=Init__<name> when compiling it).

Idempotent: running twice for the same module is a no-op. Usage:
register_static_module.py <module-name> [path/to/compstat.c]
"""
import re
import sys

name = sys.argv[1]
path = sys.argv[2] if len(sys.argv) > 2 else "src/compstat.c"
init = "Init__" + name

src = open(path).read()
if init in src:
sys.exit(0) # already registered

# Add the extern declaration after the last existing one.
externs = list(re.finditer(r"extern StructInitInfo \* Init__\w+\(void\);\n", src))
if not externs:
sys.exit("register_static_module: no extern declarations found in " + path)
at = externs[-1].end()
src = src[:at] + "extern StructInitInfo * %s(void);\n" % init + src[at:]

# Add the entry before the 0 terminator of CompInitFuncs[].
src, n = re.subn(r"\n(\s*)0(,?\n\};)", r"\n\1%s,\n\g<1>0\2" % init, src, count=1)
if n != 1:
sys.exit("register_static_module: could not find CompInitFuncs terminator in " + path)

open(path, "w").write(src)
3 changes: 3 additions & 0 deletions etc/emscripten/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class CrossOriginIsolatedHandler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header("Cross-Origin-Opener-Policy", "same-origin")
self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
# Without this, browsers cache the UI files heuristically and
# edits to web-example/ don't show up on reload.
self.send_header("Cache-Control", "no-cache")
super().end_headers()


Expand Down
Loading
Loading