Skip to content

Commit dfc8055

Browse files
Merge pull request jupyter-xeus#127 from IsabelParedes/wasm
Add Emscripten build
2 parents e77129a + 9ff016f commit dfc8055

17 files changed

+594
-118
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: build and deploy
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches:
8+
- main
9+
10+
permissions:
11+
contents: read
12+
pages: write
13+
id-token: write
14+
15+
jobs:
16+
build:
17+
runs-on: ubuntu-latest
18+
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
include:
23+
- name: Github-page
24+
25+
steps:
26+
- uses: actions/checkout@v5
27+
with:
28+
fetch-depth: 0
29+
30+
- name: Install mamba
31+
uses: mamba-org/setup-micromamba@v2
32+
with:
33+
environment-file: environment-wasm-build.yml
34+
init-shell: bash
35+
environment-name: xeus-octave-wasm-build
36+
37+
- name: Set ncpus
38+
run: echo "ncpus=$(nproc --all)" >> $GITHUB_ENV
39+
40+
- name: Build xeus-octave
41+
shell: bash -l {0}
42+
run: |
43+
micromamba create -f environment-wasm-host.yml --platform=emscripten-wasm32
44+
45+
set -eux
46+
47+
export PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-octave-wasm-host
48+
echo "PREFIX=$PREFIX" >> $GITHUB_ENV
49+
50+
emcmake cmake . \
51+
-DCMAKE_BUILD_TYPE=Release \
52+
-DCMAKE_PREFIX_PATH="$PREFIX" \
53+
-DCMAKE_SYSTEM_PREFIX_PATH="$PREFIX" \
54+
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
55+
-DCMAKE_FIND_ROOT_PATH="$PREFIX" \
56+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
57+
-DCMAKE_VERBOSE_MAKEFILE=ON
58+
59+
emmake make -j${{ env.ncpus }} install
60+
61+
- name: Jupyter Lite integration
62+
shell: bash -l {0}
63+
run: |
64+
jupyter lite build \
65+
--XeusAddon.prefix=${{ env.PREFIX }} \
66+
--XeusAddon.mounts=$PREFIX/share/octave:/share/octave \
67+
--XeusAddon.mounts=$PREFIX/share/xeus-octave:/share/xeus-octave \
68+
--contents notebooks/xeus-octave-wasm.ipynb \
69+
--output-dir dist
70+
71+
- name: Upload artifact
72+
uses: actions/upload-pages-artifact@v4
73+
with:
74+
path: ./dist
75+
76+
deploy:
77+
needs: build
78+
if: github.ref == 'refs/heads/main'
79+
permissions:
80+
pages: write
81+
id-token: write
82+
83+
environment:
84+
name: github-pages
85+
url: ${{ steps.deployment.outputs.page_url }}
86+
87+
runs-on: ubuntu-latest
88+
steps:
89+
- name: Deploy to GitHub Pages
90+
id: deployment
91+
uses: actions/deploy-pages@v4

CMakeLists.txt

