From eb198ce6061c86a8500b756697f3fe2f7a37c83d Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 13 Nov 2026 16:38:04 +0900 Subject: [PATCH 1/3] djgpp-platform 0.1.0: the i586-dos-djgpp row, DJGPP's GCC, DOSBox Staging through dirun The row is data: COFF objects, .exe, a 32-bit data model and the execution system dos, its GCC named by the row's GCC target i586-pc-msdosdjgpp. The runner is dirun's payload form with DOSBox Staging's profile. examples/hello checks its arguments and a file round trip and returns 42; CI builds and runs it on Linux x86_64. --- .github/workflows/ci.yml | 80 +++++++++++++++++++++++++++++++++++++++ .gitignore | 2 + examples/hello/mcpp.toml | 10 +++++ examples/hello/src/main.c | 20 ++++++++++ mcpp.toml | 49 ++++++++++++++++++++++++ 5 files changed, 161 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 examples/hello/mcpp.toml create mode 100644 examples/hello/src/main.c create mode 100644 mcpp.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5625e84 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,80 @@ +name: CI + +# What this workflow asserts about djgpp-platform: on a Linux x86_64 machine, mcpp builds +# examples/hello for i586-dos-djgpp with DJGPP's GCC (the row's GCC target names the payload), the +# artefact is a go32 DOS executable, and `mcpp run` runs it under DOSBox Staging through dirun with +# its arguments, its output and its status (42). +# +# The row's GCC target is read by mcpp 2026.11.13.1 and later. A dispatch, or the repository +# variable MCPP_SOURCE_REF, names a branch of mcpp that the released mcpp builds and that is then +# used. + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + inputs: + mcpp_ref: + description: "Branch of mcpp-community/mcpp to build and use (empty = the released mcpp)" + required: false + default: "" + +env: + MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF || '' }} + MCPP_VERSION: 2026.11.12.1 + XLINGS_VERSION: v2026.10.26.1 + XLINGS_NON_INTERACTIVE: '1' + +jobs: + dos: + name: i586-dos-djgpp (built and run on Linux x86_64) + runs-on: ubuntu-24.04 + timeout-minutes: 60 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + + - name: Install xlings and mcpp + run: | + set -euo pipefail + curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \ + | bash -s "$XLINGS_VERSION" + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" + for attempt in 1 2 3 4 5 6; do + xlings update > /dev/null 2>&1 || true + if xlings install "mcpp@$MCPP_VERSION" -y -g; then break; fi + [ "$attempt" = 6 ] && { echo "::error::mcpp could not be installed"; exit 1; } + sleep 60 + done + mcpp self config --mirror GLOBAL + if [ -n "$MCPP_SOURCE_REF" ]; then + src="$RUNNER_TEMP/mcpp-src" + git clone --quiet --depth 1 --branch "$MCPP_SOURCE_REF" https://github.com/mcpp-community/mcpp.git "$src" + rm -f "$src/.xlings.json" + ( cd "$src" && mcpp build --release ) + built=$(find "$src/target" -type f -name mcpp -path '*/bin/*' | head -1) + [ -n "$built" ] || { echo "::error::mcpp did not build from $MCPP_SOURCE_REF"; exit 1; } + echo "$(cd "$(dirname "$built")" && pwd)" >> "$GITHUB_PATH" + echo "under review: $("$built" --version) (from $MCPP_SOURCE_REF)" + fi + + - name: A DOS program, built and run + working-directory: examples/hello + run: | + set -euo pipefail + mcpp --version + mcpp build --target i586-dos-djgpp + exe=$(find target/i586-dos-djgpp -path '*bin/hello.exe' -type f | head -1) + file "$exe" + file "$exe" | grep -q 'DJGPP go32' || { echo "::error::not a go32 DOS executable"; exit 1; } + set +e + mcpp run --target i586-dos-djgpp -- one two | tee run.log + status=${PIPESTATUS[0]} + set -e + grep -q "hello from dos: 3 arguments" run.log && grep -q "all held" run.log \ + || { echo "::error::the program's output"; exit 1; } + [ "$status" = 42 ] || { echo "::error::the status is $status, not 42"; exit 1; } diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b1c13f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +*.log diff --git a/examples/hello/mcpp.toml b/examples/hello/mcpp.toml new file mode 100644 index 0000000..1d7ead5 --- /dev/null +++ b/examples/hello/mcpp.toml @@ -0,0 +1,10 @@ +[package] +name = "hello" +version = "0.1.0" + +[targets.hello] +kind = "bin" +main = "src/main.c" + +[target.i586-dos-djgpp] +platform = { path = "../.." } diff --git a/examples/hello/src/main.c b/examples/hello/src/main.c new file mode 100644 index 0000000..b50e580 --- /dev/null +++ b/examples/hello/src/main.c @@ -0,0 +1,20 @@ +/* A DOS program built by mcpp: its arguments, a file written and read back, and its status. */ +#include +#include + +int main(int argc, char** argv) { + int failures = 0; + printf("hello from dos: %d arguments\n", argc); + if (argc < 2 || strcmp(argv[argc - 1], "two") != 0) { printf(" FAIL the arguments arrive\n"); ++failures; } + FILE* f = fopen("NOTE.TXT", "w"); + if (!f) { printf(" FAIL a file is created\n"); return 1; } + fputs("kept", f); + fclose(f); + char back[8] = {0}; + f = fopen("NOTE.TXT", "r"); + if (!f || !fgets(back, sizeof back, f) || strcmp(back, "kept") != 0) { printf(" FAIL a file is read back\n"); ++failures; } + if (f) fclose(f); + remove("NOTE.TXT"); + puts(failures ? "FAILED" : "all held"); + return failures ? 1 : 42; +} diff --git a/mcpp.toml b/mcpp.toml new file mode 100644 index 0000000..c889d38 --- /dev/null +++ b/mcpp.toml @@ -0,0 +1,49 @@ +# djgpp-platform: 32-bit DOS programs built by DJGPP, as a platform package (mcpp SPEC-013). The +# row is data here, not in the engine: a program is a go32 executable (an MZ stub before a COFF +# image) that runs under a DPMI host; its compiler is DJGPP's GCC, named by the row's GCC target +# (`gcc-triple`), and its C library and C++ run-time are DJGPP's own. The runner is DOSBox Staging +# through dirun's payload form: the program and the DPMI host in a directory DOSBox mounts as C:, +# its output and status read back from the files a launcher writes. +[package] +namespace = "mcpplibs" +name = "djgpp-platform" +version = "0.1.0" +description = "32-bit DOS programs built by DJGPP: the i586-dos-djgpp row, its GCC payload, and DOSBox Staging as its runner" +license = "Apache-2.0" +authors = ["mcpplibs"] +repo = "https://github.com/mcpplibs/djgpp-platform" +mcpp = ">=2026.11.13.1" # the row's GCC target (gcc-triple) and COFF objects + +[platform] +targets = ["i586-dos-djgpp"] +toolchain = "gcc@12.2.0" + +# The runner: dirun boots the program under DOSBox Staging with the package's profile, which +# places the program and CWSDPMI in the directory DOSBox mounts as C: and reads the program's +# output and status back from files (DOSBox's own status is not the program's). The program's +# arguments follow `--`. +[platform.runner] +cmd = ["dirun", "--payload", "{}", "--profile", "{pkg:dosbox-staging}/dirun.toml", "--"] +hosts = ["linux-x86_64", "macos-aarch64", "windows-x86_64"] +requires = ["xim:dirun@0.3.0", "xim:dosbox-staging@0.83.0"] + +[[platform.define]] +triple = "i586-dos-djgpp" +gcc-triple = "i586-pc-msdosdjgpp" +object-format = "coff" +data-model = "ilp32" +exe-suffix = ".exe" +execution = "dos" +standard = false + +[[platform.provider]] +serves = ["i586-dos-djgpp"] +pairs = ["gcc"] +linkage = "static" + +# The C library and the C++ run-time are the toolchain's (DJGPP 2.05, libstdc++ 12). +[platform.layers] +"kernel-abi" = false +"c-abi" = false +"c++-abi" = false +"compiler-runtime" = false From 88a975498a228efd744286d35578373822a29fc8 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sat, 14 Nov 2026 23:03:58 +0900 Subject: [PATCH 2/3] ci: mcpp 2026.11.13.1, the engine the row's GCC target requires --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5625e84..8829556 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ on: env: MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF || '' }} - MCPP_VERSION: 2026.11.12.1 + MCPP_VERSION: 2026.11.13.1 XLINGS_VERSION: v2026.10.26.1 XLINGS_NON_INTERACTIVE: '1' From e566d7bf98eacd22f72a70506000882c19dbce66 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Sun, 15 Nov 2026 05:15:43 +0900 Subject: [PATCH 3/3] ci: mcpp 2026.11.14.1, the newest release --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8829556..da25229 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ on: env: MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF || '' }} - MCPP_VERSION: 2026.11.13.1 + MCPP_VERSION: 2026.11.14.1 XLINGS_VERSION: v2026.10.26.1 XLINGS_NON_INTERACTIVE: '1'