diff --git a/.github/workflows/ci-macos-wasm.yml b/.github/workflows/ci-macos-wasm.yml
new file mode 100644
index 0000000000..eb0fe1b850
--- /dev/null
+++ b/.github/workflows/ci-macos-wasm.yml
@@ -0,0 +1,89 @@
+name: Build on macOS for WASM
+on:
+ push:
+ branches: [main]
+ paths:
+ - "src/**"
+ - "!src/Plugins/Macos/**"
+ - "!src/Plugins/Windows/**"
+ - "tests/**"
+ - "lolly/**"
+ - "moebius/**"
+ - "xmake.lua"
+ - 'xmake/options.lua'
+ - 'xmake/requires.lua'
+ - 'xmake/targets/**'
+ - "xmake/packages.lua"
+ - "xmake/packages/**"
+ - ".github/workflows/ci-macos-wasm.yml"
+ - "TeXmacs/tests/*.scm"
+ - "3rdparty/**"
+ pull_request:
+ branches: [main]
+ paths:
+ - "src/**"
+ - "!src/Plugins/Macos/**"
+ - "!src/Plugins/Windows/**"
+ - "tests/**"
+ - "lolly/**"
+ - "moebius/**"
+ - "xmake.lua"
+ - 'xmake/options.lua'
+ - 'xmake/requires.lua'
+ - 'xmake/targets/**'
+ - "xmake/packages.lua"
+ - "xmake/packages/**"
+ - ".github/workflows/ci-macos-wasm.yml"
+ - "TeXmacs/tests/*.scm"
+ - "3rdparty/**"
+ workflow_dispatch:
+
+env:
+ XMAKE_ROOT: y
+ INSTALL_DIR: tmp/build/packages/app.mogan/
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ os: [macos-14]
+ arch: [arm64]
+ runs-on: ${{ matrix.os }}
+ timeout-minutes: 45
+ if: always()
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: cache xmake
+ uses: actions/cache@v4
+ with:
+ path: |
+ ${{github.workspace}}/build/.build_cache
+ /Users/runner/.xmake
+ key: xmake-${{ runner.os }}-wasm-${{ hashFiles('xmake/vars.lua', 'lolly/xmake.lua', 'moebius/xmake.lua') }}
+
+ - name: set XMAKE_GLOBALDIR
+ run: echo "XMAKE_GLOBALDIR=${{ runner.workspace }}/xmake-global" >> $GITHUB_ENV
+
+ - uses: xmake-io/github-action-setup-xmake@v1
+ with:
+ xmake-version: v3.0.4
+ actions-cache-folder: '.xmake-cache'
+
+ - name: xmake repo --update
+ run: xmake repo --update
+
+ - name: cache packages from xrepo
+ uses: actions/cache@v4
+ with:
+ path: |
+ ${{ env.XMAKE_GLOBALDIR }}/.xmake/packages
+ key: xrepo-${{ runner.os }}-${{ matrix.arch }}-${{ hashFiles('xmake/vars.lua', 'lolly/xmake.lua', 'moebius/xmake.lua') }}
+
+ - name: config
+ run: xmake config --policies=build.ccache -o ${{ runner.workspace }}/build -m releasedbg -p wasm --qt_frontend=no --yes
+
+ - name: build
+ run: xmake build --yes -vD stem
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 90946f032c..076db58a69 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,9 @@ docs/**/plugin_binary.md
# Binary of the goldfish plugin
TeXmacs/plugins/goldfish/bin/goldfish
+TeXmacs/plugins/goldfish/bin/*.wasm
+TeXmacs/plugins/goldfish/bin/*.js
+TeXmacs/plugins/goldfish/bin/*.html
goldfish.dSYM/
*.sym
*goldfish.pdb
@@ -53,4 +56,4 @@ goldfish.dSYM/
# font
TeXmacs/fonts/opentype/noto
-record
\ No newline at end of file
+record
diff --git a/3rdparty/libaesgm.lua b/3rdparty/libaesgm.lua
index 338e1a2495..f41f0506c1 100644
--- a/3rdparty/libaesgm.lua
+++ b/3rdparty/libaesgm.lua
@@ -10,7 +10,7 @@ package("liii-libaesgm")
set_sourcedir(path.join(os.scriptdir(), "libaesgm"))
- on_install("linux", "macosx", "windows", "mingw", function (package)
+ on_install("linux", "macosx", "windows", "mingw", "wasm", function (package)
if package:is_plat("windows", "mingw") and package:is_arch("arm", "arm64") then
-- Windows is always little endian
io.replace("brg_endian.h", [[
diff --git a/3rdparty/pdfhummus.lua b/3rdparty/pdfhummus.lua
index 7173c3827e..0e7ee515ba 100644
--- a/3rdparty/pdfhummus.lua
+++ b/3rdparty/pdfhummus.lua
@@ -30,7 +30,7 @@ package("liii-pdfhummus")
end
end
end)
- on_install("linux", "windows", "mingw", "macosx", function (package)
+ on_install("linux", "windows", "mingw", "macosx", "wasm", function (package)
local configs = {}
if package:config("shared") then
configs.kind = "shared"
diff --git a/3rdparty/pdfhummus/xmake.lua b/3rdparty/pdfhummus/xmake.lua
index 80012ea999..390b261e61 100644
--- a/3rdparty/pdfhummus/xmake.lua
+++ b/3rdparty/pdfhummus/xmake.lua
@@ -1,5 +1,6 @@
-- originally from https://github.com/xmake-io/xmake-repo/pull/1709
+includes("../libaesgm.lua")
option("libtiff", {description = "Enable libtiff", default = false})
option("libpng", {description = "Enable libpng", default = false})
option("libjpeg", {description = "Enable libjpeg", default = false})
@@ -17,14 +18,14 @@ end
if has_config("openssl") then
add_requires("openssl")
end
-add_requires("freetype", "zlib", "libaesgm")
+add_requires("freetype", "zlib", "liii-libaesgm")
target("pdfhummus")
set_kind("$(kind)")
add_files("PDFWriter/*.cpp")
add_headerfiles("(PDFWriter/*.h)")
add_packages("freetype")
add_packages("libtiff", "libpng", "libjpeg", "openssl")
- add_packages("libaesgm", "zlib")
+ add_packages("liii-libaesgm", "zlib")
if has_package("libtiff") then
add_defines("_INCLUDE_TIFF_HEADER")
add_cxflags("-Wno-deprecated-declarations")
diff --git a/3rdparty/tbox/xmake.lua b/3rdparty/tbox/xmake.lua
index b1fe97ce51..8cb3b80578 100644
--- a/3rdparty/tbox/xmake.lua
+++ b/3rdparty/tbox/xmake.lua
@@ -31,12 +31,6 @@ if has_config("coroutine") then
add_cxflags("gcc::-Wno-error=dangling-pointer")
end
--- set wasm toolchain
-if is_plat("wasm") then
- add_requires("emscripten")
- set_toolchains("emcc@emscripten")
-end
-
-- add build modes
add_rules("mode.release", "mode.debug", "mode.profile", "mode.coverage", "mode.valgrind", "mode.asan", "mode.tsan", "mode.ubsan")
if is_mode("debug") then
diff --git a/bin/wasm_server.py b/bin/wasm_server.py
new file mode 100644
index 0000000000..838b45b4e4
--- /dev/null
+++ b/bin/wasm_server.py
@@ -0,0 +1,62 @@
+from http.server import ThreadingHTTPServer, SimpleHTTPRequestHandler
+import sys
+import os
+
+root = os.path.abspath(sys.argv[1])
+
+html = os.path.join(root, "stem.html")
+js = os.path.join(root, "stem.js")
+
+#if not os.path.exists(html) and os.path.exists(js):
+with open(html, "w", encoding="utf-8") as f:
+ f.write("""
+
+
+
+ stem
+
+
+
+
+
+
+
+
+
+
+""")
+
+class Handler(SimpleHTTPRequestHandler):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, directory=root, **kwargs)
+
+ def end_headers(self):
+ self.send_header(
+ "Cross-Origin-Opener-Policy",
+ "same-origin"
+ )
+ self.send_header(
+ "Cross-Origin-Embedder-Policy",
+ "require-corp"
+ )
+ super().end_headers()
+
+server = ThreadingHTTPServer(
+ ("127.0.0.1", 8000),
+ Handler
+)
+
+print("Serving on http://127.0.0.1:8000/stem.html")
+
+server.serve_forever()
\ No newline at end of file
diff --git a/devel/0724.md b/devel/0724.md
new file mode 100644
index 0000000000..178b340752
--- /dev/null
+++ b/devel/0724.md
@@ -0,0 +1,21 @@
+# [0724] WASM Support for STEM (ImGui)
+## What
+- 在构建脚本中添加了适配 wasm 的逻辑
+- bin 中新增 wasm_server.py
+- `tm_server.cpp` `pipe_link.cpp` 中调整 WASM 条件编译选项,以通过编译(目前没有实现 WASM 的多进程接口)
+- `im_tm_widget` 中添加符合 Emscripten 3.1.56 的调用(在条件编译中)
+
+## 如何测试
+测试默认的 Qt 构建不被改变
+```
+xmake f
+xmake b stem
+```
+
+测试 WASM 构建
+```
+xmake f -p wasm
+xmake b stem
+xmake r stem
+```
+浏览器打开监听的地址
diff --git a/lolly/xmake.lua b/lolly/xmake.lua
index 68aaef70f4..381ac1b8a6 100644
--- a/lolly/xmake.lua
+++ b/lolly/xmake.lua
@@ -21,11 +21,6 @@ if is_plat("mingw") and is_host("windows") then
set_toolchains("mingw@mingw-w64")
end
-if is_plat("wasm") then
- add_requires("emscripten 3.1.25")
- set_toolchains("emcc@emscripten")
-end
-
-- Options
option("malloc")
set_default("default")
diff --git a/src/Plugins/ImGui/im_tm_widget.cpp b/src/Plugins/ImGui/im_tm_widget.cpp
index 6425832a3e..e07fa6197d 100644
--- a/src/Plugins/ImGui/im_tm_widget.cpp
+++ b/src/Plugins/ImGui/im_tm_widget.cpp
@@ -25,7 +25,9 @@
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
+#ifndef __EMSCRIPTEN__
#include "backends/imgui_impl_opengl3_loader.h"
+#endif
#include "imgui.h"
#if defined(IMGUI_IMPL_OPENGL_ES2)
@@ -33,6 +35,10 @@
#endif
#include // defines GLFWwindow, drags in system OpenGL headers
+#ifdef __EMSCRIPTEN__
+#include
+#endif
+
#include
#include
#include
@@ -239,7 +245,9 @@ im_tm_widget_rep::im_tm_widget_rep (int mask, command _quit)
return;
}
glfwMakeContextCurrent (window);
- glfwSwapInterval (1); // enable vsync
+#ifndef __EMSCRIPTEN__
+ glfwSwapInterval (1);
+#endif
// Match retina factor
float xscale= 1.0f, yscale= 1.0f;
@@ -272,6 +280,9 @@ im_tm_widget_rep::im_tm_widget_rep (int mask, command _quit)
style.FontScaleDpi= main_scale;
ImGui_ImplGlfw_InitForOpenGL (window, true);
+#ifdef __EMSCRIPTEN__
+ ImGui_ImplGlfw_InstallEmscriptenCallbacks (window, "#canvas");
+#endif
ImGui_ImplOpenGL3_Init (glsl_version);
initialized= true;
@@ -287,9 +298,6 @@ void
im_tm_widget_rep::shutdown_context () {
if (!initialized) return;
initialized= false;
-#ifdef __EMSCRIPTEN__
- EMSCRIPTEN_MAINLOOP_END;
-#endif
if (document_texture) {
glDeleteTextures (1, &document_texture);
document_texture= 0;
@@ -329,160 +337,175 @@ im_tm_widget_rep::plain_window_widget (string name, command _quit, int b) {
******************************************************************************/
void
-im_tm_widget_rep::run () {
- if (!initialized || window == nullptr) return;
- while (!glfwWindowShouldClose (window)) {
- glfwPollEvents ();
- // 创建了一个 stub 窗口(例如 Cmd+F 的查找窗口等)时 server
- // 将当前窗口从我们这里切换走, 编辑器被 suspend () 挂起(got_focus=false)
- // 在这里重新恢复这两种焦点状态,以确保后续的键盘和鼠标事件能够继续正常传递。
- // 此代码会在创建该占位窗口的 Scheme 处理函数返回之后执行
- // (即 glfwPollEvents 已经分发了 Cmd+F 的按键事件)。
- if (needs_refocus) {
- needs_refocus= false;
- if (window) glfwFocusWindow (window);
- im_simple_widget_rep* ed= canvas ();
- if (ed) ed->handle_keyboard_focus (true, texmacs_time ());
+im_tm_widget_rep::im_main_loop () {
+ glfwPollEvents ();
+ // 创建了一个 stub 窗口(例如 Cmd+F 的查找窗口等)时 server
+ // 将当前窗口从我们这里切换走, 编辑器被 suspend () 挂起(got_focus=false)
+ // 在这里重新恢复这两种焦点状态,以确保后续的键盘和鼠标事件能够继续正常传递。
+ // 此代码会在创建该占位窗口的 Scheme 处理函数返回之后执行
+ // (即 glfwPollEvents 已经分发了 Cmd+F 的按键事件)。
+ if (needs_refocus) {
+ needs_refocus= false;
+ if (window) glfwFocusWindow (window);
+ im_simple_widget_rep* ed= canvas ();
+ if (ed) ed->handle_keyboard_focus (true, texmacs_time ());
+ }
+ // Auto-scroll while dragging (left button held) near the top/bottom edge.
+ // ImGui 实现的拖动滚动逻辑
+ if (!is_nil (main_widget) && window != nullptr &&
+ glfwGetMouseButton (window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
+ double xpos= 0, ypos= 0;
+ glfwGetCursorPos (window, &xpos, &ypos);
+ int ww= 0, wh= 0;
+ glfwGetWindowSize (window, &ww, &wh);
+ const double EDGE= 48.0; // px proximity band
+ const SI MAXD= (SI) (80.0 * PIXEL); // cap per-frame scroll to avoid jitter
+ SI sx= 0, sy= 0;
+ get_scroll_position (main_widget, sx, sy);
+ SI new_sy= sy;
+ if (wh > 0 && ypos < EDGE) {
+ SI d= (SI) ((EDGE - ypos) * PIXEL);
+ if (d > MAXD) d= MAXD;
+ new_sy= sy + d; // near/over top → up
}
- // Auto-scroll while dragging (left button held) near the top/bottom edge.
- // ImGui 实现的拖动滚动逻辑
- if (!is_nil (main_widget) && window != nullptr &&
- glfwGetMouseButton (window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
- double xpos= 0, ypos= 0;
- glfwGetCursorPos (window, &xpos, &ypos);
- int ww= 0, wh= 0;
- glfwGetWindowSize (window, &ww, &wh);
- const double EDGE= 48.0; // px proximity band
- const SI MAXD=
- (SI) (80.0 * PIXEL); // cap per-frame scroll to avoid jitter
- SI sx= 0, sy= 0;
- get_scroll_position (main_widget, sx, sy);
- SI new_sy= sy;
- if (wh > 0 && ypos < EDGE) {
- SI d= (SI) ((EDGE - ypos) * PIXEL);
- if (d > MAXD) d= MAXD;
- new_sy= sy + d; // near/over top → up
- }
- else if (wh > 0 && ypos > (double) wh - EDGE) {
- SI d= (SI) ((ypos - ((double) wh - EDGE)) * PIXEL);
- if (d > MAXD) d= MAXD;
- new_sy= sy - d; // near/over bottom → down
- }
- if (new_sy != sy) {
- main_widget->send (SLOT_SCROLL_POSITION,
- close_box (coord2 (sx, new_sy)));
- // Re-dispatch a move so the editor's drag selection tracks the
- // viewport. Clamp ypos to [0, wh].
- double cy= ypos;
- if (cy < 0.0) cy= 0.0;
- if (wh > 0 && cy > (double) wh) cy= (double) wh;
- double cx= xpos;
- if (cx < 0.0) cx= 0.0;
- if (ww > 0 && cx > (double) ww) cx= (double) ww;
- SI msx= 0, msy= 0, nsx= 0, nsy= 0;
- screen_to_si (cx, cy, msx, msy);
- get_scroll_position (main_widget, nsx, nsy);
- dispatch_mouse ("move", msx + nsx, msy + nsy, 1);
- }
+ else if (wh > 0 && ypos > (double) wh - EDGE) {
+ SI d= (SI) ((ypos - ((double) wh - EDGE)) * PIXEL);
+ if (d > MAXD) d= MAXD;
+ new_sy= sy - d; // near/over bottom → down
}
-
- // Drive one TeXmacs tick. 驱动编辑器。
- im_interpose ();
- if (glfwGetWindowAttrib (window, GLFW_ICONIFIED) != 0) {
- ImGui_ImplGlfw_Sleep (10);
- continue;
+ if (new_sy != sy) {
+ main_widget->send (SLOT_SCROLL_POSITION,
+ close_box (coord2 (sx, new_sy)));
+ // Re-dispatch a move so the editor's drag selection tracks the
+ // viewport. Clamp ypos to [0, wh].
+ double cy= ypos;
+ if (cy < 0.0) cy= 0.0;
+ if (wh > 0 && cy > (double) wh) cy= (double) wh;
+ double cx= xpos;
+ if (cx < 0.0) cx= 0.0;
+ if (ww > 0 && cx > (double) ww) cx= (double) ww;
+ SI msx= 0, msy= 0, nsx= 0, nsy= 0;
+ screen_to_si (cx, cy, msx, msy);
+ get_scroll_position (main_widget, nsx, nsy);
+ dispatch_mouse ("move", msx + nsx, msy + nsy, 1);
}
+ }
- ImGui_ImplOpenGL3_NewFrame ();
- ImGui_ImplGlfw_NewFrame ();
- ImGui::NewFrame ();
- // Keep the editor canvas informed of the visible size (Qt does this via
- // resize events); otherwise update_visible()/SLOT_VISIBLE_PART report a
- // zero-sized region and the editor has nothing to render.
- static int last_cw= 0, last_ch= 0;
- if (!is_nil (main_widget)) {
- int cw= 0, ch= 0;
- glfwGetWindowSize (window, &cw, &ch);
- if (cw > 0 && ch > 0 && (cw != last_cw || ch != last_ch)) {
- last_cw= cw;
- last_ch= ch;
- main_widget->send (
- SLOT_SIZE,
- close_box (coord2 ((SI) (cw * PIXEL), (SI) (ch * PIXEL))));
- texture_dirty= true; // force a re-rasterization at the new canvas size
- }
- }
+ // Drive one TeXmacs tick. 驱动编辑器。
+ im_interpose ();
+ if (glfwGetWindowAttrib (window, GLFW_ICONIFIED) != 0) {
+ ImGui_ImplGlfw_Sleep (10);
+ return;
+ }
- static SI last_sx= 0, last_sy= 0;
- if (!is_nil (main_widget)) {
- SI sx= 0, sy= 0;
- get_scroll_position (main_widget, sx, sy);
- if (sx != last_sx || sy != last_sy) {
- last_sx = sx;
- last_sy = sy;
- texture_dirty= true;
- }
+ ImGui_ImplOpenGL3_NewFrame ();
+ ImGui_ImplGlfw_NewFrame ();
+ ImGui::NewFrame ();
+ // Keep the editor canvas informed of the visible size (Qt does this via
+ // resize events); otherwise update_visible()/SLOT_VISIBLE_PART report a
+ // zero-sized region and the editor has nothing to render.
+ static int last_cw= 0, last_ch= 0;
+ if (!is_nil (main_widget)) {
+ int cw= 0, ch= 0;
+ glfwGetWindowSize (window, &cw, &ch);
+ if (cw > 0 && ch > 0 && (cw != last_cw || ch != last_ch)) {
+ last_cw= cw;
+ last_ch= ch;
+ main_widget->send (SLOT_SIZE, close_box (coord2 (
+ (SI) (cw * PIXEL), (SI) (ch * PIXEL))));
+ texture_dirty= true; // force a re-rasterization at the new canvas size
}
+ }
- // Re-render only when something actually changed: either the window was
- // invalidated (texture_dirty, set by windows_refresh / SLOT_INVALIDATE_*),
- // or the editor canvas reports invalid regions.
- if (!is_nil (main_widget)) {
- if (texture_dirty || query_invalid (main_widget)) render_editor ();
+ static SI last_sx= 0, last_sy= 0;
+ if (!is_nil (main_widget)) {
+ SI sx= 0, sy= 0;
+ get_scroll_position (main_widget, sx, sy);
+ if (sx != last_sx || sy != last_sy) {
+ last_sx = sx;
+ last_sy = sy;
+ texture_dirty= true;
}
+ }
+
+ // Re-render only when something actually changed: either the window was
+ // invalidated (texture_dirty, set by windows_refresh / SLOT_INVALIDATE_*),
+ // or the editor canvas reports invalid regions.
+ if (!is_nil (main_widget)) {
+ if (texture_dirty || query_invalid (main_widget)) render_editor ();
+ }
#ifdef LIII_DEBUG
- {
- // show FPS
- ImGui::Begin ("FPS");
- ImGui::Text ("Application average %.3f ms/frame (%.1f FPS)",
- 1000.0f / io->Framerate, io->Framerate);
- ImGui::End ();
- }
+ {
+ // show FPS
+ ImGui::Begin ("FPS");
+ ImGui::Text ("Application average %.3f ms/frame (%.1f FPS)",
+ 1000.0f / io->Framerate, io->Framerate);
+ ImGui::End ();
+ }
#endif
- // Display the canvas
- int win_w= 0, win_h= 0;
- glfwGetWindowSize (window, &win_w, &win_h);
- int fb_w= 0, fb_h= 0;
- glfwGetFramebufferSize (window, &fb_w, &fb_h);
- ImGui::SetNextWindowPos (ImVec2 (0, 0));
- ImGui::SetNextWindowSize (ImVec2 ((float) win_w, (float) win_h));
- ImGui::PushStyleVar (ImGuiStyleVar_WindowRounding, 0.0f);
- ImGui::PushStyleVar (ImGuiStyleVar_WindowBorderSize, 0.0f);
- ImGui::PushStyleVar (ImGuiStyleVar_WindowPadding, ImVec2 (0, 0));
- {
- ImGui::Begin ("Mogan Canvas", nullptr,
- ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
- ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
- ImGuiWindowFlags_NoBringToFrontOnFocus |
- ImGuiWindowFlags_NoScrollbar |
- ImGuiWindowFlags_NoScrollWithMouse);
- ImGui::PopStyleVar (3);
- if (document_texture != 0) {
- ImVec2 avail= ImGui::GetContentRegionAvail ();
- float img_w= (float) tex_w;
- float img_h= (float) tex_h;
- if (img_w > avail.x) img_w= avail.x;
- if (img_h > avail.y) img_h= avail.y;
- // Note: ImGui 系永远从 (0, 0) 开始,所有位移用 scroll_x, scroll_y 完成
- ImGui::Image ((ImTextureID) (intptr_t) document_texture,
- ImVec2 (img_w, img_h));
- }
- else {
- ImGui::Text ("Editor canvas not yet wired.");
- ImGui::Text ("Close this window to quit.");
- }
- ImGui::End ();
+ // Display the canvas
+ int win_w= 0, win_h= 0;
+ glfwGetWindowSize (window, &win_w, &win_h);
+ int fb_w= 0, fb_h= 0;
+ glfwGetFramebufferSize (window, &fb_w, &fb_h);
+ ImGui::SetNextWindowPos (ImVec2 (0, 0));
+ ImGui::SetNextWindowSize (ImVec2 ((float) win_w, (float) win_h));
+ ImGui::PushStyleVar (ImGuiStyleVar_WindowRounding, 0.0f);
+ ImGui::PushStyleVar (ImGuiStyleVar_WindowBorderSize, 0.0f);
+ ImGui::PushStyleVar (ImGuiStyleVar_WindowPadding, ImVec2 (0, 0));
+ {
+ ImGui::Begin ("Mogan Canvas", nullptr,
+ ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
+ ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
+ ImGuiWindowFlags_NoBringToFrontOnFocus |
+ ImGuiWindowFlags_NoScrollbar |
+ ImGuiWindowFlags_NoScrollWithMouse);
+ ImGui::PopStyleVar (3);
+ if (document_texture != 0) {
+ ImVec2 avail= ImGui::GetContentRegionAvail ();
+ float img_w= (float) tex_w;
+ float img_h= (float) tex_h;
+ if (img_w > avail.x) img_w= avail.x;
+ if (img_h > avail.y) img_h= avail.y;
+ // Note: ImGui 系永远从 (0, 0) 开始,所有位移用 scroll_x, scroll_y 完成
+ ImGui::Image ((ImTextureID) (intptr_t) document_texture,
+ ImVec2 (img_w, img_h));
+ }
+ else {
+ ImGui::Text ("Editor canvas not yet wired.");
+ ImGui::Text ("Close this window to quit.");
}
+ ImGui::End ();
+ }
+
+ ImGui::Render ();
+ glViewport (0, 0, fb_w, fb_h);
+ glClearColor (0.45f, 0.55f, 0.60f, 1.00f);
+ glClear (GL_COLOR_BUFFER_BIT);
+ ImGui_ImplOpenGL3_RenderDrawData (ImGui::GetDrawData ());
+ glfwSwapBuffers (window);
+}
+
+void
+im_tm_widget_rep::em_main_loop_wrapper (void* arg) {
+ auto* self= static_cast (arg);
+ self->im_main_loop ();
+}
- ImGui::Render ();
- glViewport (0, 0, fb_w, fb_h);
- glClearColor (0.45f, 0.55f, 0.60f, 1.00f);
- glClear (GL_COLOR_BUFFER_BIT);
- ImGui_ImplOpenGL3_RenderDrawData (ImGui::GetDrawData ());
- glfwSwapBuffers (window);
+void
+im_tm_widget_rep::run () {
+ if (!initialized || window == nullptr) return;
+#ifdef __EMSCRIPTEN__
+ emscripten_set_main_loop_arg (im_tm_widget_rep::em_main_loop_wrapper, this, 0,
+ true);
+ emscripten_cancel_main_loop ();
+#else
+ while (!glfwWindowShouldClose (window)) {
+ im_main_loop ();
}
+#endif
shutdown_context ();
}
diff --git a/src/Plugins/ImGui/im_tm_widget.hpp b/src/Plugins/ImGui/im_tm_widget.hpp
index e1796b2216..7c822d02b1 100644
--- a/src/Plugins/ImGui/im_tm_widget.hpp
+++ b/src/Plugins/ImGui/im_tm_widget.hpp
@@ -69,6 +69,8 @@ class im_tm_widget_rep : public im_widget_rep {
array data= array ());
// Convert a position in GLFW screen coordinates to the renderer's SI space
void screen_to_si (double xpos, double ypos, SI& sx, SI& sy);
+ // ImGui's main loop
+ void im_main_loop ();
// The attached editor canvas. nullptr when no real editor is wired
im_simple_widget_rep* canvas ();
@@ -76,6 +78,8 @@ class im_tm_widget_rep : public im_widget_rep {
im_tm_widget_rep (int mask, command quit);
~im_tm_widget_rep ();
+ static void em_main_loop_wrapper (void* arg);
+
// Provide the typeset document to display
void set_box (box b, double zoom_factor);
diff --git a/src/System/Link/pipe_link.cpp b/src/System/Link/pipe_link.cpp
index 272f8d102a..c302eec95f 100644
--- a/src/System/Link/pipe_link.cpp
+++ b/src/System/Link/pipe_link.cpp
@@ -13,8 +13,8 @@
#include "tm_debug.hpp"
#include "tm_link.hpp"
-#if !(defined(QTTEXMACS) && (defined(OS_MINGW) || defined(QTPIPES) || \
- defined(OS_WIN) || defined(OS_WASM)))
+#if !(defined(QTTEXMACS) && \
+ (defined(OS_MINGW) || defined(QTPIPES) || defined(OS_WIN)))
#include "hashset.hpp"
#include "iterator.hpp"
@@ -97,6 +97,7 @@ pipe_link_rep::~pipe_link_rep () {
pipe_link_set->remove ((pointer) this);
}
+#ifndef OS_WASM
tm_link
make_pipe_link (string cmd) {
return tm_new (cmd);
@@ -127,6 +128,7 @@ process_all_pipes () {
if (con->alive) con->apply_command ();
}
}
+#endif
/******************************************************************************
* Routines for pipe_links
diff --git a/src/Texmacs/Server/tm_server.cpp b/src/Texmacs/Server/tm_server.cpp
index 2af21a1232..b5e6d561b3 100644
--- a/src/Texmacs/Server/tm_server.cpp
+++ b/src/Texmacs/Server/tm_server.cpp
@@ -19,9 +19,7 @@
#include "dictionary.hpp"
#include "file.hpp"
#include "glue.hpp"
-#ifndef OS_WASM
#include "goldfish.hpp"
-#endif
#include "lolly/system/subprocess.hpp"
#include "new_style.hpp"
#include "s7_blackbox.hpp"
@@ -154,9 +152,7 @@ tm_server_rep::tm_server_rep (app_type app) : def_zoomf (1.0) {
eval_scheme_root (init_prg);
initialize_smobs (initialize_scheme ());
initialize_glue ();
-#ifndef OS_WASM
goldfish::glue_for_community_edition (tm_s7);
-#endif
gui_interpose (texmacs_interpose_handler);
set_wait_handler (texmacs_wait_handler);
@@ -207,7 +203,6 @@ tm_server_rep::refresh () {
void
tm_server_rep::interpose_handler () {
-#ifndef OS_WASM
#ifdef QTTEXMACS
// TeXmacs/Qt handles delayed messages and socket notification
// in its own runloop
@@ -219,7 +214,6 @@ tm_server_rep::interpose_handler () {
perform_select ();
exec_pending_commands ();
#endif
-#endif // not OS_WASM
if (!headless_mode) {
int i, j;
diff --git a/xmake.lua b/xmake.lua
index 9cb024a642..a0ff6a2046 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -36,7 +36,7 @@ add_repositories("liii-repo xmake")
-- msvc, this project will not support windows env.
-- because some package is not ported to cygwin env, this project will not
-- support cygwin env.
-set_allowedplats("linux", "macosx", "windows")
+set_allowedplats("linux", "macosx", "windows", "wasm")
-- add releasedbg, debug and release modes for different platforms.
-- debug mode cannot run on mingw with qt precompiled binary
@@ -73,6 +73,14 @@ else
set_configvar("OS_WIN", false)
end
+if is_plat("wasm") then
+ set_configvar("OS_WASM", true)
+ add_requires("emscripten 3.1.56")
+ set_toolchains("emcc@emscripten")
+else
+ set_configvar("OS_WASM", false)
+end
+
includes("@builtin/check")
configvar_check_cxxtypes("HAVE_INTPTR_T", "intptr_t", {includes = {"memory"}})
configvar_check_cxxincludes("HAVE_INTTYPES_H", "inttypes.h")
@@ -103,34 +111,34 @@ if is_mode("release") then
end
if has_config("qt_frontend") then
-includes("xmake/tests.lua")
--- Tests in C++
-all_cpp_tests = os.files("tests/**_test.cpp")
-cpp_benches = os.files("bench/**_bench.cpp")
+ includes("xmake/tests.lua")
+ -- Tests in C++
+ all_cpp_tests = os.files("tests/**_test.cpp")
+ cpp_benches = os.files("bench/**_bench.cpp")
-for _, filepath in ipairs(cpp_benches) do
- add_target_cpp_bench(filepath, "libmogan")
-end
+ for _, filepath in ipairs(cpp_benches) do
+ add_target_cpp_bench(filepath, "libmogan")
+ end
-if not (is_plat("linux") and (linuxos.name () == "ubuntu" and linuxos.version():major() == 20)) then
- for _, filepath in ipairs(all_cpp_tests) do
- if not string.find(filepath, "tests/L3/") then
- add_target_cpp_test(filepath, "libmogan", "libmoebius")
+ if not (is_plat("linux") and (linuxos.name () == "ubuntu" and linuxos.version():major() == 20)) then
+ for _, filepath in ipairs(all_cpp_tests) do
+ if not string.find(filepath, "tests/L3/") then
+ add_target_cpp_test(filepath, "libmogan", "libmoebius")
+ end
end
end
-end
--- Tests in Scheme
-for _, filepath in ipairs(os.files("TeXmacs/progs/**/*-test.scm")) do
- add_target_scheme_test(filepath, INSTALL_DIR, RUN_ENVS)
-end
+ -- Tests in Scheme
+ for _, filepath in ipairs(os.files("TeXmacs/progs/**/*-test.scm")) do
+ add_target_scheme_test(filepath, INSTALL_DIR, RUN_ENVS)
+ end
-for _, filepath in ipairs(os.files("TeXmacs/progs/kernel/**/*-test.scm")) do
- add_target_scheme_test(filepath, INSTALL_DIR, RUN_ENVS)
-end
+ for _, filepath in ipairs(os.files("TeXmacs/progs/kernel/**/*-test.scm")) do
+ add_target_scheme_test(filepath, INSTALL_DIR, RUN_ENVS)
+ end
--- Integration tests
-for _, filepath in ipairs(os.files("TeXmacs/tests/*.scm")) do
- add_target_integration_test(filepath, INSTALL_DIR, RUN_ENVS)
-end
+ -- Integration tests
+ for _, filepath in ipairs(os.files("TeXmacs/tests/*.scm")) do
+ add_target_integration_test(filepath, INSTALL_DIR, RUN_ENVS)
+ end
end -- has_config("qt_frontend")
diff --git a/xmake/packages/l/libpng/xmake.lua b/xmake/packages/l/libpng/xmake.lua
new file mode 100644
index 0000000000..f6766b1f5b
--- /dev/null
+++ b/xmake/packages/l/libpng/xmake.lua
@@ -0,0 +1,92 @@
+package("libpng")
+ set_homepage("https://www.libpng.org/pub/png/libpng.html")
+ set_description("The official PNG reference library")
+ set_license("libpng-2.0")
+
+ add_urls("https://github.com/glennrp/libpng/archive/refs/tags/$(version).tar.gz",
+ "https://github.com/glennrp/libpng.git")
+
+ add_versions("v1.6.58", "a9d4df463d36a6e5f9c29bd6f4967312d17e996c1854f3511f833924eb1993cf")
+ add_versions("v1.6.57", "4cbb7b0746edc1683c9581b373365e955133b7f1243f171b7d1535b4415dfedb")
+ add_versions("v1.6.56", "41d74ffe235cb7e8bab40bcad2167f7bb25edbf2231dcfff57ccf4305dc0bfae")
+ add_versions("v1.6.55", "71a2c5b1218f60c4c6d2f1954c7eb20132156cae90bdb90b566c24db002782a6")
+ add_versions("v1.6.54", "ba7efce137409079989df4667706c339bebfbb10e9f413474718012a13c8cd4c")
+ add_versions("v1.6.53", "b20cee717e11416d2f96ccc7d184f63730ca8cb2f03bfd0c4ed77fbc909c0bff")
+ add_versions("v1.6.51", "b1872484c1c5c70acc79cbb15fb366df954fa8d5dacbe7f729d858902d17933c")
+ add_versions("v1.6.50", "71158e53cfdf2877bc99bcab33641d78df3f48e6e0daad030afe9cb8c031aa46")
+ add_versions("v1.6.49", "e425762fdfb9bb30a5d2da29c0067570e96b5d41d79c659cf0dad861e9df738e")
+ add_versions("v1.6.48", "b17e99026055727e8cba99160c3a9a7f9af788e9f786daeadded5a42243f1dd0")
+ add_versions("v1.6.47", "631a4c58ea6c10c81f160c4b21fa8495b715d251698ebc2552077e8450f30454")
+ add_versions("v1.6.46", "767b01936f9620d4ab4cdf6ec348f6526f861f825648b610b1d604167dc738d2")
+ add_versions("v1.6.44", "0ef5b633d0c65f780c4fced27ff832998e71478c13b45dfb6e94f23a82f64f7c")
+ add_versions("v1.6.43", "fecc95b46cf05e8e3fc8a414750e0ba5aad00d89e9fdf175e94ff041caf1a03a")
+ add_versions("v1.6.42", "fe89de292e223829859d21990d9c4d6b7e30e295a268f6a53a022611aa98bd67")
+ add_versions("v1.6.40", "62d25af25e636454b005c93cae51ddcd5383c40fa14aa3dae8f6576feb5692c2")
+ add_versions("v1.6.37", "ca74a0dace179a8422187671aee97dd3892b53e168627145271cad5b5ac81307")
+ add_versions("v1.6.36", "5bef5a850a9255365a2dc344671b7e9ef810de491bd479c2506ac3c337e2d84f")
+ add_versions("v1.6.35", "6d59d6a154ccbb772ec11772cb8f8beb0d382b61e7ccc62435bf7311c9f4b210")
+ add_versions("v1.6.34", "e45ce5f68b1d80e2cb9a2b601605b374bdf51e1798ef1c2c2bd62131dfcf9eef")
+
+ if is_plat("wasm") then
+ add_configs("shared", {description = "Build shared library.", default = false, type = "boolean", readonly = true})
+ add_deps("zlib")
+ else
+ add_deps("zlib")
+ end
+
+ if is_plat("linux") then
+ add_syslinks("m")
+ end
+
+ if is_plat("mingw") and is_subhost("msys") then
+ add_extsources("pacman::libpng")
+ elseif is_plat("linux") then
+ add_extsources("pacman::libpng", "apt::libpng-dev")
+ elseif is_plat("macosx") then
+ add_extsources("brew::libpng")
+ end
+
+ on_install(function (package)
+ if package:is_plat("android") and package:is_arch("armeabi-v7a") then
+ io.replace("arm/filter_neon.S", ".func", ".hidden", {plain = true})
+ io.replace("arm/filter_neon.S", ".endfunc", "", {plain = true})
+ end
+ os.cp("scripts/pnglibconf.h.prebuilt", "pnglibconf.h")
+ io.writefile("xmake.lua", [[
+ add_rules("mode.debug", "mode.release")
+ add_requires("zlib")
+ target("png")
+ set_kind("$(kind)")
+ add_files("*.c|example.c|pngtest.c")
+ if is_arch("x86", "x64", "i386", "x86_64") then
+ add_files("intel/*.c")
+ add_defines("PNG_INTEL_SSE_OPT=1")
+ add_vectorexts("sse", "sse2")
+ elseif is_arch("arm.*") then
+ add_files("arm/*.c")
+ if is_plat("windows") then
+ add_defines("PNG_ARM_NEON_OPT=1")
+ add_defines("PNG_ARM_NEON_IMPLEMENTATION=1")
+ else
+ add_files("arm/*.S")
+ add_defines("PNG_ARM_NEON_OPT=2")
+ end
+ elseif is_arch("mips.*") then
+ add_files("mips/*.c")
+ add_defines("PNG_MIPS_MSA_OPT=2")
+ elseif is_arch("ppc.*") then
+ add_files("powerpc/*.c")
+ add_defines("PNG_POWERPC_VSX_OPT=2")
+ end
+ add_headerfiles("*.h")
+ add_packages("zlib")
+ if is_kind("shared") and is_plat("windows") then
+ add_defines("PNG_BUILD_DLL")
+ end
+ ]])
+ import("package.tools.xmake").install(package)
+ end)
+
+ on_test(function (package)
+ assert(package:has_cfuncs("png_create_read_struct", {includes = "png.h"}))
+ end)
diff --git a/xmake/packages/m/mupdf/xmake.lua b/xmake/packages/m/mupdf/xmake.lua
index de092ffc61..a413b03059 100644
--- a/xmake/packages/m/mupdf/xmake.lua
+++ b/xmake/packages/m/mupdf/xmake.lua
@@ -27,26 +27,31 @@ package("mupdf")
if is_plat("linux", "macosx") then
add_deps("pkg-config", "make", "libjpeg", "freetype", "libcurl", "zlib")
+ elseif is_plat("wasm") then
+ add_deps("freetype", {configs={png=true}}) -- 保持与 liii-pdfhummus 一致,避免多次安装
+ add_deps("pkg-config", "make", "libjpeg", "harfbuzz", "zlib")
end
on_load(function (package)
if not is_plat("windows") then
if is_plat("linux") then
package:add("links", "mupdf", "mupdf-third", "harfbuzz")
+ elseif is_plat("wasm") then
+ package:add("links", "mupdf", "mupdf-third", "harfbuzz", "libjpeg", "freetype", "zlib")
else
package:add("links", "mupdf", "mupdf-third")
end
end
end)
- on_install("linux", "macosx", function (package)
+ on_install("linux", "macosx", "wasm", function (package)
if is_plat("macosx") then
io.writefile("user.make", "CFLAGS = -arch " .. package:targetarch())
-- Use pkg-config to detect system library
io.replace("Makerules", "else ifeq ($(LINUX_OR_OPENBSD),yes)", "", {plain = true})
end
-- Use system library from xmake to compat with other program
- import("package.tools.make").build(package, {
+ local configs = {
"install-libs",
"USE_SYSTEM_LIBJPEG=yes",
"USE_SYSTEM_FREETYPE=yes",
@@ -55,7 +60,56 @@ package("mupdf")
"tofu=yes",
"tofu_cjk=yes",
"prefix=" .. package:installdir()
- })
+ }
+ if not is_plat("wasm") then
+ import("package.tools.make").build(package, configs)
+ else
+ -- xmake seems not passing the right configs to mupdf's make
+ local cflags = {}
+ local ldflags = {}
+ local harfbuzz = package:dep("harfbuzz"):fetch()
+ local libjpeg = package:dep("libjpeg"):fetch()
+ local freetype = package:dep("freetype"):fetch()
+ local zlib = package:dep("zlib"):fetch()
+ local cc = package:tool("cc")
+ local cxx = package:tool("cxx")
+ local ld = package:tool("ld")
+ local ar = package:tool("ar")
+ local ranlib = package:tool("ranlib")
+ table.insert(configs, "CC=" .. cc)
+ table.insert(configs, "CXX=" .. cxx)
+ table.insert(configs, "LD=" .. ld)
+ table.insert(configs, "AR=" .. ar)
+ table.insert(configs, "RANLIB=" .. ranlib)
+ table.insert(configs, "USE_SYSTEM_HARFBUZZ=yes")
+ table.insert(cflags, "-matomics")
+ table.insert(cflags, "-mbulk-memory")
+ table.insert(cflags, "-pthread")
+ table.insert(ldflags, "-matomics")
+ table.insert(ldflags, "-mbulk-memory")
+ table.insert(ldflags, "-pthread")
+ table.insert(ldflags, "-sUSE_PTHREADS=1")
+ table.insert(ldflags, "-sSHARED_MEMORY=1")
+ table.insert(ldflags, "-DZ_PREFIX=OFF")
+ for _, pkg in ipairs({harfbuzz, libjpeg, freetype, zlib}) do
+ for _, dir in ipairs(pkg.sysincludedirs or {}) do
+ table.insert(cflags, "-I" .. dir)
+ end
+ for _, dir in ipairs(pkg.includedirs or {}) do
+ table.insert(cflags, "-I" .. dir)
+ end
+ for _, dir in ipairs(pkg.linkdirs or {}) do
+ table.insert(ldflags, "-L" .. dir)
+ end
+ end
+ os.execv("make verbose=yes", configs, {
+ envs = {
+ CFLAGS = table.concat(cflags, " "),
+ LDFLAGS = table.concat(ldflags, " ")
+ }
+ })
+ os.execv("make", table.join({"install-libs"}, configs))
+ end
end)
on_install("windows", function (package)
@@ -80,4 +134,4 @@ package("mupdf")
local output = format("platform/win32/%s/%s/", arch, build_type)
os.cp(output .. "libmupdf.lib", package:installdir("lib"))
os.cp(output .. "libthirdparty.lib", package:installdir("lib"))
- end)
+ end)
\ No newline at end of file
diff --git a/xmake/requires.lua b/xmake/requires.lua
index 195591bbc8..81c2b4d0f4 100644
--- a/xmake/requires.lua
+++ b/xmake/requires.lua
@@ -10,7 +10,9 @@
add_requires("goldfish", {system=false})
add_requires("liii-tbox", {system=false})
-add_requires("cpr", {system=false})
+if not is_plat("wasm") then
+ add_requires("cpr", {system=false})
+end
-- QWK is built locally from 3rdparty/qwindowkitty, no external package needed
if is_plat ("windows") then
add_requires("libiconv "..LIBICONV_VERSION, {system=false})
@@ -26,7 +28,9 @@ elseif is_plat("linux") and (linuxos.name() == "fedora" or linuxos.name() == "rh
add_requires("libcurl", {system=true})
else
add_requires("libpng", {system=false})
- add_requires("libcurl", {system=false})
+ if not is_plat("wasm") then
+ add_requires("libcurl", {system=false})
+ end
end
add_requires("liii-pdfhummus", {system=false,configs={libpng=true,libjpeg=true}})
@@ -38,7 +42,7 @@ add_requires("argh v1.3.2")
if has_config("qt_frontend") then
QT6_VERSION="6.8.3"
add_requires("qt6widgets "..QT6_VERSION)
-else
+elseif not is_plat("wasm") then -- WASM GLFW is in EMCC
add_requires("glfw")
end
diff --git a/xmake/stem.lua b/xmake/stem.lua
index 5c283e030f..49d737886d 100644
--- a/xmake/stem.lua
+++ b/xmake/stem.lua
@@ -17,6 +17,7 @@ stem_binary_linux = "moganstem"
stem_dmg_bg_image = "mogan-background.png"
stem_binary_macos = stem_binary_name
stem_binary_windows = stem_binary_name .. ".exe"
+stem_binary_wasm = "stem.js"
stem_lab_name = "moganlab"
stem_lab_big_name= "MoganLab"
diff --git a/xmake/targets/libmogan.lua b/xmake/targets/libmogan.lua
index 9bcf6eb1c0..b2189b9f64 100644
--- a/xmake/targets/libmogan.lua
+++ b/xmake/targets/libmogan.lua
@@ -75,7 +75,7 @@ target("libmogan") do
add_defines("QTPIPES")
set_configvar("USE_QT_PRINTER", 1)
add_defines("USE_QT_PRINTER")
- else
+ elseif not is_plat("wasm") then -- WASM GLFW is in EMCC
add_packages("glfw")
end
@@ -83,7 +83,9 @@ target("libmogan") do
add_packages("freetype")
add_packages("goldfish")
add_packages("liii-tbox")
- add_packages("cpr")
+ if not is_plat("wasm") then
+ add_packages("cpr")
+ end
add_packages("argh")
if not is_plat("macosx") then
add_packages("libiconv")
@@ -148,10 +150,18 @@ target("libmogan") do
set_configvar("CONFIG_OS", "")
end
- configvar_check_cxxsnippets(
- "CONFIG_LARGE_POINTER", [[
- #include
- static_assert(sizeof(void*) == 8, "");]])
+ if not is_plat("wasm") then
+ configvar_check_cxxsnippets(
+ "CONFIG_LARGE_POINTER", [[
+ #include
+ static_assert(sizeof(void*) == 8, "");]])
+ else
+ -- WASM use 32 bit pointers
+ configvar_check_cxxsnippets(
+ "CONFIG_LARGE_POINTER", [[
+ #include
+ static_assert(sizeof(void*) == 4, "");]])
+ end
add_configfiles(
"$(projectdir)/src/System/tm_configure.hpp.xmake", {
filename = "tm_configure.hpp",
@@ -280,6 +290,7 @@ target("libmogan") do
add_files("$(projectdir)/src/Plugins/Qt/moganqml.qrc")
else
add_files("$(projectdir)/src/Plugins/ImGui/**.cpp")
+ remove_files("$(projectdir)/TeXmacs/plugins/goldfish/src/liii_http.cpp")
end
if is_plat("macosx") then
diff --git a/xmake/targets/stem.lua b/xmake/targets/stem.lua
index 18d25e575f..25c45fb549 100644
--- a/xmake/targets/stem.lua
+++ b/xmake/targets/stem.lua
@@ -34,6 +34,8 @@ target("stem") do
set_filename(stem_binary_linux)
elseif is_plat("macosx") then
set_filename(stem_binary_macos)
+ elseif is_plat("wasm") then
+ set_filename(stem_binary_wasm)
else
set_filename(stem_binary_windows)
end
@@ -96,6 +98,17 @@ target("stem") do
set_runtimes("MT")
add_ldflags("/STACK:16777216")
end
+
+ if is_plat("wasm") then
+ add_cxxflags("-O3")
+ add_cxxflags("-sUSE_GLFW=3")
+ add_ldflags("-O3")
+ add_ldflags("-sUSE_GLFW=3")
+ add_ldflags("-sINITIAL_MEMORY=512MB")
+ add_ldflags("-sALLOW_MEMORY_GROWTH=1")
+ add_ldflags("-sSTACK_SIZE=32MB", {force = true})
+ add_ldflags("--preload-file=" .. path.join(os.projectdir(), "TeXmacs") .. "@/TeXmacs")
+ end
if has_config("qt_frontend") then
-- Qt frontend: build stem as a Qt app.
@@ -110,7 +123,7 @@ target("stem") do
add_packages("goldfish")
add_packages("mupdf")
- if not has_config("qt_frontend") then
+ if not has_config("qt_frontend") and not is_plat("wasm") then -- WASM GLFW is in EMCC
add_packages("glfw")
end
add_deps("liblolly")
@@ -221,6 +234,12 @@ target("stem") do
os.execv(binary, params, {envs={TEXMACS_PATH= path.join(os.projectdir(), "TeXmacs")}})
elseif is_plat("windows") then
os.execv(binary, params)
+ elseif is_plat("wasm") then
+ local build_dir = path.absolute(path.directory(binary))
+ os.execv("python3", {
+ path.join(os.projectdir(), "bin/wasm_server.py"),
+ build_dir
+ })
else
print("Unsupported platform: " .. tostring(os.host()))
end