Lines changed: 106 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -58,25 +58,40 @@ option(XEUS_OCTAVE_BUILD_SHARED "Split xoctave build into executable and library
5858
option(XEUS_OCTAVE_BUILD_EXECUTABLE "Build the xoctave executable" ON)
5959

6060
option(
61-
XEUS_OCTAVE_USE_SHARED_XEUS
62-
"Link xeus-octave with the xeus shared library (instead of the static library)"
61+
XEUS_OCTAVE_USE_SHARED_XEUS_ZMQ
62+
"Link xeus-octave with the xeus-zmq shared library (instead of the static library)"
6363
ON
6464
)
6565
option(
6666
XEUS_OCTAVE_USE_SHARED_XEUS_OCTAVE
67-
"Link xoctave with the xeus shared library (instead of the static library)"
67+
"Link xoctave with the xeus-octave shared library (instead of the static library)"
6868
ON
6969
)
7070

71+
if(EMSCRIPTEN)
72+
set(XEUS_OCTAVE_BUILD_STATIC ON)
73+
set(XEUS_OCTAVE_BUILD_SHARED OFF)
74+
set(XEUS_OCTAVE_BUILD_EXECUTABLE ON)
75+
set(XEUS_OCTAVE_USE_SHARED_XEUS_ZMQ OFF)
76+
set(XEUS_OCTAVE_USE_SHARED_XEUS_OCTAVE OFF)
77+
set(XEUS_OCTAVE_DISABLE_ARCH_NATIVE ON)
78+
set(XEUS_OCTAVE_DISABLE_TUNE_GENERIC ON)
79+
endif()
80+
7181
# Dependencies
7282
# ============
7383

74-
set(xeus_zmq_REQUIRED_VERSION 3.0.0)
75-
find_package(xeus-zmq ${xeus_zmq_REQUIRED_VERSION} REQUIRED)
76-
7784
find_package(PNG REQUIRED)
78-
find_package(glad REQUIRED)
79-
find_package(glfw3)
85+
86+
if(NOT EMSCRIPTEN)
87+
set(xeus_zmq_REQUIRED_VERSION 3.0.0)
88+
find_package(xeus-zmq ${xeus_zmq_REQUIRED_VERSION} REQUIRED)
89+
find_package(glad REQUIRED)
90+
find_package(glfw3)
91+
else()
92+
find_package(xeus-lite REQUIRED)
93+
endif()
94+
8095
find_package(PkgConfig REQUIRED)
8196
pkg_check_modules(octinterp REQUIRED IMPORTED_TARGET GLOBAL octinterp>=10.0)
8297

@@ -105,29 +120,40 @@ endif()
105120
set(
106121
XEUS_OCTAVE_HEADERS
107122
include/xeus-octave/config.hpp
108-
include/xeus-octave/xinterpreter.hpp
123+
include/xeus-octave/display.hpp
109124
include/xeus-octave/input.hpp
110125
include/xeus-octave/output.hpp
111-
include/xeus-octave/utils.hpp
112-
include/xeus-octave/tk_notebook.hpp
113-
include/xeus-octave/opengl.hpp
114-
include/xeus-octave/tk_plotly.hpp
115126
include/xeus-octave/plotstream.hpp
116127
include/xeus-octave/tex2html.hpp
117-
include/xeus-octave/display.hpp
128+
include/xeus-octave/tk_plotly.hpp
129+
include/xeus-octave/utils.hpp
130+
include/xeus-octave/xinterpreter.hpp
118131
)
119132

133+
if(EMSCRIPTEN)
134+
list(APPEND XEUS_OCTAVE_HEADERS include/xeus-octave/xinterpreter_wasm.hpp)
135+
else()
136+
list(
137+
APPEND
138+
XEUS_OCTAVE_HEADERS
139+
include/xeus-octave/opengl.hpp
140+
include/xeus-octave/tk_notebook.hpp
141+
)
142+
endif()
143+
120144
set(
121145
XEUS_OCTAVE_SRC
122-
src/tk_plotly.cpp
123-
src/tk_notebook.cpp
124-
src/display.cpp
125-
src/xinterpreter.cpp
126-
src/input.cpp
127-
src/output.cpp
146+
src/display.cpp src/input.cpp src/output.cpp src/tk_plotly.cpp src/xinterpreter.cpp
128147
)
129148

149+
if(EMSCRIPTEN)
150+
list(APPEND XEUS_OCTAVE_SRC src/xinterpreter_wasm.cpp)
151+
else()
152+
list(APPEND XEUS_OCTAVE_SRC src/tk_notebook.cpp)
153+
endif()
154+
130155
set(XEUS_OCTAVE_MAIN_SRC src/main.cpp)
156+
set(XEUS_OCTAVE_MAIN_WASM_SRC src/main_wasm.cpp)
131157

132158
# Targets and link - Macros
133159
# =========================
@@ -182,8 +208,10 @@ macro(xeus_octave_set_kernel_options target_name)
182208
target_link_libraries(${target_name} PRIVATE xeus-octave-static)
183209
endif()
184210

185-
find_package(Threads)
186-
target_link_libraries(${target_name} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
211+
if(NOT EMSCRIPTEN)
212+
find_package(Threads)
213+
target_link_libraries(${target_name} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
214+
endif()
187215

188216
endmacro()
189217

@@ -226,24 +254,35 @@ macro(xeus_octave_create_target target_name linkage output_name)
226254
PUBLIC $<BUILD_INTERFACE:${XEUS_OCTAVE_INCLUDE_DIR}> $<INSTALL_INTERFACE:include>
227255
)
228256

229-
target_link_libraries(
230-
${target_name}
231-
PUBLIC PkgConfig::octinterp
232-
PRIVATE glad::glad glfw PNG::PNG
233-
)
234-
if(XEUS_OCTAVE_USE_SHARED_XEUS)
235-
target_link_libraries(${target_name} PUBLIC xeus-zmq)
257+
target_link_libraries(${target_name} PRIVATE PNG::PNG)
258+
259+
if(EMSCRIPTEN)
260+
target_compile_options(${target_name} PRIVATE ${octinterp_CFLAGS})
261+
target_link_libraries(
262+
${target_name}
263+
# Cannot mix shared and static libs with emscripten
264+
PUBLIC ${octinterp_STATIC_LIBRARIES}
265+
)
236266
else()
237-
target_link_libraries(${target_name} PUBLIC xeus-zmq-static)
267+
target_link_libraries(
268+
${target_name}
269+
PUBLIC PkgConfig::octinterp
270+
PRIVATE glad::glad glfw
271+
)
272+
273+
if(XEUS_OCTAVE_USE_SHARED_XEUS_ZMQ)
274+
target_link_libraries(${target_name} PUBLIC xeus-zmq)
275+
else()
276+
target_link_libraries(${target_name} PUBLIC xeus-zmq-static)
277+
endif()
278+
279+
find_package(Threads)
280+
target_link_libraries(${target_name} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
238281
endif()
239282

240-
if(WIN32 OR CYGWIN)
241-
#
242-
elseif(APPLE)
283+
if(APPLE)
243284
target_link_libraries(${target_name} PRIVATE "-undefined dynamic_lookup")
244285
endif()
245-
find_package(Threads)
246-
target_link_libraries(${target_name} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
247286

248287
endmacro()
249288

@@ -272,9 +311,31 @@ endif()
272311
# xeus-octave
273312
# =======
274313
if(XEUS_OCTAVE_BUILD_EXECUTABLE)
275-
add_executable(xoctave ${XEUS_OCTAVE_MAIN_SRC})
276-
xeus_octave_set_common_options(xoctave)
277-
xeus_octave_set_kernel_options(xoctave)
314+
if(NOT EMSCRIPTEN)
315+
add_executable(xoctave ${XEUS_OCTAVE_MAIN_SRC})
316+
xeus_octave_set_common_options(xoctave)
317+
xeus_octave_set_kernel_options(xoctave)
318+
else()
319+
include(WasmBuildOptions)
320+
add_executable(xoctave ${XEUS_OCTAVE_MAIN_WASM_SRC})
321+
target_link_libraries(xoctave PRIVATE xeus-lite)
322+
xeus_octave_set_kernel_options(xoctave)
323+
324+
xeus_wasm_compile_options(xoctave)
325+
xeus_wasm_link_options(xoctave "web,worker")
326+
target_compile_options(xoctave PRIVATE ${octinterp_CFLAGS})
327+
target_link_options(
328+
xoctave
329+
PUBLIC
330+
"SHELL: --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/wasm/env_vars.js"
331+
PUBLIC
332+
"SHELL: --post-js ${CMAKE_CURRENT_SOURCE_DIR}/wasm/post.js"
333+
PRIVATE
334+
${octinterp_LDFLAGS}
335+
PRIVATE
336+
"SHELL: -L${CMAKE_INSTALL_PREFIX}/lib -lfreetype -lFortranDecimal -Wl,--allow-multiple-definition"
337+
)
338+
endif()
278339
endif()
279340

280341
# Installation
@@ -384,3 +445,10 @@ if(XEUS_OCTAVE_BUILD_SHARED)
384445
DESTINATION ${XEUS_OCTAVE_CMAKECONFIG_INSTALL_DIR}
385446
)
386447
endif()
448+
449+
if(EMSCRIPTEN)
450+
install(
451+
FILES "$<TARGET_FILE_DIR:xoctave>/xoctave.js" "$<TARGET_FILE_DIR:xoctave>/xoctave.wasm"
452+
DESTINATION ${CMAKE_INSTALL_BINDIR}
453+
)
454+
endif()

environment-wasm-build.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: xeus-octave-wasm-build
2+
channels:
3+
- https://repo.prefix.dev/emscripten-forge-dev
4+
- conda-forge
5+
dependencies:
6+
# Xeus-Octave
7+
- cmake
8+
- make
9+
- pkg-config
10+
- emscripten_emscripten-wasm32==3.1.73
11+
# JupyterLite
12+
- jupyterlite-core
13+
- jupyter_server
14+
- jupyterlite-xeus

environment-wasm-host.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: xeus-octave-wasm-host
2+
channels:
3+
- https://repo.prefix.dev/emscripten-forge-dev
4+
- conda-forge
5+
dependencies:
6+
- xeus
7+
- xeus-lite
8+
- nlohmann_json
9+
- octave
10+
- libpng
11+
- zlib
12+
- libflang
13+
- pcre2
14+
- libblas
15+
- liblapack
16+
- freetype

include/xeus-octave/xinterpreter.hpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <octave/oct-stream.h>
2626
#include <xeus/xinterpreter.hpp>
2727

28+
#include "xeus-octave/config.hpp"
2829
#include "xeus-octave/input.hpp"
2930
#include "xeus-octave/output.hpp"
3031

@@ -33,13 +34,24 @@ namespace nl = nlohmann;
3334
namespace xeus_octave
3435
{
3536

36-
class xoctave_interpreter : public xeus::xinterpreter
37+
class XEUS_OCTAVE_API xoctave_interpreter : public xeus::xinterpreter
3738
{
38-
private:
39+
public:
40+
41+
void publish_stream(std::string const& name, std::string const& text);
42+
43+
void display_data(nl::json data, nl::json metadata = nl::json::object(), nl::json transient = nl::json::object());
44+
45+
void
46+
update_display_data(nl::json data, nl::json metadata = nl::json::object(), nl::json transient = nl::json::object());
3947

40-
octave::interpreter interpreter;
48+
void publish_execution_result(int execution_count, nl::json data, nl::json metadata);
4149

42-
private:
50+
void publish_execution_error(
51+
std::string const& ename, std::string const& evalue, std::vector<std::string> const& trace_back
52+
);
53+
54+
protected:
4355

4456
void configure_impl() override;
4557

@@ -61,24 +73,16 @@ class xoctave_interpreter : public xeus::xinterpreter
6173

6274
void shutdown_request_impl() override;
6375

64-
public:
65-
66-
void publish_stream(std::string const& name, std::string const& text);
67-
void display_data(nl::json data, nl::json metadata = nl::json::object(), nl::json transient = nl::json::object());
68-
void
69-
update_display_data(nl::json data, nl::json metadata = nl::json::object(), nl::json transient = nl::json::object());
70-
void publish_execution_result(int execution_count, nl::json data, nl::json metadata);
71-
void publish_execution_error(
72-
std::string const& ename, std::string const& evalue, std::vector<std::string> const& trace_back
73-
);
76+
protected:
7477

75-
private:
78+
octave::interpreter m_octave_interpreter;
7679

7780
io::xoctave_output m_stdout{"stdout"};
7881
io::xoctave_output m_stderr{"stderr"};
7982
io::xoctave_input m_stdin;
8083

81-
bool m_silent, m_allow_stdin;
84+
bool m_silent{false};
85+
bool m_allow_stdin{false};
8286
};
8387

8488
} // namespace xeus_octave

0 commit comments

Comments
 (0)