Skip to content

Commit 27e4ef7

Browse files
authored
Fix makefile, add workflow to build ASM and WASM versions, update dependencies (#14)
1 parent 94798d3 commit 27e4ef7

22 files changed

+6293
-112
lines changed
+59-13
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,71 @@
1-
name: Docker Image CI
1+
# Workflow to build and publish the libzim ASM and WASM arttefacts together with the JavaScript wrapper.
2+
# If this workflow is triggered by the creation of a draft release, then the artefacts are uploaded to the release assets.
3+
# If it is triggered by a push or pull request to master, or manually, then the artefacts are archived under the corresponding Action.
4+
5+
name: Build and publish release artefacts (Docker)
26

37
on:
4-
# push:
5-
# branches: [ "master" ]
6-
# pull_request:
7-
# branches: [ "master" ]
8+
push:
9+
branches: [ master ]
10+
tags:
11+
- 'v*' # Tag push events matching v*, i.e. v1.0, v20.15.10
12+
pull_request:
13+
branches: [ master ]
814
workflow_dispatch:
15+
inputs:
16+
version:
17+
description: |
18+
If you wish to create a draft release, set the tag version, like v9.9.9 (must not be an exisitng tag).
19+
If left blank or incorrect format, archives will be archived instead of being uploaded to Releases.
20+
required: false
21+
default: ''
922

23+
# Define top-level environment vars we can refer to below
24+
env:
25+
VERSION: ${{ github.ref_name }}
26+
DISPATCH_VERSION: ${{ github.event.inputs.version }}
27+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28+
1029
jobs:
11-
1230
build:
13-
31+
name: Build and publish W/ASM artefacts
1432
runs-on: ubuntu-latest
15-
1633
steps:
1734
- uses: actions/checkout@v3
35+
# Customizes the Emscripten docker container via the Dockerfile in this repo
1836
- name: Build the Docker image
1937
run: docker build -t "docker-emscripten-libzim:v3" ./docker
20-
- name: Compile the libzim WASM
21-
run: docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) -it docker-emscripten-libzim:v3 make
22-
- name: Publish the WASM to draft release
38+
# Creates the ASM and WASM artefacts, and the JS wrappers, using the Makefile in this repo
39+
- name: Compile the libzim WASM artefacts
40+
run: docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) docker-emscripten-libzim:v3 make
41+
- name: List directories with updated archives
42+
run: |
43+
echo -e "\nList ./ :"
44+
ls -l
45+
echo -e "\nList ./tests/prototype/ :"
46+
ls -l tests/prototype/
47+
echo -e "\nList ./tests/test_large_file_access/ :"
48+
ls -l tests/test_large_file_access/
49+
# If we are not creating a release, archive the artefacts under this Action run
50+
- name: Archive build artefacts
51+
if: |
52+
github.event_name == 'pull_request' || github.event_name == 'push' && ! startsWith(github.ref_name, 'v')
53+
|| ! startsWith(github.event.inputs.version, 'v')
54+
uses: actions/upload-artifact@v3
55+
with:
56+
name: libzim-wasm-artefacts
57+
path: |
58+
libzim-wasm.*
59+
libzim-asm.*
60+
tests/test_large_file_access/large_file_access.*
61+
# Otherwise, zip the artefacts into respective packages (asm and wasm), create and upload releases
62+
- name: Zip the artefacts and create draft release
63+
id: zip-release
64+
if: github.event_name == 'push' && startsWith(github.ref_name, 'v') || startsWith(github.event.inputs.version, 'v')
2365
run: |
24-
echo 'If the run was successful, we will build a publish action here, to publish:'
25-
ls -l a.out.*
66+
if [[ ! $VERSION =~ ^v?[0-9.]+ ]]; then
67+
VERSION=$DISPATCH_VERSION
68+
fi
69+
# Create a draft release and upload zipped artefacts as release assets
70+
chmod +x ./scripts/create_draft_release.sh
71+
./scripts/create_draft_release.sh

.github/workflows/upload_release_assets_to_kiwix.yml

