From c79d52ae2eccdd3b870634045a1a102d3c356ae5 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 10:46:30 +0800 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20release=20v0.1.5=20=E2=80=94=20upgr?= =?UTF-8?q?ade=20to=20latest=20xlings/mcpp,=20add=20macOS=2014=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dependency upgrades (to latest): - mcpp 0.0.13 -> 0.0.52 (.xlings.json); 0.0.13 was removed from the registry - xlings 0.4.31 -> 0.4.51 (CI/release) - llmapi 0.2.5 -> 0.2.6, mcpplibs-tinyhttps 0.2.2 -> 0.2.3 (xmake.lua), aligning the xmake build with mcpp.toml - bump version to 0.1.5 (config.cppm, mcpp.toml, README) CI / macOS 14 support (#19): - the xlings-bundled xmake is built against a fixed macOS SDK and aborts on older runners ("built for macOS 15.5 which is newer than running OS"); install xmake via the official setup action and use xlings only for the LLVM toolchain - build-macos now runs a [macos-14, macos-15] matrix; release builds on macos-14 so the artifact also runs on newer macOS Issue fixes: - #24 (contributing): Windows run_command_capture now redirects stderr to stdout (2>&1) like linux/macos, so build errors / D2X_WAIT markers are captured - #8: `book` resolves any project-provided book/ sub-book, not just zh/en, falling back to the default book/ when absent chore: ignore generated mcpp.lock and compile_commands.json --- .github/workflows/ci.yml | 40 +++++++++++++++++++++++++---------- .github/workflows/release.yml | 27 ++++++++++++++++------- .gitignore | 2 ++ .xlings.json | 2 +- README.md | 2 +- mcpp.toml | 2 +- src/cmdprocessor.cppm | 9 +++++++- src/config.cppm | 2 +- src/platform/windows.cppm | 3 ++- xmake.lua | 4 ++-- 10 files changed, 66 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c028ef7..82d4ab1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,10 @@ on: branches: [main] pull_request: +env: + XLINGS_VERSION: 0.4.51 + MCPP_VERSION: 0.0.52 + jobs: build-linux-mcpp: name: build (linux x86_64, mcpp) @@ -13,8 +17,6 @@ jobs: - uses: actions/checkout@v4 - name: Install xlings - env: - XLINGS_VERSION: 0.4.31 run: | tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" curl -fsSL -o "/tmp/${tarball}" \ @@ -26,14 +28,14 @@ jobs: - name: Refresh package index run: xlings update - - name: Install workspace tools (.xlings.json → mcpp 0.0.13) + - name: Install workspace tools (.xlings.json -> mcpp ${{ env.MCPP_VERSION }}) run: xlings install -y - name: Cache mcpp sandbox uses: actions/cache@v4 with: - path: ~/.xlings/data/xpkgs/xim-x-mcpp/0.0.13/registry - key: mcpp-sandbox-${{ runner.os }}-mcpp0.0.13 + path: ~/.xlings/data/xpkgs/xim-x-mcpp/${{ env.MCPP_VERSION }}/registry + key: mcpp-sandbox-${{ runner.os }}-mcpp${{ env.MCPP_VERSION }} - name: Build with mcpp run: mcpp build @@ -46,15 +48,29 @@ jobs: "$binary" --version build-macos: - runs-on: macos-15 + name: build (${{ matrix.os }}, xmake/llvm) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-14, macos-15] steps: - name: Checkout code uses: actions/checkout@v4 + # Provide an OS-appropriate xmake binary. The xlings-bundled xmake is + # built against a fixed macOS SDK and crashes on older runners + # (issue #19: "built for macOS 15.5 which is newer than running OS"), + # so we install xmake via the official action and use xlings only for + # the LLVM toolchain. + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest + - name: Install Xlings env: XLINGS_NON_INTERACTIVE: 1 - XLINGS_VERSION: 0.4.31 run: | TARBALL="xlings-${XLINGS_VERSION}-macosx-arm64.tar.gz" curl -fSL -o "$RUNNER_TEMP/$TARBALL" "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${TARBALL}" @@ -63,12 +79,14 @@ jobs: xattr -dr com.apple.quarantine "$EXTRACT_DIR" 2>/dev/null || true chmod +x "$EXTRACT_DIR/bin/xlings" "$EXTRACT_DIR/bin/xlings" self install - echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" + # Append (not prepend) so the action-provided xmake keeps priority + # over the xlings-bundled one. + echo "PATH=$PATH:$HOME/.xlings/subos/current/bin" >> "$GITHUB_ENV" - - name: Install Project Dependencies via Xlings + - name: Install LLVM toolchain via Xlings run: | - xlings install - clang --version + xlings install llvm -y + which xmake && xmake --version - name: Configure xmake run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ca1a6ab..4d55b51 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ on: type: string env: - XLINGS_VERSION: v0.4.0 + XLINGS_VERSION: v0.4.51 jobs: build-linux: @@ -58,11 +58,19 @@ jobs: path: d2x-${{ inputs.version }}-linux-x86_64.tar.gz build-macos: - runs-on: macos-15 + # Build on the oldest supported macOS so the artifact also runs on newer + # releases (issue #19). The xlings-bundled xmake is built against a fixed + # SDK and crashes on older runners, so xmake comes from the official action. + runs-on: macos-14 steps: - name: Checkout code uses: actions/checkout@v4 + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest + - name: Install Xlings env: XLINGS_NON_INTERACTIVE: 1 @@ -75,18 +83,21 @@ jobs: xattr -dr com.apple.quarantine "$EXTRACT_DIR" 2>/dev/null || true chmod +x "$EXTRACT_DIR/bin/xlings" "$EXTRACT_DIR/bin/xlings" self install - echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" + # Append so the action-provided xmake keeps priority. + echo "PATH=$PATH:$HOME/.xlings/subos/current/bin" >> "$GITHUB_ENV" - - name: Install Project Dependencies via Xlings + - name: Install LLVM toolchain via Xlings run: | - xlings install + xlings install llvm -y clang --version - name: Build with xmake run: | - export LLVM_PREFIX=$HOME/.xlings/data/xpkgs/xim-x-llvm/20.1.7 - xmake f -m release --toolchain=llvm --sdk=$LLVM_PREFIX -vv -y - xmake -j$(nproc) + LLVM_ROOT="$HOME/.xlings/data/xpkgs/xim-x-llvm" + LLVM_SDK=$(find "$LLVM_ROOT" -mindepth 1 -maxdepth 1 -type d | sort -V | tail -1) + test -d "$LLVM_SDK" + xmake f -m release --toolchain=llvm --sdk="$LLVM_SDK" -vv -y + xmake -j$(sysctl -n hw.logicalcpu) - name: Verify no LLVM runtime dependency run: | diff --git a/.gitignore b/.gitignore index 700d111..75cc0d6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ build target d2x.zip +mcpp.lock +compile_commands.json diff --git a/.xlings.json b/.xlings.json index 1eb6d31..56cd039 100644 --- a/.xlings.json +++ b/.xlings.json @@ -1,6 +1,6 @@ { "workspace": { - "mcpp": { "linux": "0.0.13" }, + "mcpp": { "linux": "0.0.52" }, "xmake": "3.0.7", "gcc": { "linux": "15.1.0" }, "llvm": { "macosx": "20" } diff --git a/README.md b/README.md index 13c57d4..1e9e81f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ | --- | ```cpp -d2x version: 0.1.4 +d2x version: 0.1.5 Usage: $ d2x [command] [target] [options] diff --git a/mcpp.toml b/mcpp.toml index 966fdb6..b3adb9e 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,6 +1,6 @@ [package] name = "d2x" -version = "0.1.2" +version = "0.1.5" description = "AI-powered development assistant for C++ projects" license = "Apache-2.0" repo = "https://github.com/d2learn/d2x" diff --git a/src/cmdprocessor.cppm b/src/cmdprocessor.cppm index 0a987de..ee8fbc9 100644 --- a/src/cmdprocessor.cppm +++ b/src/cmdprocessor.cppm @@ -91,7 +91,14 @@ export int run(int argc, char* argv[]) { .action([](const cmdline::ParsedArgs& a) { apply_global_options(a); auto bookdir = std::filesystem::path(platform::get_rundir()) / "book"; - if (Config::lang() == "en") bookdir /= "en"; + // Resolve language sub-book generically (issue #8): any language + // shipped by the target project as book/ is supported, not + // just zh/en. Falls back to the default book/ when absent. + const auto& lang = Config::lang(); + if (!lang.empty() && lang != "auto") { + auto langdir = bookdir / lang; + if (std::filesystem::exists(langdir)) bookdir = langdir; + } std::println("Opening book: {}", bookdir.string()); if (std::filesystem::exists(bookdir)) { platform::run_command_capture("xlings install mdbook -y"); diff --git a/src/config.cppm b/src/config.cppm index 472c75d..8e44234 100644 --- a/src/config.cppm +++ b/src/config.cppm @@ -17,7 +17,7 @@ export struct EnvVars; export class Config; struct Info { - static constexpr std::string_view VERSION = "0.1.4"; + static constexpr std::string_view VERSION = "0.1.5"; static constexpr std::string_view REPO = "https://github.com/d2learn/d2x"; }; diff --git a/src/platform/windows.cppm b/src/platform/windows.cppm index e39bf33..e17f124 100644 --- a/src/platform/windows.cppm +++ b/src/platform/windows.cppm @@ -15,7 +15,8 @@ namespace platform_impl { export constexpr std::string_view XLINGS_INSTALL_CMD = "powershell -Command \"irm https://d2learn.org/xlings-install.ps1.txt | iex\""; export std::pair run_command_capture(const std::string& cmd) { - FILE* pipe = _popen(cmd.c_str(), "r"); + std::string full = cmd + " 2>&1"; // redirect stderr to stdout (match linux/macos) + FILE* pipe = _popen(full.c_str(), "r"); if (!pipe) { return {-1, std::string{}}; } diff --git a/xmake.lua b/xmake.lua index bef1f14..f80838e 100644 --- a/xmake.lua +++ b/xmake.lua @@ -4,8 +4,8 @@ set_languages("c++23") add_repositories("mcpplibs-index https://github.com/mcpplibs/mcpplibs-index.git") -add_requires("llmapi 0.2.5") -add_requires("mcpplibs-tinyhttps 0.2.2") +add_requires("llmapi 0.2.6") +add_requires("mcpplibs-tinyhttps 0.2.3") add_requires("mbedtls v3.6.1") add_requires("cmdline 0.0.2") add_requires("ftxui 6.1.9") From 121acf424e17bcc51f58723e11ce55c2d15437da Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 10:58:31 +0800 Subject: [PATCH 2/9] ci: build macOS with Homebrew LLVM to support macos-14 (#19) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xlings-bundled clang (20.1.7) is also built against a newer macOS SDK and aborts on macos-14 with dyld "Symbol not found: __ZdaPv" — the same OS mismatch as the xmake binary. Switch the macOS CI matrix to OS-matched toolchains: xmake from the official action + LLVM from Homebrew. Project deps come from xmake's mcpplibs-index, so xlings is no longer needed for the macOS build. release.yml: keep building the macOS artifact on macos-15 (where the xlings toolchain runs natively, preserving the no-LLVM-runtime-dep check) and only fix the previously hardcoded LLVM SDK path to be resolved dynamically. --- .github/workflows/ci.yml | 35 ++++++++++------------------------- .github/workflows/release.yml | 22 +++++++++------------- 2 files changed, 19 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82d4ab1..f11dccc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,40 +58,25 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - # Provide an OS-appropriate xmake binary. The xlings-bundled xmake is - # built against a fixed macOS SDK and crashes on older runners - # (issue #19: "built for macOS 15.5 which is newer than running OS"), - # so we install xmake via the official action and use xlings only for - # the LLVM toolchain. + # The xlings-bundled xmake AND llvm toolchain are built against a fixed + # macOS SDK and abort on older runners (issue #19): + # - xmake: "built for macOS 15.5 which is newer than running OS" + # - clang: dyld "Symbol not found: __ZdaPv" -> Abort trap: 6 on macos-14 + # Use OS-matched binaries instead: xmake from the official action and + # LLVM from Homebrew. Project deps come from xmake's mcpplibs-index, so + # xlings is not needed for the macOS build. - name: Setup xmake uses: xmake-io/github-action-setup-xmake@v1 with: xmake-version: latest - - name: Install Xlings - env: - XLINGS_NON_INTERACTIVE: 1 + - name: Install LLVM (Homebrew) run: | - TARBALL="xlings-${XLINGS_VERSION}-macosx-arm64.tar.gz" - curl -fSL -o "$RUNNER_TEMP/$TARBALL" "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${TARBALL}" - tar -xzf "$RUNNER_TEMP/$TARBALL" -C "$RUNNER_TEMP" - EXTRACT_DIR=$(find "$RUNNER_TEMP" -maxdepth 1 -type d -name "xlings-*" | head -1) - xattr -dr com.apple.quarantine "$EXTRACT_DIR" 2>/dev/null || true - chmod +x "$EXTRACT_DIR/bin/xlings" - "$EXTRACT_DIR/bin/xlings" self install - # Append (not prepend) so the action-provided xmake keeps priority - # over the xlings-bundled one. - echo "PATH=$PATH:$HOME/.xlings/subos/current/bin" >> "$GITHUB_ENV" - - - name: Install LLVM toolchain via Xlings - run: | - xlings install llvm -y - which xmake && xmake --version + brew install llvm + echo "LLVM_SDK=$(brew --prefix llvm)" >> "$GITHUB_ENV" - name: Configure xmake run: | - LLVM_ROOT="$HOME/.xlings/data/xpkgs/xim-x-llvm" - LLVM_SDK=$(find "$LLVM_ROOT" -mindepth 1 -maxdepth 1 -type d | sort -V | tail -1) test -d "$LLVM_SDK" "$LLVM_SDK/bin/clang++" --version xmake f -m release --toolchain=llvm --sdk="$LLVM_SDK" -y -vvD diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4d55b51..90b351b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,19 +58,16 @@ jobs: path: d2x-${{ inputs.version }}-linux-x86_64.tar.gz build-macos: - # Build on the oldest supported macOS so the artifact also runs on newer - # releases (issue #19). The xlings-bundled xmake is built against a fixed - # SDK and crashes on older runners, so xmake comes from the official action. - runs-on: macos-14 + # Built on macos-15, where the xlings-bundled xmake + llvm toolchain run + # natively (they are compiled against a recent macOS SDK and abort on older + # runners; see issue #19). The static-link check below keeps the artifact + # free of toolchain runtime deps. macOS 14 *build* support is exercised by + # the CI workflow (which uses Homebrew LLVM). + runs-on: macos-15 steps: - name: Checkout code uses: actions/checkout@v4 - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - - name: Install Xlings env: XLINGS_NON_INTERACTIVE: 1 @@ -83,12 +80,11 @@ jobs: xattr -dr com.apple.quarantine "$EXTRACT_DIR" 2>/dev/null || true chmod +x "$EXTRACT_DIR/bin/xlings" "$EXTRACT_DIR/bin/xlings" self install - # Append so the action-provided xmake keeps priority. - echo "PATH=$PATH:$HOME/.xlings/subos/current/bin" >> "$GITHUB_ENV" + echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" - - name: Install LLVM toolchain via Xlings + - name: Install Project Dependencies via Xlings run: | - xlings install llvm -y + xlings install clang --version - name: Build with xmake From ce7326a1685270ca5a7416628410964d833c308a Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 11:04:59 +0800 Subject: [PATCH 3/9] ci: pin Homebrew LLVM to llvm@20 (libc++ 22 breaks ) --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f11dccc..943bdf8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,8 +72,10 @@ jobs: - name: Install LLVM (Homebrew) run: | - brew install llvm - echo "LLVM_SDK=$(brew --prefix llvm)" >> "$GITHUB_ENV" + # Pin LLVM 20 to match the toolchain the project is known to build + # with; libc++ from LLVM 22+ tightens and rejects the code. + brew install llvm@20 + echo "LLVM_SDK=$(brew --prefix llvm@20)" >> "$GITHUB_ENV" - name: Configure xmake run: | From d5b4cc808991f45d35fceb5794754287b87ae478 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 11:12:31 +0800 Subject: [PATCH 4/9] ci: link toolchain libc++ on macOS so macos-14 resolves std::print symbols --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 943bdf8..83b5597 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,7 +81,12 @@ jobs: run: | test -d "$LLVM_SDK" "$LLVM_SDK/bin/clang++" --version - xmake f -m release --toolchain=llvm --sdk="$LLVM_SDK" -y -vvD + # The brew libc++ headers reference symbols (e.g. __is_posix_terminal, + # used by std::print) that the older macOS 14 SDK's system libc++ lacks. + # Link the toolchain's own libc++ runtime instead of the SDK one. + xmake f -m release --toolchain=llvm --sdk="$LLVM_SDK" \ + --ldflags="-L$LLVM_SDK/lib/c++ -L$LLVM_SDK/lib -Wl,-rpath,$LLVM_SDK/lib/c++ -Wl,-rpath,$LLVM_SDK/lib" \ + -y -vvD - name: Build with xmake run: xmake -a -j"$(sysctl -n hw.logicalcpu)" From f331991074d5270f7f4e875927f91145f239cbaf Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 11:34:25 +0800 Subject: [PATCH 5/9] ci: add checker smoke test (issue #24); release linux via mcpp - ci.yml: new `checker-smoke (linux)` job builds d2x, checks out the d2mcpp course, and runs `d2x checker` against it under a 120s timeout, asserting it reaches and reports the FIRST exercise's build error rather than hanging on the init log. The checker waits for edits forever, so the timeout kill is the expected healthy outcome; we only assert output was produced. - release.yml: build the Linux artifact with `mcpp build --static` (matching the CI build path) instead of xmake, producing a statically-linked binary; add a version-assert guard so a release never ships a mismatched d2x --version. --- .github/workflows/ci.yml | 61 +++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 24 ++++++++++---- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83b5597..91a40c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,3 +114,64 @@ jobs: - name: Verify d2x run: | build\windows\x64\release\d2x.exe --version + + # Smoke test: a real `d2x checker` run against the d2mcpp course must reach + # and report the FIRST exercise's build error within a bounded window, rather + # than hanging on the init log (issue #24). The checker waits for file edits + # forever, so a timeout kill is the expected, healthy outcome. + checker-smoke: + name: checker smoke (linux) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install xlings + run: | + tarball="xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" + curl -fsSL -o "/tmp/${tarball}" \ + "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${tarball}" + tar -xzf "/tmp/${tarball}" -C /tmp + "/tmp/xlings-${XLINGS_VERSION}-linux-x86_64/subos/default/bin/xlings" self install + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" + + - name: Refresh package index + run: xlings update + + - name: Build d2x with mcpp + run: | + xlings install -y + mcpp build + + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest + + - name: Checkout d2mcpp course + uses: actions/checkout@v4 + with: + repository: mcpp-community/d2mcpp + path: d2mcpp + + - name: Run d2x checker (must reach first exercise, not hang on load) + run: | + D2X="$PWD/$(find target -name d2x -type f | head -1)" + test -x "$D2X" || chmod +x "$D2X" + cd d2mcpp + # Force the print UI so output is plain text in a non-TTY runner. + sed -i 's/"ui_backend": *"tui"/"ui_backend": "print"/' .d2x.json || true + xmake f -y + set +e + timeout 120 "$D2X" checker --ui print --lang en > checker.out 2>&1 + code=$? + set -e + echo "checker exit=$code (124 = killed by timeout while waiting for edits = expected)" + echo "------------------ checker output (tail) ------------------" + tail -n 40 checker.out || true + echo "-----------------------------------------------------------" + if grep -q "hello-mcpp" checker.out && grep -qiE "error" checker.out; then + echo "OK: checker reached and reported the first exercise (not stuck on the loading log)" + else + echo "FAIL: checker produced no exercise build output within the window (stuck on load?)" + exit 1 + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90b351b..c4a3772 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,19 +36,29 @@ jobs: "$EXTRACT_DIR/bin/xlings" self install echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" - - name: Install Project Dependencies via Xlings - run: | - xlings install + - name: Refresh package index + run: xlings update - - name: Build with xmake + - name: Install workspace tools (.xlings.json -> mcpp) + run: xlings install -y + + - name: Build with mcpp (static) + run: mcpp build --static + + - name: Locate & verify binary run: | - xmake f -m release -y - xmake -j$(nproc) + BIN=$(find target -name d2x -type f | head -1) + test -n "$BIN" || { echo "d2x binary not found"; find target -type f | head; exit 1; } + chmod +x "$BIN" + ver=$("$BIN" --version) + echo "built d2x version: $ver (release input: ${{ inputs.version }})" + test "$ver" = "${{ inputs.version }}" || { echo "ERROR: binary version ($ver) != release version (${{ inputs.version }})"; exit 1; } + echo "BIN=$BIN" >> "$GITHUB_ENV" - name: Create release package run: | mkdir -p d2x-${{ inputs.version }}-linux-x86_64 - cp build/linux/x86_64/release/d2x d2x-${{ inputs.version }}-linux-x86_64/ + cp "$BIN" d2x-${{ inputs.version }}-linux-x86_64/ tar -czf d2x-${{ inputs.version }}-linux-x86_64.tar.gz d2x-${{ inputs.version }}-linux-x86_64 - name: Upload artifact From d0e92a50d227237a618d99460fb24b9e70c21a04 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 11:40:59 +0800 Subject: [PATCH 6/9] ci: install xmake via xlings in checker-smoke (avoid setup-xmake source build) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91a40c1..49dfc0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -142,10 +142,10 @@ jobs: xlings install -y mcpp build - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest + - name: Install xmake (via xlings, for the d2mcpp build path) + run: | + xlings install xmake -y + xmake --version - name: Checkout d2mcpp course uses: actions/checkout@v4 From d928ca3956c5aaea8e3319ac903517cc671c6212 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 11:48:21 +0800 Subject: [PATCH 7/9] ci: use standalone xmake in checker-smoke (d2mcpp pins removed xmake 3.0.7) --- .github/workflows/ci.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49dfc0b..94ccef1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -142,10 +142,16 @@ jobs: xlings install -y mcpp build - - name: Install xmake (via xlings, for the d2mcpp build path) + # Use a real xmake (not the xlings `xmake` shim): d2mcpp's .xlings.json + # pins xmake 3.0.7, which is gone from the registry, so the shim would + # fail to resolve. A standalone xmake ignores .xlings.json. Put it ahead + # of the xlings bin on PATH. + - name: Install xmake run: | - xlings install xmake -y - xmake --version + curl -fsSL https://xmake.io/shget.text | bash + source ~/.xmake/profile 2>/dev/null || true + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + "$HOME/.local/bin/xmake" --version - name: Checkout d2mcpp course uses: actions/checkout@v4 From 3af11574ee0107ff810bcc558c707f4f07c8ae82 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 11:53:45 +0800 Subject: [PATCH 8/9] ci: build d2x via mcpp on all platforms (drop xmake) Switch the macOS (macos-14/15) and Windows build jobs from xmake to the same mcpp path already used on Linux, and pin mcpp for macosx/windows in .xlings.json. The d2mcpp checker buildtool (xmake d2x-buildtools) is unrelated and unchanged. --- .github/workflows/ci.yml | 97 ++++++++++++++++++++-------------------- .xlings.json | 5 +-- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94ccef1..6581727 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,72 +48,73 @@ jobs: "$binary" --version build-macos: - name: build (${{ matrix.os }}, xmake/llvm) + name: build (${{ matrix.os }}, mcpp) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [macos-14, macos-15] steps: - - name: Checkout code - uses: actions/checkout@v4 - - # The xlings-bundled xmake AND llvm toolchain are built against a fixed - # macOS SDK and abort on older runners (issue #19): - # - xmake: "built for macOS 15.5 which is newer than running OS" - # - clang: dyld "Symbol not found: __ZdaPv" -> Abort trap: 6 on macos-14 - # Use OS-matched binaries instead: xmake from the official action and - # LLVM from Homebrew. Project deps come from xmake's mcpplibs-index, so - # xlings is not needed for the macOS build. - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest + - uses: actions/checkout@v4 - - name: Install LLVM (Homebrew) + - name: Install xlings + env: + XLINGS_NON_INTERACTIVE: 1 run: | - # Pin LLVM 20 to match the toolchain the project is known to build - # with; libc++ from LLVM 22+ tightens and rejects the code. - brew install llvm@20 - echo "LLVM_SDK=$(brew --prefix llvm@20)" >> "$GITHUB_ENV" + TARBALL="xlings-${XLINGS_VERSION}-macosx-arm64.tar.gz" + curl -fSL -o "$RUNNER_TEMP/$TARBALL" "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${TARBALL}" + tar -xzf "$RUNNER_TEMP/$TARBALL" -C "$RUNNER_TEMP" + EXTRACT_DIR=$(find "$RUNNER_TEMP" -maxdepth 1 -type d -name "xlings-*" | head -1) + xattr -dr com.apple.quarantine "$EXTRACT_DIR" 2>/dev/null || true + chmod +x "$EXTRACT_DIR/bin/xlings" + "$EXTRACT_DIR/bin/xlings" self install + echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" - - name: Configure xmake - run: | - test -d "$LLVM_SDK" - "$LLVM_SDK/bin/clang++" --version - # The brew libc++ headers reference symbols (e.g. __is_posix_terminal, - # used by std::print) that the older macOS 14 SDK's system libc++ lacks. - # Link the toolchain's own libc++ runtime instead of the SDK one. - xmake f -m release --toolchain=llvm --sdk="$LLVM_SDK" \ - --ldflags="-L$LLVM_SDK/lib/c++ -L$LLVM_SDK/lib -Wl,-rpath,$LLVM_SDK/lib/c++ -Wl,-rpath,$LLVM_SDK/lib" \ - -y -vvD - - - name: Build with xmake - run: xmake -a -j"$(sysctl -n hw.logicalcpu)" + - name: Refresh package index + run: xlings update + + - name: Install workspace tools (.xlings.json -> mcpp ${{ env.MCPP_VERSION }}) + run: xlings install -y + + - name: Build with mcpp + run: mcpp build - name: Verify d2x run: | - ./build/macosx/arm64/release/d2x --version + BIN=$(find target -name d2x -type f | head -1) + test -n "$BIN" || { echo "d2x binary not found"; find target -type f | head -20; exit 1; } + chmod +x "$BIN" + "$BIN" --version build-windows: + name: build (windows x86_64, mcpp) runs-on: windows-latest + defaults: + run: + shell: bash + env: + XLINGS_NON_INTERACTIVE: 1 steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - - - name: Build with xmake - run: | - xmake f -m release -y - xmake -j$env:NUMBER_OF_PROCESSORS + - uses: actions/checkout@v4 - - name: Verify d2x + # Everything in one bash step so the in-process PATH is used directly + # (avoids cross-step PATH translation issues for the msys/Windows mix). + - name: Install xlings and build with mcpp run: | - build\windows\x64\release\d2x.exe --version + set -e + ZIP="xlings-${XLINGS_VERSION}-windows-x86_64.zip" + curl -fSL -o "$RUNNER_TEMP/$ZIP" "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/${ZIP}" + unzip -q "$RUNNER_TEMP/$ZIP" -d "$RUNNER_TEMP/xl" + XL=$(find "$RUNNER_TEMP/xl" -name 'xlings.exe' | head -1) + echo "xlings: $XL" + "$XL" self install + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xlings update + xlings install -y + mcpp build + D2X=$(find target -name 'd2x.exe' -type f | head -1) + test -n "$D2X" || { echo "d2x.exe not found"; find target -type f | head -20; exit 1; } + "$D2X" --version # Smoke test: a real `d2x checker` run against the d2mcpp course must reach # and report the FIRST exercise's build error within a bounded window, rather diff --git a/.xlings.json b/.xlings.json index 56cd039..e88cf7b 100644 --- a/.xlings.json +++ b/.xlings.json @@ -1,8 +1,5 @@ { "workspace": { - "mcpp": { "linux": "0.0.52" }, - "xmake": "3.0.7", - "gcc": { "linux": "15.1.0" }, - "llvm": { "macosx": "20" } + "mcpp": { "linux": "0.0.52", "macosx": "0.0.52", "windows": "0.0.52" } } } From 9439bbbed455c4b4d71c3a50ba01ce0109baff90 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Mon, 8 Jun 2026 12:08:16 +0800 Subject: [PATCH 9/9] release+chore: build release artifacts via mcpp; remove xmake.lua - release.yml: macOS and Windows release jobs now build with mcpp (matching CI and the Linux release job), with a version-assert guard. macOS builds on macos-14 so the artifact runs on macOS 14+. - Delete xmake.lua: d2x is now built exclusively via mcpp (mcpp.toml) across local/CI/release. The buildtools/xmake plugin (the d2x-buildtools deliverable for d2x-type courses) and the d2mcpp checker path are unaffected. --- .github/workflows/release.yml | 81 +++++++++++++++++++---------------- xmake.lua | 27 ------------ 2 files changed, 44 insertions(+), 64 deletions(-) delete mode 100644 xmake.lua diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4a3772..eb1ef5c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -68,12 +68,9 @@ jobs: path: d2x-${{ inputs.version }}-linux-x86_64.tar.gz build-macos: - # Built on macos-15, where the xlings-bundled xmake + llvm toolchain run - # natively (they are compiled against a recent macOS SDK and abort on older - # runners; see issue #19). The static-link check below keeps the artifact - # free of toolchain runtime deps. macOS 14 *build* support is exercised by - # the CI workflow (which uses Homebrew LLVM). - runs-on: macos-15 + # Built on the oldest supported macOS so the artifact also runs on newer + # releases. mcpp manages its own toolchain, so no SDK pinning is needed. + runs-on: macos-14 steps: - name: Checkout code uses: actions/checkout@v4 @@ -92,33 +89,29 @@ jobs: "$EXTRACT_DIR/bin/xlings" self install echo "PATH=$HOME/.xlings/subos/current/bin:$PATH" >> "$GITHUB_ENV" - - name: Install Project Dependencies via Xlings - run: | - xlings install - clang --version + - name: Refresh package index + run: xlings update - - name: Build with xmake - run: | - LLVM_ROOT="$HOME/.xlings/data/xpkgs/xim-x-llvm" - LLVM_SDK=$(find "$LLVM_ROOT" -mindepth 1 -maxdepth 1 -type d | sort -V | tail -1) - test -d "$LLVM_SDK" - xmake f -m release --toolchain=llvm --sdk="$LLVM_SDK" -vv -y - xmake -j$(sysctl -n hw.logicalcpu) + - name: Install workspace tools (.xlings.json -> mcpp) + run: xlings install -y - - name: Verify no LLVM runtime dependency + - name: Build with mcpp + run: mcpp build + + - name: Locate & verify binary run: | - BIN=build/macosx/arm64/release/d2x - if otool -L "$BIN" | grep -q "llvm"; then - otool -L "$BIN" - echo "FAIL: binary links against LLVM dylib" - exit 1 - fi - echo "OK: binary has no LLVM runtime dependency" + BIN=$(find target -name d2x -type f | head -1) + test -n "$BIN" || { echo "d2x binary not found"; find target -type f | head; exit 1; } + chmod +x "$BIN" + ver=$("$BIN" --version) + echo "built d2x version: $ver (release input: ${{ inputs.version }})" + test "$ver" = "${{ inputs.version }}" || { echo "ERROR: binary version ($ver) != release version (${{ inputs.version }})"; exit 1; } + echo "BIN=$BIN" >> "$GITHUB_ENV" - name: Create release package run: | mkdir -p d2x-${{ inputs.version }}-macosx-arm64 - cp build/macosx/arm64/release/d2x d2x-${{ inputs.version }}-macosx-arm64/ + cp "$BIN" d2x-${{ inputs.version }}-macosx-arm64/ tar -czf d2x-${{ inputs.version }}-macosx-arm64.tar.gz d2x-${{ inputs.version }}-macosx-arm64 - name: Upload artifact @@ -129,25 +122,39 @@ jobs: build-windows: runs-on: windows-latest + defaults: + run: + shell: bash + env: + XLINGS_NON_INTERACTIVE: 1 steps: - name: Checkout code uses: actions/checkout@v4 - - name: Setup xmake - uses: xmake-io/github-action-setup-xmake@v1 - with: - xmake-version: latest - - - name: Build with xmake + - name: Install xlings and build with mcpp run: | - xmake f -m release -y - xmake -j$env:NUMBER_OF_PROCESSORS + set -e + VERSION_NUM="${XLINGS_VERSION#v}" + ZIP="xlings-${VERSION_NUM}-windows-x86_64.zip" + curl -fSL -o "$RUNNER_TEMP/$ZIP" "https://github.com/d2learn/xlings/releases/download/${XLINGS_VERSION}/${ZIP}" + unzip -q "$RUNNER_TEMP/$ZIP" -d "$RUNNER_TEMP/xl" + XL=$(find "$RUNNER_TEMP/xl" -name 'xlings.exe' | head -1) + "$XL" self install + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xlings update + xlings install -y + mcpp build + D2X=$(find target -name 'd2x.exe' -type f | head -1) + test -n "$D2X" || { echo "d2x.exe not found"; find target -type f | head; exit 1; } + ver=$("$D2X" --version) + echo "built d2x version: $ver (release input: ${{ inputs.version }})" + test "$ver" = "${{ inputs.version }}" || { echo "ERROR: binary version ($ver) != release version (${{ inputs.version }})"; exit 1; } + mkdir -p "d2x-${{ inputs.version }}-windows-x86_64" + cp "$D2X" "d2x-${{ inputs.version }}-windows-x86_64/" - - name: Create release package + - name: Zip release package shell: pwsh run: | - New-Item -ItemType Directory -Path "d2x-${{ inputs.version }}-windows-x86_64" -Force - Copy-Item "build\windows\x64\release\d2x.exe" -Destination "d2x-${{ inputs.version }}-windows-x86_64\" Compress-Archive -Path "d2x-${{ inputs.version }}-windows-x86_64" -DestinationPath "d2x-${{ inputs.version }}-windows-x86_64.zip" - name: Upload artifact diff --git a/xmake.lua b/xmake.lua deleted file mode 100644 index f80838e..0000000 --- a/xmake.lua +++ /dev/null @@ -1,27 +0,0 @@ -add_rules("mode.debug", "mode.release") - -set_languages("c++23") - -add_repositories("mcpplibs-index https://github.com/mcpplibs/mcpplibs-index.git") - -add_requires("llmapi 0.2.6") -add_requires("mcpplibs-tinyhttps 0.2.3") -add_requires("mbedtls v3.6.1") -add_requires("cmdline 0.0.2") -add_requires("ftxui 6.1.9") - -target("d2x") - set_kind("binary") - - add_files("src/main.cpp") - -- add common module interface units - add_files("src/**.cppm") - add_packages("ftxui", "llmapi", "mcpplibs-tinyhttps", "mbedtls", "cmdline") - set_policy("build.c++.modules", true) - - -- platform specific settings - if is_plat("macosx") then - set_toolchains("llvm") - elseif is_plat("linux") then - add_ldflags("-static", {force = true}) - end