Skip to content

Commit 06a0137

Browse files
authored
Switch to memory64 for the Wasm build to enable greater memory usage. (#99)
Now we forcibly return a double instead of size_ts for all methods, to avoid the confusion of dealing with a mix of Numbers/BigInts in Javascript. Node >= 24 MUST be used with memory64. Updated actions to use the latest builder image with an appropriately modern Node.
1 parent 80fff5e commit 06a0137

15 files changed

Lines changed: 83 additions & 55 deletions

.github/workflows/publish-npm.yaml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,25 @@ on:
77
name: Build and publish to NPM
88

99
jobs:
10+
prepare-version:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout repo
14+
uses: actions/checkout@v4
15+
16+
- id: find-version
17+
run: |
18+
version=$(cat .image-version)
19+
echo "version=${version}" >> $GITHUB_OUTPUT
20+
21+
outputs:
22+
version: ${{ steps.find-version.outputs.version }}
23+
1024
build:
1125
runs-on: ubuntu-latest
26+
needs: [prepare-version]
1227
if: ${{ github.event.workflow_run.conclusion == 'success' }}
13-
container: ghcr.io/kanaverse/emcmake-docker/builder:master
28+
container: ghcr.io/kanaverse/emcmake-docker/builder:${{ needs.prepare-version.outputs.version }}
1429

1530
steps:
1631
- name: Checkout repo
@@ -19,7 +34,7 @@ jobs:
1934
- name: Set up Node
2035
uses: actions/setup-node@v4
2136
with:
22-
node-version: 18
37+
node-version: 24
2338
registry-url: 'https://registry.npmjs.org'
2439

2540
# We only run the remaining (remote-touching) steps if the version has actually changed.
@@ -38,7 +53,7 @@ jobs:
3853
uses: actions/cache@v4
3954
with:
4055
path: extern/installed
41-
key: deps-${{ hashFiles('extern/**/build.sh') }}-${{ env.IMAGE_VERSION }}
56+
key: deps-${{ hashFiles('extern/**/build.sh') }}-${{ needs.prepare-version.outputs.version }}
4257

4358
- name: Cache Modules
4459
if: env.UPDATE_SCRANJS == 1
@@ -64,7 +79,7 @@ jobs:
6479
uses: actions/cache@v4
6580
with:
6681
path: tests/rds/*.rds
67-
key: rds-${{ hashFiles('tests/rds/generate.R') }}
82+
key: rds-${{ hashFiles('tests/rds/generate.R') }}-${{ needs.prepare-version.outputs.version }}
6883

6984
- name: Double-checking tests
7085
if: env.UPDATE_SCRANJS == 1

.github/workflows/run-tests.yaml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,20 @@ on:
66

77
name: Test JS bindings
88

9-
env:
10-
IMAGE_VERSION: master
11-
129
jobs:
1310
prepare-version:
1411
runs-on: ubuntu-latest
1512
steps:
16-
- run: echo "null"
13+
- name: Checkout repo
14+
uses: actions/checkout@v4
15+
16+
- id: find-version
17+
run: |
18+
version=$(cat .image-version)
19+
echo "version=${version}" >> $GITHUB_OUTPUT
20+
1721
outputs:
18-
version: ${{ env.IMAGE_VERSION }}
22+
version: ${{ steps.find-version.outputs.version }}
1923

2024
# Building the RDS files for the various RDS-reading utilities.
2125
create_rds:
@@ -53,7 +57,7 @@ jobs:
5357
uses: actions/cache@v4
5458
with:
5559
path: extern/installed
56-
key: deps-${{ hashFiles('extern/**/build.sh') }}-${{ env.IMAGE_VERSION }}
60+
key: deps-${{ hashFiles('extern/**/build.sh') }}-${{ needs.prepare-version.outputs.version }}
5761

5862
- name: Build HDF5
5963
if: steps.installed.outputs.cache-hit != 'true'
@@ -79,7 +83,7 @@ jobs:
7983
- name: Set up Node
8084
uses: actions/setup-node@v4
8185
with:
82-
node-version: 18
86+
node-version: 24
8387

8488
- name: Cache Modules
8589
uses: actions/cache@v4
@@ -94,7 +98,7 @@ jobs:
9498
uses: actions/cache@v4
9599
with:
96100
path: extern/installed
97-
key: deps-${{ hashFiles('extern/**/build.sh') }}-${{ env.IMAGE_VERSION }}
101+
key: deps-${{ hashFiles('extern/**/build.sh') }}-${{ needs.prepare-version.outputs.version }}
98102

99103
- name: Cache RDS files
100104
uses: actions/cache@v4
@@ -107,7 +111,7 @@ jobs:
107111
uses: actions/cache@v4
108112
with:
109113
path: js/wasm
110-
key: wasm-${{ hashFiles('build.sh', 'extern/**/build.sh', 'CMakeLists.txt', 'extern/CMakeLists.txt', 'src/*') }}-${{ env.IMAGE_VERSION }}
114+
key: wasm-${{ hashFiles('build.sh', 'extern/**/build.sh', 'CMakeLists.txt', 'extern/CMakeLists.txt', 'src/*') }}-${{ needs.prepare-version.outputs.version }}
111115

112116
- name: Update node build
113117
if: steps.wasm-build.outputs.cache-hit != 'true'

.image-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2025-11-25

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
engine-strict=true

CMakeLists.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ target_compile_options(
7171
scran_wasm PUBLIC
7272
-O3
7373
-pthread
74+
-sMEMORY64
7475
)
7576

7677
target_link_libraries(
@@ -121,7 +122,8 @@ target_link_options(scran_wasm PRIVATE
121122
-O3
122123
--bind
123124
-sALLOW_MEMORY_GROWTH=1
124-
-sMAXIMUM_MEMORY=4GB
125+
-sMEMORY64
126+
-sMAXIMUM_MEMORY=16GB # current maximum, otherwise Emscripten complains.
125127
-sSTACK_SIZE=2MB
126128
-sUSE_ZLIB=1
127129
-sMODULARIZE=1
@@ -137,14 +139,15 @@ set_target_properties(scran_wasm PROPERTIES OUTPUT_NAME scran)
137139

138140
set(COMPILE_NODE OFF CACHE BOOL "Compile for Node.js")
139141
if (COMPILE_NODE)
142+
# Exporting HEAP8 for compatibility with old wasmarrays.js.
140143
target_link_options(scran_wasm PRIVATE
141144
-sENVIRONMENT=node
142145
-sNODERAWFS=1
143-
-sEXPORTED_RUNTIME_METHODS=wasmMemory,PThread
146+
-sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,PThread
144147
)
145148
else ()
146149
target_link_options(scran_wasm PRIVATE
147150
-sENVIRONMENT=web,worker
148-
-sEXPORTED_RUNTIME_METHODS=wasmMemory,PThread,FS
151+
-sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,PThread,FS
149152
)
150153
endif()

build.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,16 @@ if [ ! -e $builddir ]
4545
then
4646
mkdir $builddir
4747
echo "{}" > $builddir/package.json # avoid assuming ES6 syntax for igraph config scripts.
48+
49+
# Setting the C flags below, even though we don't have any C;
50+
# this ensures that emcmake knows to operate in 64-bit mode for find_package().
4851
emcmake cmake \
4952
-S . \
5053
-B $builddir \
5154
-DCOMPILE_NODE=${node_flag} \
5255
-DCMAKE_BUILD_TYPE=Release \
5356
-DCMAKE_PREFIX_PATH=extern/installed \
57+
-DCMAKE_C_FLAGS="-sMEMORY64" \
5458
-DTATAMI_HDF5_FIND_HDF5=OFF
5559
fi
5660

extern/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ FetchContent_Declare(
9595
FetchContent_Declare(
9696
scran_qc
9797
GIT_REPOSITORY https://github.com/libscran/scran_qc
98-
GIT_TAG master
98+
GIT_TAG v0.1.1
9999
)
100100

101101
FetchContent_Declare(

extern/hdf5/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ BUILD_DIR=build-${HDF5_VERSION}
3030
if [ ! -e ${BUILD_DIR} ]
3131
then
3232
mkdir -p ../installed
33-
coreflags="-pthread" # propagating compile flags from the root scran.js CMakeLists.txt.
33+
coreflags="-pthread -sMEMORY64" # propagating compile flags from the root scran.js CMakeLists.txt.
3434
echo "{}" > package.json # avoid assuming ES6 module syntax from the root scran.js package.json.
3535
emcmake cmake \
3636
-S ${SOURCE_DIR} \

extern/igraph/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ BUILD_DIR=build-${IGRAPH_VERSION}
2323
if [ ! -e ${BUILD_DIR} ]
2424
then
2525
mkdir -p ../installed
26-
coreflags="-pthread" # propagating compile flags from the root scran.js CMakeLists.txt.
26+
coreflags="-pthread -sMEMORY64" # propagating compile flags from the root scran.js CMakeLists.txt.
2727
echo "{}" > package.json # avoid assuming ES6 module syntax from the root scran.js package.json.
2828
emcmake cmake \
2929
-S ${SOURCE_DIR} \

js/wasm.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ const cache = {};
88
* @param {object} [options={}] - Optional parameters.
99
* @param {number} [options.numberOfThreads=4] - Number of threads to use for calculations.
1010
* This will spin up the requested number of Web Workers during module initialization.
11-
* @param {boolean} [options.localFile=false] - Whether or not to look for the Wasm and worker scripts locally.
12-
* This should only be `true` when using old versions of Node.js where file URLs are not supported,
13-
* and is ignored completely outside of Node.js contexts.
11+
* @param {boolean} [options.localFile=false] - Deprecated and ignored.
1412
*
1513
* @return {boolean}
1614
* The Wasm bindings are initialized and `true` is returned.
@@ -25,10 +23,6 @@ export async function initialize({ numberOfThreads = 4, localFile = false } = {}
2523
scran_custom_nthreads: numberOfThreads
2624
};
2725

28-
if (localFile) { /** NODE ONLY **/
29-
options.locateFile = (x) => import.meta.url.substring(7) + "/../wasm/" + x; /** NODE ONLY **/
30-
} /** NODE ONLY **/
31-
3226
cache.module = await loadScran(options);
3327
cache.space = register(cache.module);
3428

0 commit comments

Comments
 (0)