+1-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ on:
1818
# Define top-level environment vars we can refer to below
1919
env:
2020
REPOSITORY: ${{ github.repository }}
21-
RELEASE: ${{ github.event.release }}
2221
VERSION: ${{ github.event.release.tag_name }}
2322
DISPATCH_VERSION: ${{ github.event.inputs.version }}
2423
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -34,14 +33,13 @@ jobs:
3433
- name: Find the release, get assets, and upload
3534
run: |
3635
$repository = $Env:REPOSITORY
37-
$release = $Env:RELEASE
3836
$version = $Env:VERSION
3937
if (! $version) { $version = $Env:DISPATCH_VERSION }
4038
if (! $version) {
4139
Write-Host "`n** You must set a tag version so that we can find and upload the assets! **`n" -ForegroundColor Red
4240
exit 1
4341
}
44-
echo "`nUsing tag: $TAG_NAME for version upload`n"
42+
echo "`nUsing tag: $version for version upload`n"
4543
$SSH_KEY = $Env:SSH_KEY
4644
if (! $SSH_KEY) {
4745
Write-Warning "The SSH secret is empty!"

.gitignore

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
.vscode/
12
/nbproject/private/
2-
/build/
3+
/build*
34
/xz-*/
45
/zlib-*/
56
/zstd-*/
@@ -11,6 +12,6 @@
1112
/zstd-*.tar.gz
1213
/icu4c-*.tgz
1314
/xapian-core-*.tar.xz
14-
/libzim-*.tar.gz
15+
/libzim-*
1516
ssh_key
1617
github_token

Makefile

+46-24
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,81 @@
1-
all: demo_file_api.js big_file_demo.js
1+
all: libzim-wasm.dev.js libzim-asm.dev.js libzim-wasm.js libzim-asm.js large_file_access.js
2+
23
build/lib/liblzma.so :
3-
wget -N https://tukaani.org/xz/xz-5.2.4.tar.gz
4+
# Origin: https://tukaani.org/xz/xz-5.2.4.tar.gz
5+
[ ! -f xz-*.tar.gz ] && wget -N https://dev.kiwix.org/kiwix-build/xz-5.2.4.tar.gz || true
46
tar xf xz-5.2.4.tar.gz
57
cd xz-5.2.4 ; ./autogen.sh
68
cd xz-5.2.4 ; emconfigure ./configure --prefix=`pwd`/../build
79
cd xz-5.2.4 ; emmake make
810
cd xz-5.2.4 ; emmake make install
911

10-
build/lib/libz.a :
12+
build/lib/libz.a :
13+
# Version not yet available in dev.kiwix.org
1114
wget -N https://zlib.net/zlib-1.2.13.tar.gz
1215
tar xf zlib-1.2.13.tar.gz
1316
cd zlib-1.2.13 ; emconfigure ./configure --prefix=`pwd`/../build
1417
cd zlib-1.2.13 ; emmake make
1518
cd zlib-1.2.13 ; emmake make install
1619

17-
build/lib/libzstd.a :
18-
wget -N https://github.com/facebook/zstd/releases/download/v1.4.4/zstd-1.4.4.tar.gz
19-
tar xf zstd-1.4.4.tar.gz
20-
cd zstd-1.4.4/build/meson ; meson setup --cross-file=../../../emscripten-crosscompile.ini -Dbin_programs=false -Dbin_contrib=false -Dzlib=disabled -Dlzma=disabled -Dlz4=disabled --prefix=`pwd`/../../../build --libdir=lib builddir
21-
cd zstd-1.4.4/build/meson/builddir ; ninja
22-
cd zstd-1.4.4/build/meson/builddir ; ninja install
20+
build/lib/libzstd.a :
21+
# Origin: https://github.com/facebook/zstd/releases/download/v1.4.4/zstd-1.4.4.tar.gz
22+
[ ! -f zstd-*.tar.gz ] && wget -N https://dev.kiwix.org/kiwix-build/zstd-1.5.2.tar.gz || true
23+
tar xf zstd-1.5.2.tar.gz
24+
cd zstd-1.5.2/build/meson ; meson setup --cross-file=../../../emscripten-crosscompile.ini -Dbin_programs=false -Dbin_contrib=false -Dzlib=disabled -Dlzma=disabled -Dlz4=disabled --prefix=`pwd`/../../../build --libdir=lib builddir
25+
cd zstd-1.5.2/build/meson/builddir ; ninja
26+
cd zstd-1.5.2/build/meson/builddir ; ninja install
2327

2428
build/lib/libicudata.so :
25-
wget -N https://github.com/unicode-org/icu/releases/download/release-69-1/icu4c-69_1-src.tgz
26-
tar xf icu4c-69_1-src.tgz
29+
# Version not yet available in dev.kiwix.org
30+
wget -N https://github.com/unicode-org/icu/releases/download/release-71-1/icu4c-71_1-src.tgz
31+
tar xf icu4c-71_1-src.tgz
2732
# It's no use trying to compile examples
2833
sed -i -e 's/^SUBDIRS =\(.*\)$$(DATASUBDIR) $$(EXTRA) $$(SAMPLE) $$(TEST)\(.*\)/SUBDIRS =\1\2/' icu/source/Makefile.in
2934
cd icu/source ; emconfigure ./configure --prefix=`pwd`/../../build
3035
cd icu/source ; emmake make
3136
cd icu/source ; emmake make install
3237

3338
build/lib/libxapian.a : build/lib/libz.a
34-
wget -N https://oligarchy.co.uk/xapian/1.4.18/xapian-core-1.4.18.tar.xz
39+
# Origin: https://oligarchy.co.uk/xapian/1.4.18/xapian-core-1.4.18.tar.xz
40+
[ ! -f xapian-*.tar.gz ] && wget -N https://dev.kiwix.org/kiwix-build/xapian-core-1.4.18.tar.xz || true
3541
tar xf xapian-core-1.4.18.tar.xz
3642
# Some options coming from https://github.com/xapian/xapian/tree/master/xapian-core/emscripten
37-
#cd xapian-core-1.4.18; emconfigure ./configure --prefix=`pwd`/../build "CFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib" "CXXFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib" CPPFLAGS='-DFLINTLOCK_USE_FLOCK' CXXFLAGS='-Oz -s USE_ZLIB=1 -fno-rtti' --disable-backend-honey --disable-backend-inmemory --disable-shared --disable-backend-remote
43+
# cd xapian-core-1.4.18; emconfigure ./configure --prefix=`pwd`/../build "CFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib" "CXXFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib" CPPFLAGS='-DFLINTLOCK_USE_FLOCK' CXXFLAGS='-Oz -s USE_ZLIB=1 -fno-rtti' --disable-backend-honey --disable-backend-inmemory --disable-shared --disable-backend-remote
3844
cd xapian-core-1.4.18; emconfigure ./configure --prefix=`pwd`/../build "CFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib" "CXXFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib" --disable-shared --disable-backend-remote
3945
cd xapian-core-1.4.18; emmake make "CFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib -std=c++11" "CXXFLAGS=-I`pwd`/../build/include -L`pwd`/../build/lib -std=c++11"
4046
cd xapian-core-1.4.18; emmake make install
4147

4248
build/lib/libzim.a : build/lib/liblzma.so build/lib/libz.a build/lib/libzstd.a build/lib/libicudata.so build/lib/libxapian.a
43-
wget -N --content-disposition https://github.com/openzim/libzim/archive/7.2.2.tar.gz
44-
tar xf libzim-7.2.2.tar.gz
49+
# Origin: wget -N --content-disposition https://github.com/openzim/libzim/archive/7.2.2.tar.gz
50+
[ ! -f libzim-*.tar.xz ] && wget -N https://download.openzim.org/release/libzim/libzim-8.1.0.tar.xz || true
51+
tar xf libzim-8.1.0.tar.xz
4552
# It's no use trying to compile examples
46-
sed -i -e "s/^subdir('examples')//" libzim-7.2.2/meson.build
47-
cd libzim-7.2.2; PKG_CONFIG_PATH=/src/build/lib/pkgconfig meson --prefix=`pwd`/../build --cross-file=../emscripten-crosscompile.ini . build -DUSE_MMAP=false
48-
cd libzim-7.2.2; ninja -C build
49-
cd libzim-7.2.2; ninja -C build install
53+
sed -i -e "s/^subdir('examples')//" libzim-8.1.0/meson.build
54+
cd libzim-8.1.0; PKG_CONFIG_PATH=/src/build/lib/pkgconfig meson --prefix=`pwd`/../build --cross-file=../emscripten-crosscompile.ini . build -DUSE_MMAP=false
55+
cd libzim-8.1.0; ninja -C build
56+
cd libzim-8.1.0; ninja -C build install
57+
58+
# Development WASM version for testing, completely unoptimized
59+
libzim-wasm.dev.js: build/lib/libzim.a libzim_bindings.cpp prejs_file_api.js postjs_file_api.js
60+
em++ -o libzim-wasm.dev.js --bind libzim_bindings.cpp -I/src/build/include -L/src/build/lib -lzim -llzma -lzstd -lxapian -lz -licui18n -licuuc -licudata -lpthread -lm -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -Werror -std=c++11 -O0 -g --pre-js prejs_file_api.js --post-js postjs_file_api.js -s WASM=1 -s DISABLE_EXCEPTION_CATCHING=0 -s "EXPORTED_RUNTIME_METHODS=['ALLOC_NORMAL','printErr','ALLOC_STACK','print']" -s DEMANGLE_SUPPORT=1 -s INITIAL_MEMORY=83886080 -s ALLOW_MEMORY_GROWTH=1 -lworkerfs.js
61+
cp libzim-wasm.dev.* tests/prototype/
62+
63+
# Development ASM version for testing, completely unoptimized
64+
libzim-asm.dev.js: build/lib/libzim.a libzim_bindings.cpp prejs_file_api.js postjs_file_api.js
65+
em++ -o libzim-asm.dev.js --bind libzim_bindings.cpp -I/src/build/include -L/src/build/lib -lzim -llzma -lzstd -lxapian -lz -licui18n -licuuc -licudata -lpthread -lm -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -Werror -std=c++11 -O0 -g --pre-js prejs_file_api.js --post-js postjs_file_api.js -s WASM=0 --memory-init-file 0 -s DISABLE_EXCEPTION_CATCHING=0 -s "EXPORTED_RUNTIME_METHODS=['ALLOC_NORMAL','printErr','ALLOC_STACK','print']" -s DEMANGLE_SUPPORT=1 -s INITIAL_MEMORY=83886080 -s ALLOW_MEMORY_GROWTH=1 -lworkerfs.js
66+
67+
# Production WASM version, optimized and packed
68+
libzim-wasm.js: build/lib/libzim.a libzim_bindings.cpp prejs_file_api.js postjs_file_api.js
69+
em++ -o libzim-wasm.js --bind libzim_bindings.cpp -I/src/build/include -L/src/build/lib -lzim -llzma -lzstd -lxapian -lz -licui18n -licuuc -licudata -O3 --pre-js prejs_file_api.js --post-js postjs_file_api.js -s WASM=1 -s "EXPORTED_RUNTIME_METHODS=['ALLOC_NORMAL','printErr','ALLOC_STACK','print']" -s INITIAL_MEMORY=83886080 -s ALLOW_MEMORY_GROWTH=1 -lworkerfs.js
5070

51-
demo_file_api.js: build/lib/libzim.a demo_file_api.cpp prejs_file_api.js postjs_file_api.js
52-
em++ --bind demo_file_api.cpp -I/src/build/include -L/src/build/lib -lzim -llzma -lzstd -lxapian -lz -licui18n -licuuc -licudata -lpthread -lm -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -Werror -std=c++11 -O0 -g --pre-js prejs_file_api.js --post-js postjs_file_api.js -s DISABLE_EXCEPTION_CATCHING=0 -s "EXPORTED_RUNTIME_METHODS=['ALLOC_NORMAL','printErr','ALLOC_STACK','print']" -s DEMANGLE_SUPPORT=1 -s TOTAL_MEMORY=83886080 -s ALLOW_MEMORY_GROWTH=1 -lworkerfs.js
71+
# Production ASM version, optimized and packed
72+
libzim-asm.js: build/lib/libzim.a libzim_bindings.cpp prejs_file_api.js postjs_file_api.js
73+
em++ -o libzim-asm.js --bind libzim_bindings.cpp -I/src/build/include -L/src/build/lib -lzim -llzma -lzstd -lxapian -lz -licui18n -licuuc -licudata -O3 --pre-js prejs_file_api.js --post-js postjs_file_api.js -s WASM=0 --memory-init-file 0 -s MIN_EDGE_VERSION=40 -s "EXPORTED_RUNTIME_METHODS=['ALLOC_NORMAL','printErr','ALLOC_STACK','print']" -s INITIAL_MEMORY=83886080 -s ALLOW_MEMORY_GROWTH=1 -lworkerfs.js
5374

54-
big_file_demo.js:
55-
em++ --bind -std=c++11 -O0 --pre-js prejs_file_api_testbigfile.js --post-js postjs_file_api_testbigfile.js big_file_test.cpp -lworkerfs.js -o bigfile.js
75+
# Test case: for testing large files
76+
large_file_access.js: test_file_bindings.cpp prejs_test_file_access.js postjs_test_file_access.js
77+
em++ -o large_file_access.js --bind test_file_bindings.cpp -std=c++11 -O0 --pre-js prejs_test_file_access.js --post-js postjs_test_file_access.js -lworkerfs.js
78+
cp large_file_access.* tests/test_large_file_access/
5679

5780
clean :
5881
rm -rf xz-*
@@ -62,6 +85,5 @@ clean :
6285
rm -rf icu*
6386
rm -rf libzim-*
6487
rm -rf build
65-
rm a.out.*
6688

6789
.PHONY : all clean

README.md

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
1-
# Prototype of libzim in Webassembly
1+
# Prototype of libzim in WebAssembly (WASM)
22

3-
Demo at https://openzim.github.io/javascript-libzim/
3+
This Repository provides the source code and utilities for compiling the [ZIM File](https://wiki.openzim.org/wiki/ZIM_file_format) reader [lbizim](https://wiki.openzim.org/wiki/Libzim) from C++ to [WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly) (and [ASM.js](https://developer.mozilla.org/en-US/docs/Games/Tools/asm.js)).
44

5-
It uses WORKERFS as FS with emscripten and run in a web worker, file object is mount before run, and name is passed as argument.
5+
A prototype in HTML/JS, for testing the WASM version, is provided at https://openzim.github.io/javascript-libzim/tests/prototyep/. This prototype uses WORKERFS as the Emscripten File System and runs in a Web Worker. The file object is mounted before run, and the name is passed as argument.
6+
7+
There is also an HTML/JS utility for testing the ability of Emscripten File Systems to read large files (muliti-gigabyte) at https://openzim.github.io/javascript-libzim/tests/test_large_file_access/.
68

79
## Steps to recompile manually
10+
811
- Install emscripten : https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
9-
- Install dependencies necessary for compilation. On ubuntu 18.04, you need to activate universe repository and :
12+
- Install dependencies necessary for compilation. On ubuntu 18.04, you need to activate universe repository and:
13+
1014
```
1115
sudo apt install ninja-build meson pkg-config python3 autopoint libtool autoconf
1216
sudo apt install zlib1g-dev libicu-dev libxapian-dev liblzma-dev
1317
```
18+
1419
- activate emscripten environment variables with something like `source ./emsdk_env.sh`
1520
- run `make`
1621

1722
## Steps to recompile with Docker
18-
While being at the root of this repository :
19-
- Build the Docker image with the provided Dockerfile (based on https://hub.docker.com/r/emscripten/emsdk , which is based on Debian) :
23+
24+
While being at the root of this repository:
25+
- Build the Docker image with the provided Dockerfile (based on https://hub.docker.com/r/emscripten/emsdk, which is based on Debian):
26+
2027
```
2128
docker build -t "docker-emscripten-libzim:v3" ./docker
2229
```
23-
- Run the build with :
30+
31+
- Run the build with:
32+
2433
```
2534
docker run --rm -v $(pwd):/src -v /tmp/emscripten_cache/:/home/emscripten/.emscripten_cache -u $(id -u):$(id -g) -it docker-emscripten-libzim:v3 make
2635
```

emscripten-crosscompile.ini

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ cpp = 'em++'
44
c_ld = 'wasm-ld'
55
cpp_ld = 'wasm-ld'
66
pkgconfig = 'pkg-config'
7+
ar = 'emar'
78

89
[host_machine]
910
system = 'emscripten'

bigfile.js renamed to large_file_access.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,7 @@ function createExportWrapper(name, fixedasm) {
15031503
}
15041504

15051505
var wasmBinaryFile;
1506-
wasmBinaryFile = 'bigfile.wasm';
1506+
wasmBinaryFile = 'large_file_access.wasm';
15071507
if (!isDataURI(wasmBinaryFile)) {
15081508
wasmBinaryFile = locateFile(wasmBinaryFile);
15091509
}
File renamed without changes.

demo_file_api.cpp renamed to libzim_bindings.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ std::shared_ptr<zim::Archive> g_archive;
1414

1515
int main(int argc, char* argv[])
1616
{
17-
std::cout << "wasm initialized" << std::endl;
17+
std::cout << "assembler initialized" << std::endl;
1818
return 0;
1919
}
2020

@@ -95,11 +95,11 @@ std::unique_ptr<EntryWrapper> getEntryByPath(std::string url) {
9595
}
9696

9797
// Search for a text, and returns the path of the first result
98-
std::vector<EntryWrapper> search(std::string text) {
98+
std::vector<EntryWrapper> search(std::string text, int numResults) {
9999
auto searcher = zim::Searcher(*g_archive);
100100
auto query = zim::Query(text);
101101
auto search = searcher.search(query);
102-
auto searchResultSet = search.getResults(0,50);
102+
auto searchResultSet = search.getResults(0, numResults);
103103
std::vector<EntryWrapper> ret;
104104
for(auto entry:searchResultSet) {
105105
ret.push_back(EntryWrapper(entry));
File renamed without changes.

0 commit comments

Comments
 (0)