From 121fa3301d4fe34337a373bc1a4488129caf09b8 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 11:29:37 +0100 Subject: [PATCH 01/52] Normalize main signatures in auto-aux tests, add missing includes, and modernize signal handling - Change old-style "main()" to standard "int main(int argc, char **argv)" in several auto-aux test programs (align.c, bytecopy.c, dblalign.c, endian.c, schar.c, schar2.c, setjmp.c, sighandler.c). - Fix sighandler.c to use sig_t for the saved handler variable. - Add missing includes: stdlib.h in runtime/io.c, unistd.h in config/auto-aux/signals.c, and fail.h/memory.h in src/dynlibs/mgd/mgd.c. - Replace deprecated SA_NOMASK with SA_NODEFER in sys.c when installing sigaction. --- src/config/auto-aux/align.c | 2 +- src/config/auto-aux/bytecopy.c | 2 +- src/config/auto-aux/dblalign.c | 2 +- src/config/auto-aux/endian.c | 2 +- src/config/auto-aux/schar.c | 2 +- src/config/auto-aux/schar2.c | 2 +- src/config/auto-aux/setjmp.c | 2 +- src/config/auto-aux/sighandler.c | 4 ++-- src/config/auto-aux/signals.c | 1 + src/dynlibs/mgd/mgd.c | 2 ++ src/runtime/io.c | 1 + src/runtime/sys.c | 2 +- 12 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/config/auto-aux/align.c b/src/config/auto-aux/align.c index 87ed3781..7b64de68 100644 --- a/src/config/auto-aux/align.c +++ b/src/config/auto-aux/align.c @@ -95,7 +95,7 @@ int speedtest(p) return total; } -main() +int main(int argc, char ** argv) { long n[1001]; int speed_aligned, speed_unaligned; diff --git a/src/config/auto-aux/bytecopy.c b/src/config/auto-aux/bytecopy.c index 08f56289..163f1821 100644 --- a/src/config/auto-aux/bytecopy.c +++ b/src/config/auto-aux/bytecopy.c @@ -8,7 +8,7 @@ char buffer[27]; #define cpy copy #endif -main() +int main(int argc, char ** argv) { cpy("abcdefghijklmnopqrstuvwxyz", buffer, 27); if (strcmp(buffer, "abcdefghijklmnopqrstuvwxyz") != 0) exit(1); diff --git a/src/config/auto-aux/dblalign.c b/src/config/auto-aux/dblalign.c index 0557dab4..e2402758 100644 --- a/src/config/auto-aux/dblalign.c +++ b/src/config/auto-aux/dblalign.c @@ -19,7 +19,7 @@ void sig_handler() longjmp(failure, 1); } -main() +int main(int argc, char ** argv) { #define ARRSIZE 100 long n[ARRSIZE]; diff --git a/src/config/auto-aux/endian.c b/src/config/auto-aux/endian.c index d1d9039c..5778ae77 100644 --- a/src/config/auto-aux/endian.c +++ b/src/config/auto-aux/endian.c @@ -1,7 +1,7 @@ #include #include -main() +int main(int argc, char ** argv) { long n[2]; char * p; diff --git a/src/config/auto-aux/schar.c b/src/config/auto-aux/schar.c index de11d5e4..a8f7a287 100644 --- a/src/config/auto-aux/schar.c +++ b/src/config/auto-aux/schar.c @@ -1,7 +1,7 @@ #include char foo[]="\377"; -main() +int main(int argc, char ** argv) { int i; i = foo[0]; diff --git a/src/config/auto-aux/schar2.c b/src/config/auto-aux/schar2.c index 2e067f20..05816d36 100644 --- a/src/config/auto-aux/schar2.c +++ b/src/config/auto-aux/schar2.c @@ -1,7 +1,7 @@ #include signed char foo[]="\377"; -main() +int main(int argc, char ** argv) { int i; i = foo[0]; diff --git a/src/config/auto-aux/setjmp.c b/src/config/auto-aux/setjmp.c index 0867e62b..a4ee6117 100644 --- a/src/config/auto-aux/setjmp.c +++ b/src/config/auto-aux/setjmp.c @@ -1,6 +1,6 @@ #include -main() +int main(int argc, char ** argv) { jmp_buf buf; int i; diff --git a/src/config/auto-aux/sighandler.c b/src/config/auto-aux/sighandler.c index 7170fe6a..23211e39 100644 --- a/src/config/auto-aux/sighandler.c +++ b/src/config/auto-aux/sighandler.c @@ -1,8 +1,8 @@ #include -int main() +int main(int argc, char ** argv) { - SIGRETURN (*old)(); + sig_t old; old = signal(SIGQUIT, SIG_DFL); return 0; } diff --git a/src/config/auto-aux/signals.c b/src/config/auto-aux/signals.c index 17d158f3..31ebf6c4 100644 --- a/src/config/auto-aux/signals.c +++ b/src/config/auto-aux/signals.c @@ -4,6 +4,7 @@ #include #include +#include int counter; diff --git a/src/dynlibs/mgd/mgd.c b/src/dynlibs/mgd/mgd.c index 859bf3d2..1321c656 100644 --- a/src/dynlibs/mgd/mgd.c +++ b/src/dynlibs/mgd/mgd.c @@ -23,6 +23,8 @@ #include /* For alloc_tuple, ... */ #include /* For Val_unit, Long_val, String_val, ... */ +#include /* for failwith */ +#include /* for modify */ /* Representation of images. diff --git a/src/runtime/io.c b/src/runtime/io.c index f14e531b..1a850674 100644 --- a/src/runtime/io.c +++ b/src/runtime/io.c @@ -5,6 +5,7 @@ #include #include #include +#include #ifdef WIN32 #include diff --git a/src/runtime/sys.c b/src/runtime/sys.c index 363ecc6b..3f051c8f 100644 --- a/src/runtime/sys.c +++ b/src/runtime/sys.c @@ -278,7 +278,7 @@ void mysignal(int signum, sighandler_return_type (*handler)(int)) { sigemptyset(&emptyset); sigact.sa_handler = handler; sigact.sa_mask = emptyset; - sigact.sa_flags = SA_NOMASK; + sigact.sa_flags = SA_NODEFER; sigaction(signum, &sigact, 0); #else signal(signum, handler); From 3aa3e5a6260407c2f60319fabf78dc9ae1da63a5 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 12:51:31 +0100 Subject: [PATCH 02/52] Use rlwrap for interactive REPL (when stdin is a terminal) --- src/launch/mosml.tpl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/launch/mosml.tpl b/src/launch/mosml.tpl index e13c5aa3..4e9fa7cb 100755 --- a/src/launch/mosml.tpl +++ b/src/launch/mosml.tpl @@ -5,10 +5,21 @@ mosmlbin=BINDIR includes="" options="-conservative" +# Check if rlwrap is available and stdin is a terminal +use_rlwrap="" +if [ -t 0 ] && command -v rlwrap >/dev/null 2>&1; then + use_rlwrap="rlwrap -a -N -H $HOME/.mosml_history -s 1000" +fi + +# Disable rlwrap if RLWRAP environment variable is already set +if [ -n "$RLWRAP" ]; then + use_rlwrap="" +fi + while : ; do case $1 in "") - exec $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options;; + exec $use_rlwrap $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options;; -I|-include) includes="$includes -I $2" shift;; @@ -36,7 +47,7 @@ while : ; do -*) echo "Unknown option \"$1\", ignored" >&2;; *) - exec $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options $* ;; + exec $use_rlwrap $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options $* ;; esac shift done From 7f4803580dcf86b02ceb01e2b5bcaf52fb2309a3 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 12:54:13 +0100 Subject: [PATCH 03/52] Use pkg-config to locate GMP headers and libs; add common fallbacks --- src/dynlibs/intinf/Makefile | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/dynlibs/intinf/Makefile b/src/dynlibs/intinf/Makefile index d8beaf02..8559b651 100644 --- a/src/dynlibs/intinf/Makefile +++ b/src/dynlibs/intinf/Makefile @@ -4,10 +4,25 @@ # The GNU GMP multiprecision package must be installed. # Where to find GMP header file and compiled library +# Uses pkg-config if available, otherwise falls back to common default locations. +# Can be overridden: make GMPINCDIR=/path/to/gmp/include GMPLIBDIR=/path/to/gmp/lib -#GMPDIR=${HOME}/c/gmp-2.0.2 -GMPINCDIR=/usr/local/include -GMPLIBDIR=/usr/local/lib +GMPINCDIR ?= $(shell pkg-config --cflags-only-I gmp 2>/dev/null | sed 's/-I//' | xargs) +GMPLIBDIR ?= $(shell pkg-config --libs-only-L gmp 2>/dev/null | sed 's/-L//' | xargs) + +# Fallback to common locations if pkg-config fails +ifeq ($(GMPINCDIR),) + GMPINCDIR ?= $(shell \ + for dir in /opt/homebrew/opt/gmp/include /usr/local/include /usr/include; do \ + [ -f $$dir/gmp.h ] && echo $$dir && break; \ + done) +endif +ifeq ($(GMPLIBDIR),) + GMPLIBDIR ?= $(shell \ + for dir in /opt/homebrew/opt/gmp/lib /usr/local/lib /usr/lib; do \ + [ -f $$dir/libgmp* ] && echo $$dir && break; \ + done) +endif include ../../Makefile.inc From bf1999eeffd274d3cafb1906c1ff1b2bc587261c Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 13:04:01 +0100 Subject: [PATCH 04/52] CI: simplify workflow triggers, reformat job YAML, and upgrade actions/checkout to v5 --- .github/workflows/buildAndTest.yml | 97 ++++++++++++++---------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 4d9c2dd9..93a3b6fe 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -1,57 +1,48 @@ name: Build & Test -on: - pull_request: - - push: - branches: - - master - - devel - +on: [push, pull_request] jobs: - - build-test: - - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - - runs-on: ${{ matrix.os }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update -qq - sudo apt-get install -y binutils build-essential perl libgmp-dev - - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - run: | - brew update - brew install gmp - - - name: Build - run: | - cd src && make world - - - name: Install - run: | - cd src - sudo make install - - - name: Test compiler and runtime system - run: | - cd src/test - make current cleaned - diff cleaned-result cleaned-result.ok - - - name: Test mosmllib - run: | - cd src/mosmllib/test - make current cleaned - diff cleaned-result cleaned-result.ok + build-test: + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update -qq + sudo apt-get install -y binutils build-essential perl libgmp-dev + + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew update + brew install gmp + + - name: Build + run: | + cd src && make world + + - name: Install + run: | + cd src + sudo make install + + - name: Test compiler and runtime system + run: | + cd src/test + make current cleaned + diff cleaned-result cleaned-result.ok + + - name: Test mosmllib + run: | + cd src/mosmllib/test + make current cleaned + diff cleaned-result cleaned-result.ok From 099e5efa101c2535562f438e29a8c448d1bce2e8 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 13:08:07 +0100 Subject: [PATCH 05/52] intinf/Makefile: add more GMP fallback paths and guard -I/-L flags --- src/dynlibs/intinf/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dynlibs/intinf/Makefile b/src/dynlibs/intinf/Makefile index 8559b651..bc9e4c12 100644 --- a/src/dynlibs/intinf/Makefile +++ b/src/dynlibs/intinf/Makefile @@ -13,13 +13,13 @@ GMPLIBDIR ?= $(shell pkg-config --libs-only-L gmp 2>/dev/null | sed 's/-L//' | x # Fallback to common locations if pkg-config fails ifeq ($(GMPINCDIR),) GMPINCDIR ?= $(shell \ - for dir in /opt/homebrew/opt/gmp/include /usr/local/include /usr/include; do \ + for dir in /opt/homebrew/opt/gmp/include /opt/homebrew/include /usr/local/include /usr/include /usr/include/x86_64-linux-gnu; do \ [ -f $$dir/gmp.h ] && echo $$dir && break; \ done) endif ifeq ($(GMPLIBDIR),) GMPLIBDIR ?= $(shell \ - for dir in /opt/homebrew/opt/gmp/lib /usr/local/lib /usr/lib; do \ + for dir in /opt/homebrew/opt/gmp/lib /opt/homebrew/lib /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu; do \ [ -f $$dir/libgmp* ] && echo $$dir && break; \ done) endif @@ -28,7 +28,7 @@ include ../../Makefile.inc #OPTS=-fno-defer-pop ROOTDIR:=../.. -CFLAGS=-Dunix -O3 $(OPTS) $(ADDDYNLIBCFLAGS) -I$(CAMLRT) -I${GMPINCDIR} +CFLAGS=-Dunix -O3 $(OPTS) $(ADDDYNLIBCFLAGS) -I$(CAMLRT) $(if $(GMPINCDIR),-I${GMPINCDIR},) #CFLAGS=-Dunix -O2 $(OPTS) $(ADDDYNLIBCFLAGS) -I$(INCDIR) -I ${GMPDIR} MOSMLTOOLS=camlrunm $(TOOLDIR) @@ -48,7 +48,7 @@ intinf.o: intinf.c $(CC) $(CFLAGS) -c -o intinf.o intinf.c libmgmp.so: intinf.o - $(DYNLD) -o libmgmp.so intinf.o -L$(GMPLIBDIR) -lgmp -lc + $(DYNLD) -o libmgmp.so intinf.o $(if $(GMPLIBDIR),-L$(GMPLIBDIR),) -lgmp -lc test: echo $(CURDIR) From 9cd47f3231e3ff3a1f23e8276080fe989cf0ac74 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 13:15:26 +0100 Subject: [PATCH 06/52] CI: expand build matrix and add macOS arm64 + Windows builds; stage installs, add rlwrap, upload artifacts and create release job --- .github/workflows/buildAndTest.yml | 199 +++++++++++++++++++++++++++-- 1 file changed, 191 insertions(+), 8 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 93a3b6fe..93991490 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -1,12 +1,30 @@ name: Build & Test -on: [push, pull_request] +on: + push: + branches: ["**"] + tags: ["v*.*.*"] + pull_request: + branches: ["**"] + release: + types: [created] jobs: build-test: + name: Build & Test (${{ matrix.os }}) strategy: + fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + platform: linux + arch: x86_64 + - os: macos-latest + platform: macos + arch: x86_64 + - os: macos-14 + platform: macos + arch: arm64 runs-on: ${{ matrix.os }} @@ -15,25 +33,25 @@ jobs: uses: actions/checkout@v5 - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' + if: matrix.platform == 'linux' run: | sudo apt-get update -qq - sudo apt-get install -y binutils build-essential perl libgmp-dev + sudo apt-get install -y binutils build-essential perl libgmp-dev rlwrap - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' + if: matrix.platform == 'macos' run: | brew update - brew install gmp + brew install gmp rlwrap - name: Build run: | cd src && make world - - name: Install + - name: Install to staging directory run: | cd src - sudo make install + make DESTDIR=${{ github.workspace }}/staging PREFIX=/usr/local install - name: Test compiler and runtime system run: | @@ -46,3 +64,168 @@ jobs: cd src/mosmllib/test make current cleaned diff cleaned-result cleaned-result.ok + + - name: Create artifact archive + run: | + cd staging + tar -czf ../mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz usr/local + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: mosml-${{ matrix.platform }}-${{ matrix.arch }} + path: mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz + retention-days: 30 + + build-windows: + name: Build & Test (Windows x86_64) + runs-on: windows-latest + defaults: + run: + shell: msys2 {0} + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + install: >- + base-devel + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-gmp + make + perl + rlwrap + + - name: Build + run: | + cd src + make world + + - name: Install to staging directory + run: | + cd src + mkdir -p ${{ github.workspace }}/staging + make DESTDIR=${{ github.workspace }}/staging PREFIX=/usr/local install + + - name: Test compiler and runtime system + run: | + cd src/test + make current cleaned + diff cleaned-result cleaned-result.ok || true + + - name: Test mosmllib + run: | + cd src/mosmllib/test + make current cleaned + diff cleaned-result cleaned-result.ok || true + + - name: Create artifact archive + run: | + cd staging + tar -czf ../mosml-windows-x86_64.tar.gz usr/local + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: mosml-windows-x86_64 + path: mosml-windows-x86_64.tar.gz + retention-days: 30 + + create-release: + name: Create Release + needs: [build-test, build-windows] + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Display structure of downloaded files + run: ls -R artifacts + + - name: Extract version from tag + id: version + run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + + - name: Create release notes + run: | + cat > release_notes.md << 'EOF' + # Moscow ML ${{ steps.version.outputs.version }} + + This release includes builds for multiple platforms and architectures: + + ## Platform Support + - **Linux (x86_64)**: Full support with rlwrap integration + - **macOS (x86_64)**: Intel-based Macs with rlwrap integration + - **macOS (arm64)**: Apple Silicon (M1/M2/M3) with rlwrap integration + - **Windows (x86_64)**: Windows 10/11 via MSYS2 with rlwrap integration + + ## Features + - Standard ML (SML'97) implementation + - Bytecode compiler and runtime + - Separate compilation support + - Dynamic linking (on supported platforms) + - Interactive REPL with **rlwrap** support for command history and line editing + - Full Standard ML Basis Library + + ## Installation + + ### Linux / macOS + ```bash + # Extract the archive + tar -xzf mosml--.tar.gz + + # Copy to system (requires root) + sudo cp -r usr/local/* /usr/local/ + + # Or install to custom location + tar -xzf mosml--.tar.gz -C $HOME/.local --strip-components=2 + export PATH="$HOME/.local/bin:$PATH" + ``` + + ### Windows (MSYS2) + ```bash + # Extract within MSYS2 environment + tar -xzf mosml-windows-x86_64.tar.gz + cp -r usr/local/* /usr/local/ + ``` + + ## rlwrap Integration + The `mosml` interactive REPL now automatically uses `rlwrap` when available, providing: + - Command history (saved to `~/.mosml_history`) + - Line editing with arrow keys + - Tab completion support + + To disable rlwrap, set the `RLWRAP` environment variable before running mosml. + + ## Documentation + See the [project repository](https://github.com/${{ github.repository }}) for full documentation. + EOF + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + name: Moscow ML ${{ steps.version.outputs.version }} + body_path: release_notes.md + draft: false + prerelease: false + files: | + artifacts/mosml-linux-x86_64/mosml-linux-x86_64.tar.gz + artifacts/mosml-macos-x86_64/mosml-macos-x86_64.tar.gz + artifacts/mosml-macos-arm64/mosml-macos-arm64.tar.gz + artifacts/mosml-windows-x86_64/mosml-windows-x86_64.tar.gz + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 22320ed1da35c836ac945ccc3f209f36e5a98d66 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 13:19:31 +0100 Subject: [PATCH 07/52] CI: adjust install and staging in buildAndTest workflow; run actual installs and create staging for artifacts --- .github/workflows/buildAndTest.yml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 93991490..f69568d5 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -48,10 +48,10 @@ jobs: run: | cd src && make world - - name: Install to staging directory + - name: Install run: | cd src - make DESTDIR=${{ github.workspace }}/staging PREFIX=/usr/local install + sudo make install - name: Test compiler and runtime system run: | @@ -65,6 +65,11 @@ jobs: make current cleaned diff cleaned-result cleaned-result.ok + - name: Create staging directory for artifact + run: | + cd src + make DESTDIR=${{ github.workspace }}/staging PREFIX=/usr/local install + - name: Create artifact archive run: | cd staging @@ -106,11 +111,10 @@ jobs: cd src make world - - name: Install to staging directory + - name: Install run: | cd src - mkdir -p ${{ github.workspace }}/staging - make DESTDIR=${{ github.workspace }}/staging PREFIX=/usr/local install + make install PREFIX=/mingw64 - name: Test compiler and runtime system run: | @@ -124,6 +128,12 @@ jobs: make current cleaned diff cleaned-result cleaned-result.ok || true + - name: Create staging directory for artifact + run: | + cd src + mkdir -p ${{ github.workspace }}/staging + make DESTDIR=${{ github.workspace }}/staging PREFIX=/usr/local install + - name: Create artifact archive run: | cd staging From f50d7d6fa2ca744a76d8b5100e0afebb004e083c Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Wed, 5 Nov 2025 15:35:42 +0100 Subject: [PATCH 08/52] CI: remove Windows build job and stop installing gmp on macOS - Drop the build-windows (MSYS2) job and related artifact upload - Remove Windows entries from release notes and release artifact list - Update create-release dependency to only require build-test - macOS dependency step no longer installs gmp (install rlwrap only) --- .github/workflows/buildAndTest.yml | 77 +----------------------------- 1 file changed, 2 insertions(+), 75 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index f69568d5..3986ec6c 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -42,7 +42,7 @@ jobs: if: matrix.platform == 'macos' run: | brew update - brew install gmp rlwrap + brew install rlwrap - name: Build run: | @@ -82,73 +82,9 @@ jobs: path: mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz retention-days: 30 - build-windows: - name: Build & Test (Windows x86_64) - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} - - steps: - - name: Checkout - uses: actions/checkout@v5 - - - name: Setup MSYS2 - uses: msys2/setup-msys2@v2 - with: - msystem: MINGW64 - update: true - install: >- - base-devel - mingw-w64-x86_64-toolchain - mingw-w64-x86_64-gmp - make - perl - rlwrap - - - name: Build - run: | - cd src - make world - - - name: Install - run: | - cd src - make install PREFIX=/mingw64 - - - name: Test compiler and runtime system - run: | - cd src/test - make current cleaned - diff cleaned-result cleaned-result.ok || true - - - name: Test mosmllib - run: | - cd src/mosmllib/test - make current cleaned - diff cleaned-result cleaned-result.ok || true - - - name: Create staging directory for artifact - run: | - cd src - mkdir -p ${{ github.workspace }}/staging - make DESTDIR=${{ github.workspace }}/staging PREFIX=/usr/local install - - - name: Create artifact archive - run: | - cd staging - tar -czf ../mosml-windows-x86_64.tar.gz usr/local - - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - name: mosml-windows-x86_64 - path: mosml-windows-x86_64.tar.gz - retention-days: 30 - create-release: name: Create Release - needs: [build-test, build-windows] + needs: [build-test] if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: @@ -181,7 +117,6 @@ jobs: - **Linux (x86_64)**: Full support with rlwrap integration - **macOS (x86_64)**: Intel-based Macs with rlwrap integration - **macOS (arm64)**: Apple Silicon (M1/M2/M3) with rlwrap integration - - **Windows (x86_64)**: Windows 10/11 via MSYS2 with rlwrap integration ## Features - Standard ML (SML'97) implementation @@ -206,13 +141,6 @@ jobs: export PATH="$HOME/.local/bin:$PATH" ``` - ### Windows (MSYS2) - ```bash - # Extract within MSYS2 environment - tar -xzf mosml-windows-x86_64.tar.gz - cp -r usr/local/* /usr/local/ - ``` - ## rlwrap Integration The `mosml` interactive REPL now automatically uses `rlwrap` when available, providing: - Command history (saved to `~/.mosml_history`) @@ -236,6 +164,5 @@ jobs: artifacts/mosml-linux-x86_64/mosml-linux-x86_64.tar.gz artifacts/mosml-macos-x86_64/mosml-macos-x86_64.tar.gz artifacts/mosml-macos-arm64/mosml-macos-arm64.tar.gz - artifacts/mosml-windows-x86_64/mosml-windows-x86_64.tar.gz env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1eb94fef52e4b736549e84386018e770af2f3c84 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 18:06:03 +0100 Subject: [PATCH 09/52] src/Makefile.inc: use i686-w64-mingw32-gcc for Cross_W32 cross-compiler --- src/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.inc b/src/Makefile.inc index 6f8cf3e1..deaf2a74 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -78,7 +78,7 @@ ifeq ($(UNAME_S),Darwin) # For MacOS X, use the same as Linux except DYNDL DYNLD=$(LD) -bundle -undefined dynamic_lookup endif ifeq ($(UNAME_S),Cross_W32) - CC=i586-mingw32msvc-gcc + CC=i686-w64-mingw32-gcc CPP=cpp -P -traditional -Umsdos -Uunix -Dwin32 -Wno-invalid-pp-token ADDRUNLIBS= ADDRUNCFLAGS= From 8d0dc46168e18ac459a79294934dd85d0ec2575e Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 18:11:07 +0100 Subject: [PATCH 10/52] CI: add mingw-w64 and Windows cross-build/upload to buildAndTest workflow --- .github/workflows/buildAndTest.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 3986ec6c..284f1480 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -36,7 +36,7 @@ jobs: if: matrix.platform == 'linux' run: | sudo apt-get update -qq - sudo apt-get install -y binutils build-essential perl libgmp-dev rlwrap + sudo apt-get install -y binutils build-essential perl libgmp-dev rlwrap mingw-w64 - name: Install dependencies (macOS) if: matrix.platform == 'macos' @@ -75,6 +75,14 @@ jobs: cd staging tar -czf ../mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz usr/local + - name: Cross-compile Windows binaries (on Linux) + if: matrix.platform == 'linux' + run: | + mkdir -p win-root + (cd src && make DESTDIR=`pwd`/../win-root PREFIX=/mosml cross_w32) + cd win-root + zip -r ../mosml-windows-x86_64.zip mosml + - name: Upload build artifacts uses: actions/upload-artifact@v4 with: @@ -82,6 +90,14 @@ jobs: path: mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz retention-days: 30 + - name: Upload Windows build artifact + if: matrix.platform == 'linux' + uses: actions/upload-artifact@v4 + with: + name: mosml-windows-x86_64 + path: mosml-windows-x86_64.zip + retention-days: 30 + create-release: name: Create Release needs: [build-test] @@ -164,5 +180,6 @@ jobs: artifacts/mosml-linux-x86_64/mosml-linux-x86_64.tar.gz artifacts/mosml-macos-x86_64/mosml-macos-x86_64.tar.gz artifacts/mosml-macos-arm64/mosml-macos-arm64.tar.gz + artifacts/mosml-windows-x86_64/mosml-windows-x86_64.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From f56f03c9945135e4acb2855d33be5482b700c0c4 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 18:34:34 +0100 Subject: [PATCH 11/52] fix: improve rlwrap availability check and warning messages --- src/launch/mosml.tpl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/launch/mosml.tpl b/src/launch/mosml.tpl index 4e9fa7cb..63bbaae5 100755 --- a/src/launch/mosml.tpl +++ b/src/launch/mosml.tpl @@ -9,6 +9,10 @@ options="-conservative" use_rlwrap="" if [ -t 0 ] && command -v rlwrap >/dev/null 2>&1; then use_rlwrap="rlwrap -a -N -H $HOME/.mosml_history -s 1000" +else + echo "Warning: rlwrap not found or input is not a terminal; running without rlwrap." >&2 + echo "For better command line editing, consider installing rlwrap." >&2 + use_rlwrap="" fi # Disable rlwrap if RLWRAP environment variable is already set From 7137318f37391310ae73778c8cdd99305616df16 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 21:26:45 +0100 Subject: [PATCH 12/52] chore: update .gitignore to include comprehensive file patterns for build artifacts and temporary files --- .gitignore | 475 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) diff --git a/.gitignore b/.gitignore index 50cf6ded..7c4c5393 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,476 @@ /config + +# Build artifacts +*.o +*.a +*.so +*.dylib +*.uo +*.ui + +# Compiled binaries +camlrunm +mosmlcmp +mosmllnk +mosmllex +mosmlyac + +# Runtime/build folders +staging/ +win-root/ + +# Editor and OS files +.DS_Store +*.swp +*~ + +# Temporary docs/examples not required for builds +doc/ +examples/ + +# Created by https://www.toptal.com/developers/gitignore/api/linux,macos,windows,c,standardml,latex +# Edit at https://www.toptal.com/developers/gitignore?templates=linux,macos,windows,c,standardml,latex + +### C ### +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +### LaTeX ### +## Core latex/pdflatex auxiliary files: +*.aux +*.lof +*.log +*.lot +*.fls +*.toc +*.fmt +*.fot +*.cb +*.cb2 +.*.lb + +## Intermediate documents: +*.dvi +*.xdv +*-converted-to.* +# these rules might exclude image files for figures etc. +# *.ps +# *.eps +# *.pdf + +## Generated if empty string is given at "Please type another file name for output:" +.pdf + +## Bibliography auxiliary files (bibtex/biblatex/biber): +*.bbl +*.bcf +*.blg +*-blx.aux +*-blx.bib +*.run.xml + +## Build tool auxiliary files: +*.fdb_latexmk +*.synctex +*.synctex(busy) +*.synctex.gz +*.synctex.gz(busy) +*.pdfsync + +## Build tool directories for auxiliary files +# latexrun +latex.out/ + +## Auxiliary and intermediate files from other packages: +# algorithms +*.alg +*.loa + +# achemso +acs-*.bib + +# amsthm +*.thm + +# beamer +*.nav +*.pre +*.snm +*.vrb + +# changes +*.soc + +# comment +*.cut + +# cprotect +*.cpt + +# elsarticle (documentclass of Elsevier journals) +*.spl + +# endnotes +*.ent + +# fixme +*.lox + +# feynmf/feynmp +*.mf +*.mp +*.t[1-9] +*.t[1-9][0-9] +*.tfm + +#(r)(e)ledmac/(r)(e)ledpar +*.end +*.?end +*.[1-9] +*.[1-9][0-9] +*.[1-9][0-9][0-9] +*.[1-9]R +*.[1-9][0-9]R +*.[1-9][0-9][0-9]R +*.eledsec[1-9] +*.eledsec[1-9]R +*.eledsec[1-9][0-9] +*.eledsec[1-9][0-9]R +*.eledsec[1-9][0-9][0-9] +*.eledsec[1-9][0-9][0-9]R + +# glossaries +*.acn +*.acr +*.glg +*.glo +*.gls +*.glsdefs +*.lzo +*.lzs +*.slg +*.slo +*.sls + +# uncomment this for glossaries-extra (will ignore makeindex's style files!) +# *.ist + +# gnuplot +*.gnuplot +*.table + +# gnuplottex +*-gnuplottex-* + +# gregoriotex +*.gaux +*.glog +*.gtex + +# htlatex +*.4ct +*.4tc +*.idv +*.lg +*.trc +*.xref + +# hyperref +*.brf + +# knitr +*-concordance.tex +# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files +# *.tikz +*-tikzDictionary + +# listings +*.lol + +# luatexja-ruby +*.ltjruby + +# makeidx +*.idx +*.ilg +*.ind + +# minitoc +*.maf +*.mlf +*.mlt +*.mtc[0-9]* +*.slf[0-9]* +*.slt[0-9]* +*.stc[0-9]* + +# minted +_minted* +*.pyg + +# morewrites +*.mw + +# newpax +*.newpax + +# nomencl +*.nlg +*.nlo +*.nls + +# pax +*.pax + +# pdfpcnotes +*.pdfpc + +# sagetex +*.sagetex.sage +*.sagetex.py +*.sagetex.scmd + +# scrwfile +*.wrt + +# svg +svg-inkscape/ + +# sympy +*.sout +*.sympy +sympy-plots-for-*.tex/ + +# pdfcomment +*.upa +*.upb + +# pythontex +*.pytxcode +pythontex-files-*/ + +# tcolorbox +*.listing + +# thmtools +*.loe + +# TikZ & PGF +*.dpth +*.md5 +*.auxlock + +# titletoc +*.ptc + +# todonotes +*.tdo + +# vhistory +*.hst +*.ver + +# easy-todo +*.lod + +# xcolor +*.xcp + +# xmpincl +*.xmpi + +# xindy +*.xdy + +# xypic precompiled matrices and outlines +*.xyc +*.xyd + +# endfloat +*.ttt +*.fff + +# Latexian +TSWLatexianTemp* + +## Editors: +# WinEdt +*.bak +*.sav + +# Texpad +.texpadtmp + +# LyX +*.lyx~ + +# Kile +*.backup + +# gummi +.*.swp + +# KBibTeX +*~[0-9]* + +# TeXnicCenter +*.tps + +# auto folder when using emacs and auctex +./auto/* +*.el + +# expex forward references with \gathertags +*-tags.tex + +# standalone packages +*.sta + +# Makeindex log files +*.lpz + +# xwatermark package +*.xwm + +# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib +# option is specified. Footnotes are the stored in a file with suffix Notes.bib. +# Uncomment the next line to have this generated file ignored. +#*Notes.bib + +### LaTeX Patch ### +# LIPIcs / OASIcs +*.vtc + +# glossaries +*.glstex + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### StandardML ### +## Ignore all SML/NJ Compiler Manager build directories +.cm/ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/linux,macos,windows,c,standardml,latex + From da7d01277ed15411ba14e3ea3481868ae51489d2 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 21:27:06 +0100 Subject: [PATCH 13/52] feat: add Dockerfile and docker-compose configuration for building and running Moscow ML --- .dockerignore | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ compose.yml | 15 +++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..71eaf3b4 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,52 @@ +# Build artifacts +*.o +*.a +*.so +*.dylib +*.uo +*.ui +camlrunm +mosmlcmp +mosmllnk +mosmllex +mosmlyac + +# Binaries (top-level names only) +camlrunm +mosmlcmp +mosmllnk +mosmllex +mosmlyac +mosmldep +cutdeps + +# Generated files +src/compiler/Parser.sig +src/compiler/Parser.sml +src/compiler/Lexer.sml +src/compiler/Opcodes.sml +src/compiler/Predef.sml +src/compiler/Prim_c.sml +src/runtime/primitives +src/config/m.h +src/config/s.h + +# Build directories +bin/ +lib/ +include/ + +# OS files +.DS_Store +.git +.github +*.swp +*~ + +# Documentation and examples (not needed for build) +doc/ +examples/ + +# Staging and install directories +staging/ +win-root/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..0ca33885 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,51 @@ +# Build stage - compile Moscow ML from source +FROM --platform=linux/amd64 ubuntu:22.04 AS builder + +ENV DEBIAN_FRONTEND=noninteractive + +# Install build dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + binutils \ + build-essential \ + ca-certificates \ + libgmp-dev \ + perl && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Copy source code +COPY . /mosml-src + +# Build Moscow ML +WORKDIR /mosml-src/src +RUN make world && \ + make DESTDIR=/mosml-install PREFIX=/usr/local install + +# Runtime stage - minimal image with only runtime dependencies +FROM --platform=linux/amd64 ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive + +# Install runtime dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + libc6 \ + libgmp10 \ + rlwrap && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Copy installed Moscow ML from builder +COPY --from=builder /mosml-install/usr/local /usr/local + +# Create workspace directory +WORKDIR /workspace + +# Add labels +LABEL org.opencontainers.image.title="Moscow ML" +LABEL org.opencontainers.image.description="Moscow ML is a light-weight implementation of Standard ML (SML), a strict functional language widely used in teaching and research." +LABEL org.opencontainers.image.source="https://github.com/Francesco146/mosml" + +# Default command is interactive REPL +ENTRYPOINT ["mosml"] diff --git a/compose.yml b/compose.yml new file mode 100644 index 00000000..5a69baee --- /dev/null +++ b/compose.yml @@ -0,0 +1,15 @@ +services: + mosml: + image: ghcr.io/francesco146/mosml:latest + build: + context: . + dockerfile: Dockerfile + tags: + - mosml:latest + - ghcr.io/francesco146/mosml:latest + platform: linux/amd64 # needed for Apple Silicon Macs + volumes: + - ./container-shared-dir:/workspace + container_name: mosml + stdin_open: true + tty: true From aaf1e54a50c4ea905c44d187a353401c3c2d1708 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 21:27:22 +0100 Subject: [PATCH 14/52] feat: add GitHub Actions workflow for Docker build and push --- .github/workflows/docker.yml | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/docker.yml diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..d5731403 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,64 @@ +name: Docker Build and Push + +on: + push: + branches: ["**"] + tags: ["v*.*.*"] + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + name: Build and Push Docker Image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Log in to Docker Hub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + docker.io/${{ secrets.DOCKERHUB_USERNAME }}/mosml + tags: | + type=raw,value=latest + type=semver,pattern={{version}} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max From ca079408b747ed20fa60e4b1aa0eacc1ea454c1d Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 22:08:56 +0100 Subject: [PATCH 15/52] fix: in docker rlwrap didn't work --- src/launch/mosml.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/launch/mosml.tpl b/src/launch/mosml.tpl index 63bbaae5..61791ae0 100755 --- a/src/launch/mosml.tpl +++ b/src/launch/mosml.tpl @@ -8,7 +8,7 @@ options="-conservative" # Check if rlwrap is available and stdin is a terminal use_rlwrap="" if [ -t 0 ] && command -v rlwrap >/dev/null 2>&1; then - use_rlwrap="rlwrap -a -N -H $HOME/.mosml_history -s 1000" + use_rlwrap="rlwrap -a -H $HOME/.mosml_history -s 1000" else echo "Warning: rlwrap not found or input is not a terminal; running without rlwrap." >&2 echo "For better command line editing, consider installing rlwrap." >&2 From 560a209ff344acdcf94467e64bb98ab9668f7f67 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 22:50:12 +0100 Subject: [PATCH 16/52] fix: streamline clean commands in Makefile for better readability --- src/Makefile | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Makefile b/src/Makefile index f2a545e7..1dc254ca 100644 --- a/src/Makefile +++ b/src/Makefile @@ -134,20 +134,20 @@ basisdynlib_uninstall: # Remove all generated files clean: - cd config; $(MAKE) clean - cd runtime; $(MAKE) clean - cd launch; $(MAKE) clean - cd mosmlyac; $(MAKE) clean - cd mosmllib; $(MAKE) clean - cd compiler; $(MAKE) clean - cd toolssrc; $(MAKE) clean - cd lex; $(MAKE) clean - cd test; $(MAKE) clean - cd mosmllib/test; $(MAKE) clean - cd ../examples; $(MAKE) clean - cd dynlibs; $(MAKE) clean + cd config && $(MAKE) clean + cd runtime && $(MAKE) clean + cd launch && $(MAKE) clean + cd mosmlyac && $(MAKE) clean + cd mosmllib && $(MAKE) clean + cd compiler && $(MAKE) clean + cd toolssrc && $(MAKE) clean + cd lex && $(MAKE) clean + cd test && $(MAKE) clean + cd mosmllib/test && $(MAKE) clean + (cd ../examples && $(MAKE) clean) + cd dynlibs && $(MAKE) clean rm -f camlrunm$(EXE) - cd doc; $(MAKE) clean + cd doc && $(MAKE) clean dynlibs: cd dynlibs; $(MAKE) From 400b4db2d5a0dbba5812965bc29412828da31620 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 22:50:59 +0100 Subject: [PATCH 17/52] feat: update history file location in mosml.tpl to respect XDG Base Directory spec --- compose.yml | 2 ++ src/launch/mosml.tpl | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/compose.yml b/compose.yml index 5a69baee..380b8512 100644 --- a/compose.yml +++ b/compose.yml @@ -8,6 +8,8 @@ services: - mosml:latest - ghcr.io/francesco146/mosml:latest platform: linux/amd64 # needed for Apple Silicon Macs + environment: + - XDG_DATA_HOME=/workspace/.local/share volumes: - ./container-shared-dir:/workspace container_name: mosml diff --git a/src/launch/mosml.tpl b/src/launch/mosml.tpl index 61791ae0..cb045c67 100755 --- a/src/launch/mosml.tpl +++ b/src/launch/mosml.tpl @@ -5,10 +5,21 @@ mosmlbin=BINDIR includes="" options="-conservative" +# Determine history file location (respects XDG Base Directory spec, falls back to HOME) +if [ -n "$XDG_DATA_HOME" ]; then + history_file="$XDG_DATA_HOME/mosml/history" +else + # macOS, Windows (MSYS/Git Bash), and systems without XDG + history_file="$HOME/.local/share/mosml/history" +fi + +# Create history directory if possible (ignore errors gracefully) +mkdir -p "$(dirname "$history_file")" 2>/dev/null || true + # Check if rlwrap is available and stdin is a terminal use_rlwrap="" if [ -t 0 ] && command -v rlwrap >/dev/null 2>&1; then - use_rlwrap="rlwrap -a -H $HOME/.mosml_history -s 1000" + use_rlwrap="rlwrap -a -H $history_file -s 1000" else echo "Warning: rlwrap not found or input is not a terminal; running without rlwrap." >&2 echo "For better command line editing, consider installing rlwrap." >&2 From 1650950f4724aa18d48ac977bfebef9d2b0029e7 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 22:51:06 +0100 Subject: [PATCH 18/52] fix: add docker shared volumes to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7c4c5393..d975d48d 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,9 @@ win-root/ doc/ examples/ +# docker shared volumes +container-shared-dir + # Created by https://www.toptal.com/developers/gitignore/api/linux,macos,windows,c,standardml,latex # Edit at https://www.toptal.com/developers/gitignore?templates=linux,macos,windows,c,standardml,latex From 5e775ed8590004bf213e68ff49b2c9124485543f Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 22:51:14 +0100 Subject: [PATCH 19/52] fix: add clean step before building Moscow ML in Dockerfile --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0ca33885..cbd8973b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,8 @@ COPY . /mosml-src # Build Moscow ML WORKDIR /mosml-src/src -RUN make world && \ +RUN make clean && \ + make world && \ make DESTDIR=/mosml-install PREFIX=/usr/local install # Runtime stage - minimal image with only runtime dependencies From 0d0641213477a5bf7ae0a3adf85b49bda74f8ed6 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 22:54:58 +0100 Subject: [PATCH 20/52] feat: add Windows build support and update rlwrap integration documentation --- .github/workflows/buildAndTest.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 284f1480..f57205d0 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -133,6 +133,7 @@ jobs: - **Linux (x86_64)**: Full support with rlwrap integration - **macOS (x86_64)**: Intel-based Macs with rlwrap integration - **macOS (arm64)**: Apple Silicon (M1/M2/M3) with rlwrap integration + - **Windows (x86_64)**: Native Windows build ## Features - Standard ML (SML'97) implementation @@ -159,7 +160,7 @@ jobs: ## rlwrap Integration The `mosml` interactive REPL now automatically uses `rlwrap` when available, providing: - - Command history (saved to `~/.mosml_history`) + - Command history (saved to $XDG_DATA_HOME/mosml/history or $HOME/.local/share/mosml/history, if XDG_DATA_HOME is not set) - Line editing with arrow keys - Tab completion support From 4ca2e18c6d41522268735c6e6511db7d8c0b19d0 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 7 Nov 2025 23:01:27 +0100 Subject: [PATCH 21/52] fix(Makefile): ignore missing dirs in clean --- src/Makefile | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Makefile b/src/Makefile index 1dc254ca..27e6129d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -134,20 +134,20 @@ basisdynlib_uninstall: # Remove all generated files clean: - cd config && $(MAKE) clean - cd runtime && $(MAKE) clean - cd launch && $(MAKE) clean - cd mosmlyac && $(MAKE) clean - cd mosmllib && $(MAKE) clean - cd compiler && $(MAKE) clean - cd toolssrc && $(MAKE) clean - cd lex && $(MAKE) clean - cd test && $(MAKE) clean - cd mosmllib/test && $(MAKE) clean - (cd ../examples && $(MAKE) clean) - cd dynlibs && $(MAKE) clean - rm -f camlrunm$(EXE) - cd doc && $(MAKE) clean + -cd config && $(MAKE) clean + -cd runtime && $(MAKE) clean + -cd launch && $(MAKE) clean + -cd mosmlyac && $(MAKE) clean + -cd mosmllib && $(MAKE) clean + -cd compiler && $(MAKE) clean + -cd toolssrc && $(MAKE) clean + -cd lex && $(MAKE) clean + -cd test && $(MAKE) clean + -cd mosmllib/test && $(MAKE) clean + -(cd ../examples && $(MAKE) clean) + -cd dynlibs && $(MAKE) clean + -rm -f camlrunm$(EXE) + -cd doc && $(MAKE) clean dynlibs: cd dynlibs; $(MAKE) From f3dd0b58eb991fd657c2ea8becb4feebd2012c49 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Sat, 8 Nov 2025 10:17:50 +0100 Subject: [PATCH 22/52] fix: add clean step for cross compilation and support for Windows installation of mosmllex --- src/Makefile | 3 ++- src/lex/Makefile | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 27e6129d..e533951c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,6 +35,7 @@ world: # Cross compilation to Win cross_w32: + cd runtime; $(MAKE) clean cd config; $(MAKE) all cd runtime; $(MAKE) all cp runtime/camlrunm$(EXE) . @@ -61,7 +62,7 @@ cross_w32: $(MAKE) -C mosmllib UNAME_S=Cross_W32 install $(MAKE) -C compiler UNAME_S=Cross_W32 install_w32 $(MAKE) -C toolssrc UNAME_S=Cross_W32 install - $(MAKE) -C lex UNAME_S=Cross_W32 install + $(MAKE) -C lex UNAME_S=Cross_W32 install_w32 $(MAKE) -C launch.w32 UNAME_S=Cross_W32 install $(MAKE) -C doc install $(INSTALL_DATA) ../install.txt.w32 $(DESTDIR)$(PREFIX) diff --git a/src/lex/Makefile b/src/lex/Makefile index 2ec4ab21..eca1d487 100644 --- a/src/lex/Makefile +++ b/src/lex/Makefile @@ -39,6 +39,10 @@ clean: install: ${INSTALL_DATA} mosmllex $(DESTDIR)$(LIBDIR) +install_w32: + cat ../launch.w32/header.exe mosmllex > $(DESTDIR)$(BINDIR)/mosmllex.exe + chmod a+x $(DESTDIR)$(BINDIR)/mosmllex.exe + uninstall: ${UNINSTALL_DATA} $(DESTDIR)$(LIBDIR)/mosmllex From d4ec2061ca79bca80e8667450970be89ad689b13 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Sat, 8 Nov 2025 15:30:04 +0100 Subject: [PATCH 23/52] fix: update installation instructions for MOSML to set correct mosmllib path --- install.txt.w32 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.txt.w32 b/install.txt.w32 index 9631845a..62505852 100644 --- a/install.txt.w32 +++ b/install.txt.w32 @@ -30,13 +30,13 @@ INSTALLING MOSCOW ML (BINARIES ONLY) UNDER WINDOWS 95/98/ME/NT/2000/XP/?? tools/ mosmldep, Makefile.stub (2) Add C:\mosml\bin to the PATH variable, and set the environment - variable `mosmllib' to C:\mosml\lib. + variable `mosmllib' to C:\mosml\lib\mosml. (a) In the case of Windows 95/98/ME your AUTOEXEC.BAT file should contain something like: set PATH=C:\dos; ... ;C:\mosml\bin - set MOSMLLIB=C:\mosml\lib + set MOSMLLIB=C:\mosml\lib\mosml The system must be rebooted to enable the new environment variables. @@ -44,7 +44,7 @@ INSTALLING MOSCOW ML (BINARIES ONLY) UNDER WINDOWS 95/98/ME/NT/2000/XP/?? (b) In the case of Windows NT/2000/XP, choose Start | Settings | Control Panel | System | Advanced | Environment Variables | System Variables | New - Enter MOSMLLIB as Variable Name and C:\mosml\lib as Variable Value. + Enter MOSMLLIB as Variable Name and C:\mosml\lib\mosml as Variable Value. Double-click on Path and add ;C:\mosml\bin to the Variable Value. (3) Start Moscow ML by entering the command line From 95cf012bdd711ba98733606446fbb948a0f0bdd1 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Sun, 9 Nov 2025 21:14:18 +0100 Subject: [PATCH 24/52] revert: update Windows cross-compilation compiler to use i586-mingw32msvc-gcc --- src/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.inc b/src/Makefile.inc index deaf2a74..6f8cf3e1 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -78,7 +78,7 @@ ifeq ($(UNAME_S),Darwin) # For MacOS X, use the same as Linux except DYNDL DYNLD=$(LD) -bundle -undefined dynamic_lookup endif ifeq ($(UNAME_S),Cross_W32) - CC=i686-w64-mingw32-gcc + CC=i586-mingw32msvc-gcc CPP=cpp -P -traditional -Umsdos -Uunix -Dwin32 -Wno-invalid-pp-token ADDRUNLIBS= ADDRUNCFLAGS= From 42692ce29848eaa77ef1a30c55d49f7e52e5bd83 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Sun, 9 Nov 2025 21:14:26 +0100 Subject: [PATCH 25/52] fix: remove unnecessary clean step in cross compilation for Windows --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index e533951c..5f6d29e0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,7 +35,6 @@ world: # Cross compilation to Win cross_w32: - cd runtime; $(MAKE) clean cd config; $(MAKE) all cd runtime; $(MAKE) all cp runtime/camlrunm$(EXE) . From 6281577a1bbee3c8be7538245ee2d12ff3350fdd Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Thu, 13 Nov 2025 10:51:25 +0100 Subject: [PATCH 26/52] fix: improve quoting in build script for Windows cross-compilation --- .github/workflows/buildAndTest.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index f57205d0..bd5d6faa 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -79,7 +79,7 @@ jobs: if: matrix.platform == 'linux' run: | mkdir -p win-root - (cd src && make DESTDIR=`pwd`/../win-root PREFIX=/mosml cross_w32) + (cd src && make DESTDIR="$(pwd)/../win-root" PREFIX=/mosml cross_w32) cd win-root zip -r ../mosml-windows-x86_64.zip mosml @@ -120,7 +120,7 @@ jobs: - name: Extract version from tag id: version - run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" - name: Create release notes run: | From 73125f314c3ae847f83bcfd8cc356c381adf4a71 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Thu, 13 Nov 2025 10:51:45 +0100 Subject: [PATCH 27/52] fix: update GMP library directory check to use 'ls' for better compatibility --- src/dynlibs/intinf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynlibs/intinf/Makefile b/src/dynlibs/intinf/Makefile index bc9e4c12..82d358c0 100644 --- a/src/dynlibs/intinf/Makefile +++ b/src/dynlibs/intinf/Makefile @@ -20,7 +20,7 @@ endif ifeq ($(GMPLIBDIR),) GMPLIBDIR ?= $(shell \ for dir in /opt/homebrew/opt/gmp/lib /opt/homebrew/lib /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu; do \ - [ -f $$dir/libgmp* ] && echo $$dir && break; \ + ls "$$dir"/libgmp* > /dev/null 2>&1 && echo "$$dir" && break; \ done) endif From 6221287f690a785708dad483c57f57175436da04 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Thu, 13 Nov 2025 10:52:50 +0100 Subject: [PATCH 28/52] fix: correct typos in README for building Windows installer --- src/tools/installer/README.inno | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/installer/README.inno b/src/tools/installer/README.inno index 2a7aa4f2..6445b2d4 100644 --- a/src/tools/installer/README.inno +++ b/src/tools/installer/README.inno @@ -16,7 +16,7 @@ Current status of the resulting installer is: How to build an installer step by step: --------------------------------------- -1. Prepare a binary distrubution of mosml (ie. cross-compile everything) +1. Prepare a binary distribution of mosml (ie. cross-compile everything) 2. Place binary distribution in "mosml" subdirectory. @@ -24,4 +24,4 @@ How to build an installer step by step: 4. Run Inno Setup on mosml.iss -5. The installer can now be found the directory "Output" +5. The installer can now be found in the directory "Output" From 7f8456a050bfac19f06dc1b2860c3e8da2ba5625 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Thu, 13 Nov 2025 10:56:40 +0100 Subject: [PATCH 29/52] fix: update Inno Setup script for Moscow ML version 2.10.5 and add Italian translations --- src/tools/installer/mosml.iss | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/tools/installer/mosml.iss b/src/tools/installer/mosml.iss index b28a3253..4287e20f 100644 --- a/src/tools/installer/mosml.iss +++ b/src/tools/installer/mosml.iss @@ -1,30 +1,30 @@ -; Inno Setup script for Moscow ML ver. 2.10.1 +; Inno Setup script for Moscow ML ver. 2.10.5 [Setup] AppId={{A34767A0-A549-48AB-90BB-F460DA36ED51} AppName=Moscow ML -AppVersion=2.10.1 -AppVerName=Moscow ML version 2.10.1 +AppVersion=2.10.5 +AppVerName=Moscow ML version 2.10.5 AppPublisherURL=http://mosml.org AppSupportURL=https://github.com/kfl/mosml/issues -AppUpdatesURL=http://mosml.org +AppUpdatesURL=https://github.com/kfl/mosml/releases DefaultDirName={pf}\mosml DefaultGroupName=Moscow ML -OutputBaseFilename=mosml-setup-2.10.1 +OutputBaseFilename=mosml-setup-2.10.5 Compression=lzma SolidCompression=yes ChangesEnvironment=yes [Languages] Name: "da"; MessagesFile: "compiler:Languages\Danish.isl" +Name: "it"; MessagesFile: "compiler:Languages\Italian.isl" Name: "en"; MessagesFile: "compiler:Default.isl" [Files] Source: "mosml\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: mosml [Components] -Name: "mosml"; Description: "Moscow ML v2.10.1"; Flags: fixed; Types: full custom - +Name: "mosml"; Description: "Moscow ML v2.10.5"; Flags: fixed; Types: full custom [Types] Name: "full"; Description: "{cm:FullInstall}" Name: "custom"; Description: "{cm:CustomInstall}"; Flags: iscustom @@ -44,34 +44,47 @@ Name: "{commondesktop}\{cm:MosMLName}"; Filename: "{app}\bin\mosml.exe"; Paramet [CustomMessages] en.FullInstall=Full installation da.FullInstall=Fuld installation +it.FullInstall=Installazione completa en.CustomInstall=Custom installation da.CustomInstall=Brugerdefineret installation +it.CustomInstall=Installazione personalizzata en.StartMenu=Create Start Menu shortcuts da.StartMenu=Lav genveje i startmenuen +it.StartMenu=Crea collegamenti nel menu Start en.DesktopIcon=Create shortcuts on your desktop -da.DesktopIcon=Lav genveje på skrivebordet +da.DesktopIcon=Lav genveje pÃ¥ skrivebordet +it.DesktopIcon=Crea collegamenti sul desktop en.MosMLName=Moscow ML Commandline da.MosMLName=Moscow ML Kommandolinje +it.MosMLName=Moscow ML da riga di comando en.UninstallProgram=Uninstall %1 -da.UninstallProgram=Afinstallér %1 +da.UninstallProgram=Afinstaller %1 +it.UninstallProgram=Disinstalla %1 en.Documentation=Documentation da.Documentation=Dokumentation +it.Documentation=Documentazione en.OwnersManual=Moscow ML Owner's Manual da.OwnersManual=Moscow ML Owner's Manual +it.OwnersManual=Manuale dell'utente di Moscow ML en.LibraryDocs=Moscow ML Library da.LibraryDocs=Moscow ML Library +it.LibraryDocs=Libreria di Moscow ML en.LanguageOverview=Moscow ML Language Overview da.LanguageOverview=Moscow ML Language Overview +it.LanguageOverview=Panoramica del linguaggio Moscow ML en.Updating=Updating %1... da.Updating=Opdaterer %1... +it.Updating=Aggiornamento di %1... en.Setting=Setting %1... -da.Setting=Sætter %1... -da.Deleting=Sletter %1... +da.Setting=Sætter %1... +it.Setting=Impostazione di %1... en.Deleting=Deleting %1... +da.Deleting=Sletter %1... +it.Deleting=Cancellazione di %1... [Registry] Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\bin"; Flags: preservestringtype; Components: mosml From 335d786644ac7878f1b777f0500a6e0247f71e05 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 12:54:47 +0100 Subject: [PATCH 30/52] feat: add Dockerfile and build script for cross-compilation of Windows binaries --- Dockerfile.w32 | 40 +++++++++++++ build-win.sh | 159 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 Dockerfile.w32 create mode 100644 build-win.sh diff --git a/Dockerfile.w32 b/Dockerfile.w32 new file mode 100644 index 00000000..1f8a3f94 --- /dev/null +++ b/Dockerfile.w32 @@ -0,0 +1,40 @@ +# This Dockerfile sets up a cross-compilation environment for building Windows (win32) binaries +# on an Ubuntu 14.04 (Trusty) base image using the i386 architecture. +# Hopefully this will work in the future, i had no luck compiling on amd64 ubuntu images. + +FROM --platform=linux/386 ubuntu:14.04 + +RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty main restricted universe multiverse" > /etc/apt/sources.list && \ + echo "deb http://archive.ubuntu.com/ubuntu/ trusty-updates main restricted universe multiverse" >> /etc/apt/sources.list && \ + echo "deb http://archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse" >> /etc/apt/sources.list && \ + echo "deb http://security.ubuntu.com/ubuntu trusty-security main restricted universe multiverse" >> /etc/apt/sources.list && \ + apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y \ + binutils \ + build-essential \ + libgmp-dev \ + make \ + mingw32 \ + mingw32-binutils \ + mingw32-runtime \ + perl \ + unzip \ + zip \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +ENV CC=gcc \ + PATH=/usr/bin:${PATH} + +COPY . /mosml +WORKDIR /mosml + +COPY build-win.sh /usr/local/bin/build-win.sh +RUN chmod +x /usr/local/bin/build-win.sh + +# Build: docker build -t mosml-win-builder --platform=linux/386 -f Dockerfile.w32 . +# When running the container, mount a host directory on /out to receive the zip. +# Example (fish shell): docker run --rm -v (pwd)/out:/out mosml-win-builder +# Example (bash/zsh): docker run --rm -v $(pwd)/out:/out mosml-win-builder +# Example (PowerShell): docker run --rm -v ${PWD}/out:/out mosml-win-builder +ENTRYPOINT ["/usr/local/bin/build-win.sh"] diff --git a/build-win.sh b/build-win.sh new file mode 100644 index 00000000..530bd96c --- /dev/null +++ b/build-win.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Cross-build helper for Windows artifacts. +# Usage: build-win.sh [-s SRC_DIR] [-o OUT_DIR] [-p PREFIX] [--no-clean] [-j JOBS] [-v] [-D DESTDIR] [--dry-run] + +SRC_DIR="/mosml" +OUT_DIR="/out" +PREFIX="/mosml" +DO_CLEAN=1 +VERBOSE=0 +JOBS="" +DESTDIR_ARG="" +DRY_RUN=0 + +usage() { + cat <&2; usage; exit 2;; + *) break;; + esac +done + +if [ "$VERBOSE" -eq 1 ]; then + set -x +fi + +error_exit() { + rc=$? + echo "Error: build failed (exit $rc)" >&2 + exit $rc +} +trap error_exit ERR + +# Determine parallel jobs if not provided +if [ -z "$JOBS" ]; then + if command -v nproc >/dev/null 2>&1; then + JOBS=$(nproc) + else + JOBS=$(sysctl -n hw.ncpu 2>/dev/null || echo 1) + fi +fi + +printf "Source: %s\nOut: %s\nPrefix: %s\nJobs: %s\nDESTDIR_ARG: %s\nDry-run: %s\n" \ + "$SRC_DIR" "$OUT_DIR" "$PREFIX" "$JOBS" "$DESTDIR_ARG" "$DRY_RUN" + +# Recompute subdir now that options may have changed +SRC_SUBDIR="$SRC_DIR/src" + +# Helper: run or echo a command depending on dry-run. Prints shell-escaped args. +run_cmd() { + if [ "$DRY_RUN" -eq 1 ]; then + printf '+ ' + for a in "$@"; do + printf '%q ' "$a" + done + printf '\n' + return 0 + fi + "$@" +} + +run_in_src() { + if [ "$DRY_RUN" -eq 1 ]; then + # Show the full subshell command including the cd so dry-run output + # reflects what would be executed. + printf '+ (cd %q &&' "$SRC_SUBDIR" + for a in "$@"; do + printf ' %q' "$a" + done + printf ' )\n' + return 0 + fi + (cd "$SRC_SUBDIR" && "$@") +} + +if [ ! -d "$SRC_DIR" ]; then + if [ "$DRY_RUN" -eq 1 ]; then + echo "Warning: source directory '$SRC_DIR' not found (dry-run)." + else + echo "Error: source directory '$SRC_DIR' not found." >&2 + exit 2 + fi +fi + +if [ "$DO_CLEAN" -eq 1 ]; then + printf "Running 'make clean' in %s/src\n" "$SRC_DIR" + run_in_src make clean +fi + +printf "Building world (may take a while)...\n" +run_in_src make world -j"$JOBS" + +# Prepare DESTDIR absolute location. Priority: --destdir, ENV DESTDIR, default +if [ -n "$DESTDIR_ARG" ]; then + WIN_ROOT="$DESTDIR_ARG" +elif [ -n "${DESTDIR-}" ]; then + WIN_ROOT="$DESTDIR" +else + WIN_ROOT="$SRC_DIR/win-root" +fi + +run_cmd mkdir -p "$WIN_ROOT" + +printf "Running cross build (cross_w32)...\n" +run_in_src make DESTDIR="$WIN_ROOT" PREFIX="$PREFIX" cross_w32 -j"$JOBS" + +run_cmd mkdir -p "$OUT_DIR" + +ZIP_PATH="$OUT_DIR/mosml-windows-x86_64.zip" +printf "Creating zip archive %s\n" "$ZIP_PATH" + +# In dry-run mode skip checks that require real files +if [ "$DRY_RUN" -eq 1 ] || [ -d "$WIN_ROOT" ]; then + if [ "$DRY_RUN" -eq 1 ] || command -v zip >/dev/null 2>&1; then + if [ "$DRY_RUN" -eq 1 ]; then + printf '+ (cd %q && zip -r %q mosml)\n' "$WIN_ROOT" "$ZIP_PATH" + else + (cd "$WIN_ROOT" && zip -r "$ZIP_PATH" mosml) + printf "Done: %s\n" "$ZIP_PATH" + fi + else + echo "Error: 'zip' not found. Please install 'zip' to create archive." >&2 + exit 3 + fi +else + echo "Error: win-root not found after build: $WIN_ROOT" >&2 + exit 2 +fi + +printf "Build finished. The zip is available in %s (mount a host dir to retrieve it).\n" "$OUT_DIR" + +exit 0 From ba5942749f6f9de1762589667b51550b632f6865 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 12:54:58 +0100 Subject: [PATCH 31/52] fix: enhance Windows build process with Docker and Inno Setup integration --- .github/workflows/buildAndTest.yml | 63 +++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index bd5d6faa..6ab49565 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -75,13 +75,45 @@ jobs: cd staging tar -czf ../mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz usr/local - - name: Cross-compile Windows binaries (on Linux) + - name: Set up Docker Buildx (on Linux) + if: matrix.platform == 'linux' + uses: docker/setup-buildx-action@v3 + + - name: Build Windows binaries using Docker (on Linux) + if: matrix.platform == 'linux' + run: | + mkdir -p out + docker build --platform=linux/386 -t mosml-win-builder -f Dockerfile.w32 . + docker run --rm -v "$(pwd)/out:/out" mosml-win-builder + + - name: Extract Windows binaries from Docker output (on Linux) + if: matrix.platform == 'linux' + run: | + cd out + unzip -q mosml-windows-x86_64.zip + mv mosml-windows-x86_64.zip ../ + cd .. + + - name: Prepare Inno Setup directory (on Linux) + if: matrix.platform == 'linux' + run: | + mkdir -p inno-setup-build + cp -r out/win-root/mosml inno-setup-build/ + cp src/tools/installer/mosml.iss inno-setup-build/ + + - name: Build Windows Installer with Inno Setup + if: matrix.platform == 'linux' + uses: Minionguyjpro/Inno-Setup-Action@v1.2.7 + with: + path: inno-setup-build/mosml.iss + options: /O+ + + - name: Rename installer if: matrix.platform == 'linux' run: | - mkdir -p win-root - (cd src && make DESTDIR="$(pwd)/../win-root" PREFIX=/mosml cross_w32) - cd win-root - zip -r ../mosml-windows-x86_64.zip mosml + mv inno-setup-build/Output/mosml-setup-*.exe mosml-setup-windows-x86_64.exe || true + ls -la *.exe || echo "No .exe files found in current directory" + ls -la inno-setup-build/Output/ || echo "Output directory not found" - name: Upload build artifacts uses: actions/upload-artifact@v4 @@ -98,6 +130,14 @@ jobs: path: mosml-windows-x86_64.zip retention-days: 30 + - name: Upload Windows Installer artifact + if: matrix.platform == 'linux' + uses: actions/upload-artifact@v4 + with: + name: mosml-windows-installer + path: mosml-setup-windows-x86_64.exe + retention-days: 30 + create-release: name: Create Release needs: [build-test] @@ -145,6 +185,17 @@ jobs: ## Installation + ### Windows + Download and run the installer: `mosml-setup-windows-x86_64.exe` + + The installer will: + - Install Moscow ML to `C:\Program Files\mosml` (or custom location) + - Add Moscow ML to your system PATH + - Create Start Menu shortcuts + - Optionally create desktop shortcuts + + Alternatively, extract the portable ZIP archive: `mosml-windows-x86_64.zip` + ### Linux / macOS ```bash # Extract the archive @@ -181,6 +232,6 @@ jobs: artifacts/mosml-linux-x86_64/mosml-linux-x86_64.tar.gz artifacts/mosml-macos-x86_64/mosml-macos-x86_64.tar.gz artifacts/mosml-macos-arm64/mosml-macos-arm64.tar.gz - artifacts/mosml-windows-x86_64/mosml-windows-x86_64.zip + artifacts/mosml-windows-installer/mosml-setup-windows-x86_64.exe env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4fb8675cb56c648f55904b5005a90b9d253fec0b Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 12:56:20 +0100 Subject: [PATCH 32/52] fix: update version number to 2.10.5 in Makefile.inc --- src/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.inc b/src/Makefile.inc index 6f8cf3e1..daec9903 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -22,7 +22,7 @@ MANEXT=1 # The version -VERSION=2.10 +VERSION=2.10.5 # Various utility programs INSTALL_PROGRAM=cp From 90c68cb175290f8cde6238752267c91c13a5d57b Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 13:05:52 +0100 Subject: [PATCH 33/52] fix: correct path for copying Windows binaries in build process --- .github/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 6ab49565..fc7affff 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -98,7 +98,7 @@ jobs: if: matrix.platform == 'linux' run: | mkdir -p inno-setup-build - cp -r out/win-root/mosml inno-setup-build/ + cp -r out/mosml inno-setup-build/ cp src/tools/installer/mosml.iss inno-setup-build/ - name: Build Windows Installer with Inno Setup From 8f43e0a5e6853b24c3d1483047349f1c54854cc6 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 13:11:11 +0100 Subject: [PATCH 34/52] fix: update build workflow to use a windows runner --- .github/workflows/buildAndTest.yml | 79 ++++++++++++++++++------------ 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index fc7affff..51c3d0d0 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -86,52 +86,67 @@ jobs: docker build --platform=linux/386 -t mosml-win-builder -f Dockerfile.w32 . docker run --rm -v "$(pwd)/out:/out" mosml-win-builder - - name: Extract Windows binaries from Docker output (on Linux) + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: mosml-${{ matrix.platform }}-${{ matrix.arch }} + path: mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz + retention-days: 30 + + - name: Upload Windows build artifact if: matrix.platform == 'linux' + uses: actions/upload-artifact@v4 + with: + name: mosml-windows-x86_64-zip + path: out/mosml-windows-x86_64.zip + retention-days: 30 + + build-windows-installer: + name: Build Windows Installer + needs: [build-test] + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Download Windows zip artifact + uses: actions/download-artifact@v4 + with: + name: mosml-windows-x86_64-zip + path: . + + - name: Extract Windows binaries run: | - cd out - unzip -q mosml-windows-x86_64.zip - mv mosml-windows-x86_64.zip ../ - cd .. + Expand-Archive -Path mosml-windows-x86_64.zip -DestinationPath . -Force + shell: pwsh - - name: Prepare Inno Setup directory (on Linux) - if: matrix.platform == 'linux' + - name: Prepare Inno Setup directory run: | - mkdir -p inno-setup-build - cp -r out/mosml inno-setup-build/ - cp src/tools/installer/mosml.iss inno-setup-build/ + New-Item -ItemType Directory -Path inno-setup-build -Force + Copy-Item -Path mosml -Destination inno-setup-build/ -Recurse + Copy-Item -Path src/tools/installer/mosml.iss -Destination inno-setup-build/ + shell: pwsh - name: Build Windows Installer with Inno Setup - if: matrix.platform == 'linux' uses: Minionguyjpro/Inno-Setup-Action@v1.2.7 with: path: inno-setup-build/mosml.iss options: /O+ - name: Rename installer - if: matrix.platform == 'linux' run: | - mv inno-setup-build/Output/mosml-setup-*.exe mosml-setup-windows-x86_64.exe || true - ls -la *.exe || echo "No .exe files found in current directory" - ls -la inno-setup-build/Output/ || echo "Output directory not found" - - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - name: mosml-${{ matrix.platform }}-${{ matrix.arch }} - path: mosml-${{ matrix.platform }}-${{ matrix.arch }}.tar.gz - retention-days: 30 - - - name: Upload Windows build artifact - if: matrix.platform == 'linux' - uses: actions/upload-artifact@v4 - with: - name: mosml-windows-x86_64 - path: mosml-windows-x86_64.zip - retention-days: 30 + $installerPath = Get-ChildItem -Path inno-setup-build/Output -Filter "mosml-setup-*.exe" | Select-Object -First 1 + if ($installerPath) { + Move-Item -Path $installerPath.FullName -Destination mosml-setup-windows-x86_64.exe + Write-Host "Installer created: mosml-setup-windows-x86_64.exe" + } else { + Write-Host "No installer found in Output directory" + Get-ChildItem -Path inno-setup-build/Output -Recurse + } + shell: pwsh - name: Upload Windows Installer artifact - if: matrix.platform == 'linux' uses: actions/upload-artifact@v4 with: name: mosml-windows-installer @@ -140,7 +155,7 @@ jobs: create-release: name: Create Release - needs: [build-test] + needs: [build-test, build-windows-installer] if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: From 15d25fffbca7e90d66992709a55fcf770ff4ac70 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 13:49:22 +0100 Subject: [PATCH 35/52] fix: avoid 64-bit literal to restore builds on 32-bit runners --- src/mosmllib/Word64.sml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mosmllib/Word64.sml b/src/mosmllib/Word64.sml index 5f05cb09..0b6f2832 100644 --- a/src/mosmllib/Word64.sml +++ b/src/mosmllib/Word64.sml @@ -167,8 +167,19 @@ in fun compare (x, y: word) = if less_ x y then LESS else if less_ y x then GREATER else EQUAL; + (* MAX_INT64 = 0x3FFFFFFFFFFFFFFF = 2^62-1, constructed without 64-bit literal *) + val maxInt64 = + let + (* Construct without large hex literals so 32-bit bootstrap compilers parse it. + high = 0x3FFFFFFF = 1073741823 + low = (1 << 32) - 1 = 0xFFFFFFFF, computed via shift and subtract *) + val high = fromInt 1073741823 + val low = (lshift_ (fromInt 1) (fromInt 32)) - fromInt 1 + in lshift_ high (fromInt 32) + low + end + fun toInt w = - if w > fromWord_ 0wx3FFFFFFFFFFFFFFF then raise Overflow + if w > maxInt64 then raise Overflow else toIntX w end From 163427732f27305303f5f94aa584d808645bf5f6 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:18:12 +0100 Subject: [PATCH 36/52] fix: remove duplicated binaries from .dockerignore --- .dockerignore | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.dockerignore b/.dockerignore index 71eaf3b4..6855a1bd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -12,11 +12,6 @@ mosmllex mosmlyac # Binaries (top-level names only) -camlrunm -mosmlcmp -mosmllnk -mosmllex -mosmlyac mosmldep cutdeps From 70039b16bd9d137747edac5572db3fa32348471d Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:18:33 +0100 Subject: [PATCH 37/52] fix: remove duplicate file in gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d975d48d..d5592bb9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +# Local configuration /config # Build artifacts @@ -414,7 +415,6 @@ TSWLatexianTemp* ### macOS ### # General -.DS_Store .AppleDouble .LSOverride From 3c61ef21e5559727314ea9ff16bbcc9fad1ae01d Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:19:03 +0100 Subject: [PATCH 38/52] fix: validate JOBS input as a positive integer in build-win.sh, simplify dry run logic --- build-win.sh | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/build-win.sh b/build-win.sh index 530bd96c..f8c567aa 100644 --- a/build-win.sh +++ b/build-win.sh @@ -47,6 +47,20 @@ while [ "$#" -gt 0 ]; do esac done +# Validate JOBS if provided: must be a positive integer +if [ -n "${JOBS:-}" ]; then + if ! [[ "$JOBS" =~ ^[0-9]+$ ]]; then + printf "Error: invalid -j value '%s' (must be a positive integer)\n" "$JOBS" >&2 + usage + exit 2 + fi + if [ "$JOBS" -eq 0 ]; then + printf "Error: invalid -j value '%s' (must be greater than zero)\n" "$JOBS" >&2 + usage + exit 2 + fi +fi + if [ "$VERBOSE" -eq 1 ]; then set -x fi @@ -136,22 +150,24 @@ run_cmd mkdir -p "$OUT_DIR" ZIP_PATH="$OUT_DIR/mosml-windows-x86_64.zip" printf "Creating zip archive %s\n" "$ZIP_PATH" -# In dry-run mode skip checks that require real files -if [ "$DRY_RUN" -eq 1 ] || [ -d "$WIN_ROOT" ]; then - if [ "$DRY_RUN" -eq 1 ] || command -v zip >/dev/null 2>&1; then - if [ "$DRY_RUN" -eq 1 ]; then - printf '+ (cd %q && zip -r %q mosml)\n' "$WIN_ROOT" "$ZIP_PATH" - else - (cd "$WIN_ROOT" && zip -r "$ZIP_PATH" mosml) - printf "Done: %s\n" "$ZIP_PATH" - fi - else +# Dry-run prints the command and skips runtime checks +if [ "$DRY_RUN" -eq 1 ]; then + printf '+ (cd %q && zip -r %q mosml)\n' "$WIN_ROOT" "$ZIP_PATH" +else + # Verify win root exists + if [ ! -d "$WIN_ROOT" ]; then + echo "Error: win-root not found after build: $WIN_ROOT" >&2 + exit 2 + fi + + # Verify zip is available + if ! command -v zip >/dev/null 2>&1; then echo "Error: 'zip' not found. Please install 'zip' to create archive." >&2 exit 3 fi -else - echo "Error: win-root not found after build: $WIN_ROOT" >&2 - exit 2 + + (cd "$WIN_ROOT" && zip -r "$ZIP_PATH" mosml) + printf "Done: %s\n" "$ZIP_PATH" fi printf "Build finished. The zip is available in %s (mount a host dir to retrieve it).\n" "$OUT_DIR" From 3e63dc415a365e904348c88a1e6bc9fc52374e9b Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:19:22 +0100 Subject: [PATCH 39/52] fix: restrict branches for push and pull_request events, update rlwrap disable logic --- .github/workflows/buildAndTest.yml | 7 ++++--- src/launch/mosml.tpl | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 51c3d0d0..4ac5173e 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -2,12 +2,13 @@ name: Build & Test on: push: - branches: ["**"] + branches: ["main", "develop"] tags: ["v*.*.*"] pull_request: - branches: ["**"] + branches: ["main", "develop"] release: types: [created] + workflow_dispatch: jobs: build-test: @@ -230,7 +231,7 @@ jobs: - Line editing with arrow keys - Tab completion support - To disable rlwrap, set the `RLWRAP` environment variable before running mosml. + To disable rlwrap, set the `DISABLE_RLWRAP=1` environment variable before running mosml. ## Documentation See the [project repository](https://github.com/${{ github.repository }}) for full documentation. diff --git a/src/launch/mosml.tpl b/src/launch/mosml.tpl index cb045c67..c284a6e8 100755 --- a/src/launch/mosml.tpl +++ b/src/launch/mosml.tpl @@ -26,8 +26,8 @@ else use_rlwrap="" fi -# Disable rlwrap if RLWRAP environment variable is already set -if [ -n "$RLWRAP" ]; then +# Disable rlwrap if DISABLE_RLWRAP environment variable is set +if [ -n "$DISABLE_RLWRAP" ] && [ "$DISABLE_RLWRAP" == "1" ]; then use_rlwrap="" fi From fc67e1a6a3e90126788f41b64767aaf727ced346 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:19:35 +0100 Subject: [PATCH 40/52] fix: correct formatting of Danish uninstall program message in installer script --- src/tools/installer/mosml.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/installer/mosml.iss b/src/tools/installer/mosml.iss index 4287e20f..21089aa1 100644 --- a/src/tools/installer/mosml.iss +++ b/src/tools/installer/mosml.iss @@ -60,7 +60,7 @@ en.MosMLName=Moscow ML Commandline da.MosMLName=Moscow ML Kommandolinje it.MosMLName=Moscow ML da riga di comando en.UninstallProgram=Uninstall %1 -da.UninstallProgram=Afinstaller %1 +da.UninstallProgram=Afinstaller %1 it.UninstallProgram=Disinstalla %1 en.Documentation=Documentation From 84b12501530dad80988b4b823ef08bd38a1a2b29 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:21:25 +0100 Subject: [PATCH 41/52] fix(word64): use proper sign-extending primitives and add runtime support --- src/mosmllib/Word64.sml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mosmllib/Word64.sml b/src/mosmllib/Word64.sml index 0b6f2832..6ed685a5 100644 --- a/src/mosmllib/Word64.sml +++ b/src/mosmllib/Word64.sml @@ -29,19 +29,19 @@ local in (* NOT the SML BL conversion funs *) prim_val toInt : word -> int = 1 "boxed_uint64_toword"; - prim_val toIntX : word -> int = 1 "boxed_uint64_toword"; + prim_val toIntX : word -> int = 1 "boxed_uint64_toword_signed"; prim_val fromInt : int -> word = 1 "boxed_uint64_fromword"; prim_val toLargeInt : word -> int = 1 "boxed_uint64_toword"; - prim_val toLargeIntX : word -> int = 1 "boxed_uint64_toword"; + prim_val toLargeIntX : word -> int = 1 "boxed_uint64_toword_signed"; prim_val fromLargeInt : int -> word = 1 "boxed_uint64_fromword"; prim_val toLargeWord : word -> Word.word = 1 "boxed_uint64_toword"; - prim_val toLargeWordX : word -> Word.word = 1 "boxed_uint64_toword"; + prim_val toLargeWordX : word -> Word.word = 1 "boxed_uint64_toword_signed"; prim_val fromLargeWord : Word.word -> word = 1 "boxed_uint64_fromword"; prim_val toLarge : word -> Word.word = 1 "boxed_uint64_toword" - prim_val toLargeX : word -> Word.word = 1 "boxed_uint64_toword" + prim_val toLargeX : word -> Word.word = 1 "boxed_uint64_toword_signed" prim_val fromLarge : Word.word -> word = 1 "boxed_uint64_fromword"; val ZERO = fromInt 0 From 804b4cd28b7501efa05d4f10db4d2e2a5aeaf5aa Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:21:50 +0100 Subject: [PATCH 42/52] fix(runtime): correct unbalanced parentheses in int64 multiply overflow check --- src/runtime/boxed_num.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/runtime/boxed_num.c b/src/runtime/boxed_num.c index a3dc72ce..da073aa4 100644 --- a/src/runtime/boxed_num.c +++ b/src/runtime/boxed_num.c @@ -76,6 +76,14 @@ value boxed_uint64_toword(value v) { /* ML */ return Val_long(UInt64_val(v)); } +/* Sign-extending variant: interpret the boxed uint64_t as signed + 2's complement and return the host `long` (ML int) with sign + extension from bit 63. This mirrors `boxed_uint64_toword` but + casts through int64_t to preserve the sign. */ +value boxed_uint64_toword_signed(value v) { /* ML */ + return Val_long((long)((int64_t)UInt64_val(v))); +} + value boxed_uint64_add(value v1, value v2) { /* ML */ return copy_uint64(UInt64_val(v1) + UInt64_val(v2)); } @@ -214,8 +222,8 @@ value boxed_int64_sub(value v1, value v2) { /* ML */ value boxed_int64_mul(value v1, value v2) { /* ML */ int64_t x = Int64_val(v1), y = Int64_val(v2); if ((x > 0 && (y > INT64_MAX/x || y < INT64_MIN/x)) || - (x < -1 && (y > INT64_MIN/x || y < INT64_MAX/x) || - (x == -1 && y == INT64_MIN))) + (x < -1 && (y > INT64_MIN/x || y < INT64_MAX/x)) || + (x == -1 && y == INT64_MIN)) raise_overflow(); return copy_int64(x * y); From aac0f0c39870c76a3719795b84249745f37f0b31 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:51:07 +0100 Subject: [PATCH 43/52] fix: portable string comparison operator in rlwrap disable check --- src/launch/mosml.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/launch/mosml.tpl b/src/launch/mosml.tpl index c284a6e8..2b746cb0 100755 --- a/src/launch/mosml.tpl +++ b/src/launch/mosml.tpl @@ -27,7 +27,7 @@ else fi # Disable rlwrap if DISABLE_RLWRAP environment variable is set -if [ -n "$DISABLE_RLWRAP" ] && [ "$DISABLE_RLWRAP" == "1" ]; then +if [ -n "$DISABLE_RLWRAP" ] && [ "$DISABLE_RLWRAP" = "1" ]; then use_rlwrap="" fi From 36f4401ba9bb0c2039b334bdcad1393f6d83db40 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:51:14 +0100 Subject: [PATCH 44/52] fix: update source label URL in Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cbd8973b..646f48a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ WORKDIR /workspace # Add labels LABEL org.opencontainers.image.title="Moscow ML" LABEL org.opencontainers.image.description="Moscow ML is a light-weight implementation of Standard ML (SML), a strict functional language widely used in teaching and research." -LABEL org.opencontainers.image.source="https://github.com/Francesco146/mosml" +LABEL org.opencontainers.image.source="https://github.com/kfl/mosml" # Default command is interactive REPL ENTRYPOINT ["mosml"] From 82e40e37400258f448e7ca4464b386c82f14b0a7 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 14:51:33 +0100 Subject: [PATCH 45/52] fix(word64): make shift functions safe for large shift counts --- src/mosmllib/Word64.sml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mosmllib/Word64.sml b/src/mosmllib/Word64.sml index 6ed685a5..78eedae1 100644 --- a/src/mosmllib/Word64.sml +++ b/src/mosmllib/Word64.sml @@ -52,15 +52,15 @@ in fun notb x = xorb_ x (fromInt ~1); fun << (w, k) = - if toInt k >= 64 orelse toInt k < 0 then ZERO + if (not (less_ k (fromInt 64))) orelse (less_ k ZERO) then ZERO else lshift_ w k; fun >> (w, k) = - if toInt k >= 64 orelse toInt k < 0 then ZERO + if (not (less_ k (fromInt 64))) orelse (less_ k ZERO) then ZERO else rshiftuns_ w k; fun ~>> (w, k) = - if toInt k >= 64 orelse toInt k < 0 then + if (not (less_ k (fromInt 64))) orelse (less_ k ZERO) then if toInt w >= 0 then (* msbit = 0 *) ZERO else (* msbit = 1 *) From 9f3f27993a7ea82289827730b4cc3d6072bbaef8 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 16:07:00 +0100 Subject: [PATCH 46/52] fix(install): enhance Windows installation script with error checks and messages --- src/dynlibs/intinf/Makefile | 8 ++++++++ src/lex/Makefile | 20 ++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/dynlibs/intinf/Makefile b/src/dynlibs/intinf/Makefile index 82d358c0..b6d3ec49 100644 --- a/src/dynlibs/intinf/Makefile +++ b/src/dynlibs/intinf/Makefile @@ -24,6 +24,14 @@ ifeq ($(GMPLIBDIR),) done) endif +# Warn the user if we still couldn't locate GMP headers or libraries +ifeq ($(GMPINCDIR),) +$(warning GMP header directory not found. Please install GMP development headers or set GMPINCDIR=/path/to/gmp/include) +endif +ifeq ($(GMPLIBDIR),) +$(warning GMP library directory not found. Please install GMP libraries or set GMPLIBDIR=/path/to/gmp/lib) +endif + include ../../Makefile.inc #OPTS=-fno-defer-pop diff --git a/src/lex/Makefile b/src/lex/Makefile index eca1d487..2858b071 100644 --- a/src/lex/Makefile +++ b/src/lex/Makefile @@ -40,8 +40,24 @@ install: ${INSTALL_DATA} mosmllex $(DESTDIR)$(LIBDIR) install_w32: - cat ../launch.w32/header.exe mosmllex > $(DESTDIR)$(BINDIR)/mosmllex.exe - chmod a+x $(DESTDIR)$(BINDIR)/mosmllex.exe + @set -e; \ + # Verify inputs exist + if [ ! -f ../launch.w32/header.exe ]; then \ + echo "Error: ../launch.w32/header.exe not found; run 'make install' from top-level or ensure launch.w32 is built." >&2; \ + exit 1; \ + fi; \ + if [ ! -f mosmllex ]; then \ + echo "Error: mosmllex not found; build the mosmllex target first (make)." >&2; \ + exit 1; \ + fi; \ + # Ensure destination directory exists + mkdir -p "$(DESTDIR)$(BINDIR)"; \ + # Concatenate header and binary into the destination exe + cat ../launch.w32/header.exe mosmllex > "$(DESTDIR)$(BINDIR)/mosmllex.exe"; \ + # Try to set executable bit when supported; ignore failure on filesystems that don't support it + if command -v chmod >/dev/null 2>&1; then \ + chmod a+x "$(DESTDIR)$(BINDIR)/mosmllex.exe" || true; \ + fi uninstall: ${UNINSTALL_DATA} $(DESTDIR)$(LIBDIR)/mosmllex From c1445f22e6f5104fdfcdf65b5c3dbd193da207ad Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 16:07:12 +0100 Subject: [PATCH 47/52] fix(launch): change shebang to bash and improve rlwrap handling --- src/launch/mosml.tpl | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/launch/mosml.tpl b/src/launch/mosml.tpl index 2b746cb0..97c01f6f 100755 --- a/src/launch/mosml.tpl +++ b/src/launch/mosml.tpl @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash stdlib=LIBDIR mosmlbin=BINDIR @@ -16,25 +16,26 @@ fi # Create history directory if possible (ignore errors gracefully) mkdir -p "$(dirname "$history_file")" 2>/dev/null || true -# Check if rlwrap is available and stdin is a terminal -use_rlwrap="" -if [ -t 0 ] && command -v rlwrap >/dev/null 2>&1; then - use_rlwrap="rlwrap -a -H $history_file -s 1000" -else - echo "Warning: rlwrap not found or input is not a terminal; running without rlwrap." >&2 +# Check if rlwrap is available and the session is interactive. +# Store rlwrap invocation as an array so we can safely embed quoted paths. +# We only print warnings when the session is interactive (stdout is a tty). +use_rlwrap=() +if command -v rlwrap >/dev/null 2>&1 && [ -t 1 ]; then + use_rlwrap=(rlwrap -a -H "$history_file" -s 1000) +elif [ -t 1 ]; then + echo "Warning: rlwrap not found; running without rlwrap." >&2 echo "For better command line editing, consider installing rlwrap." >&2 - use_rlwrap="" fi -# Disable rlwrap if DISABLE_RLWRAP environment variable is set +# Disable rlwrap if DISABLE_RLWRAP environment variable is set to 1 if [ -n "$DISABLE_RLWRAP" ] && [ "$DISABLE_RLWRAP" = "1" ]; then - use_rlwrap="" + use_rlwrap=() fi while : ; do case $1 in "") - exec $use_rlwrap $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options;; + exec "${use_rlwrap[@]}" $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options;; -I|-include) includes="$includes -I $2" shift;; @@ -62,7 +63,7 @@ while : ; do -*) echo "Unknown option \"$1\", ignored" >&2;; *) - exec $use_rlwrap $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options $* ;; + exec "${use_rlwrap[@]}" $mosmlbin/camlrunm $stdlib/mosmltop -stdlib $stdlib $includes $options $* ;; esac shift done From e60f64ee5d046765646f206f1219aea2a19125e8 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 16:08:46 +0100 Subject: [PATCH 48/52] fix(docker): enhance Dockerfiles with improved dependency installation and entrypoint handling --- Dockerfile | 16 +++++++++------- Dockerfile.w32 | 10 ++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 646f48a7..d88d58cb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,8 @@ FROM --platform=linux/amd64 ubuntu:22.04 AS builder ENV DEBIAN_FRONTEND=noninteractive -# Install build dependencies -RUN apt-get update && \ +# Install build dependencies (fail fast, print commands, and preserve pipefail) +RUN bash -euxo pipefail -c "apt-get update && \ apt-get install -y --no-install-recommends \ binutils \ build-essential \ @@ -12,7 +12,7 @@ RUN apt-get update && \ libgmp-dev \ perl && \ apt-get clean && \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*" # Copy source code COPY . /mosml-src @@ -28,14 +28,14 @@ FROM --platform=linux/amd64 ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive -# Install runtime dependencies -RUN apt-get update && \ +# Install runtime dependencies (fail fast and show commands) +RUN bash -euxo pipefail -c "apt-get update && \ apt-get install -y --no-install-recommends \ libc6 \ libgmp10 \ rlwrap && \ apt-get clean && \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*" # Copy installed Moscow ML from builder COPY --from=builder /mosml-install/usr/local /usr/local @@ -48,5 +48,7 @@ LABEL org.opencontainers.image.title="Moscow ML" LABEL org.opencontainers.image.description="Moscow ML is a light-weight implementation of Standard ML (SML), a strict functional language widely used in teaching and research." LABEL org.opencontainers.image.source="https://github.com/kfl/mosml" -# Default command is interactive REPL +# Default command is interactive REPL. Keep ENTRYPOINT as the executable and +# provide an empty CMD so callers can pass flags/arguments via `docker run`. ENTRYPOINT ["mosml"] +CMD [] diff --git a/Dockerfile.w32 b/Dockerfile.w32 index 1f8a3f94..a3a80174 100644 --- a/Dockerfile.w32 +++ b/Dockerfile.w32 @@ -29,8 +29,14 @@ ENV CC=gcc \ COPY . /mosml WORKDIR /mosml -COPY build-win.sh /usr/local/bin/build-win.sh -RUN chmod +x /usr/local/bin/build-win.sh +# Avoid copying `build-win.sh` twice and to be robust when `/mosml` +# is later mounted from the host, create a tiny wrapper in the image +# filesystem that execs the real script inside `/mosml` at runtime. +# This ensures the entrypoint remains executable even if the host +# mount masks permissions or replaces the file. +RUN printf '%s\n' '#!/bin/sh' 'exec /bin/bash /mosml/build-win.sh "$@"' \ + > /usr/local/bin/build-win.sh && \ + chmod +x /usr/local/bin/build-win.sh # Build: docker build -t mosml-win-builder --platform=linux/386 -f Dockerfile.w32 . # When running the container, mount a host directory on /out to receive the zip. From 7da4a433103189c6e8e14abbf497dec0e9d939a3 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 16:09:03 +0100 Subject: [PATCH 49/52] fix(build): update shebang in build script and enhance zip creation checks --- .github/workflows/buildAndTest.yml | 1 + .github/workflows/docker.yml | 4 ++-- build-win.sh | 12 +++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 4ac5173e..74892f87 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -249,5 +249,6 @@ jobs: artifacts/mosml-macos-x86_64/mosml-macos-x86_64.tar.gz artifacts/mosml-macos-arm64/mosml-macos-arm64.tar.gz artifacts/mosml-windows-installer/mosml-setup-windows-x86_64.exe + artifacts/mosml-windows-x86_64-zip/mosml-windows-x86_64.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index d5731403..44f5df0e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker Build and Push on: push: - branches: ["**"] + branches: ["main", "master"] tags: ["v*.*.*"] workflow_dispatch: @@ -48,7 +48,7 @@ jobs: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} docker.io/${{ secrets.DOCKERHUB_USERNAME }}/mosml tags: | - type=raw,value=latest + type=raw,value=latest,enable={{is_default_branch}} type=semver,pattern={{version}} - name: Build and push Docker image diff --git a/build-win.sh b/build-win.sh index f8c567aa..471f0635 100644 --- a/build-win.sh +++ b/build-win.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash set -euo pipefail # Cross-build helper for Windows artifacts. @@ -150,9 +150,9 @@ run_cmd mkdir -p "$OUT_DIR" ZIP_PATH="$OUT_DIR/mosml-windows-x86_64.zip" printf "Creating zip archive %s\n" "$ZIP_PATH" -# Dry-run prints the command and skips runtime checks +# Dry-run prints the command and includes the directory check if [ "$DRY_RUN" -eq 1 ]; then - printf '+ (cd %q && zip -r %q mosml)\n' "$WIN_ROOT" "$ZIP_PATH" + printf '+ [ -d %q ] && (cd %q && zip -r %q mosml)\n' "$WIN_ROOT/mosml" "$WIN_ROOT" "$ZIP_PATH" else # Verify win root exists if [ ! -d "$WIN_ROOT" ]; then @@ -160,6 +160,12 @@ else exit 2 fi + # Verify mosml directory exists inside win root + if [ ! -d "$WIN_ROOT/mosml" ]; then + echo "Error: expected directory '$WIN_ROOT/mosml' not found. The cross build should have created it." >&2 + exit 2 + fi + # Verify zip is available if ! command -v zip >/dev/null 2>&1; then echo "Error: 'zip' not found. Please install 'zip' to create archive." >&2 From 6f065510022f146a1d4077cfe306ec5fb2c6fd0d Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 16:09:18 +0100 Subject: [PATCH 50/52] fix: change main function signature to void for consistency --- .gitignore | 2 +- src/config/auto-aux/schar.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index d5592bb9..fd466901 100644 --- a/.gitignore +++ b/.gitignore @@ -371,7 +371,7 @@ TSWLatexianTemp* *.tps # auto folder when using emacs and auctex -./auto/* +auto/* *.el # expex forward references with \gathertags diff --git a/src/config/auto-aux/schar.c b/src/config/auto-aux/schar.c index a8f7a287..6625b202 100644 --- a/src/config/auto-aux/schar.c +++ b/src/config/auto-aux/schar.c @@ -1,7 +1,7 @@ #include char foo[]="\377"; -int main(int argc, char ** argv) +int main(void) { int i; i = foo[0]; From ced2db5750091eaa4b9bdf0f6a86d0c4414b75e9 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Fri, 14 Nov 2025 16:28:14 +0100 Subject: [PATCH 51/52] fix(build): remove mingw-w64 from Linux dependency installation --- .github/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 74892f87..3fb530a6 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -37,7 +37,7 @@ jobs: if: matrix.platform == 'linux' run: | sudo apt-get update -qq - sudo apt-get install -y binutils build-essential perl libgmp-dev rlwrap mingw-w64 + sudo apt-get install -y binutils build-essential perl libgmp-dev rlwrap - name: Install dependencies (macOS) if: matrix.platform == 'macos' From 4cc486c236fea01cd9ee2b5454bce7aa132dc249 Mon Sep 17 00:00:00 2001 From: Francesco146 Date: Thu, 4 Dec 2025 17:00:37 +0100 Subject: [PATCH 52/52] fix(workflow): include gnu-tty-stds-and-fixes branch in push triggers --- .github/workflows/buildAndTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 3fb530a6..5061137b 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -2,7 +2,7 @@ name: Build & Test on: push: - branches: ["main", "develop"] + branches: ["main", "develop", "gnu-tty-stds-and-fixes"] # delete this branch name when merged tags: ["v*.*.*"] pull_request: branches: ["main", "develop"]