diff --git a/.agents/skills/mcpplibs-index-add.md b/.agents/skills/mcpplibs-index-add.md index f5e4da3..b9477cc 100644 --- a/.agents/skills/mcpplibs-index-add.md +++ b/.agents/skills/mcpplibs-index-add.md @@ -14,6 +14,7 @@ This skill adds a new library from `https://github.com/mcpplibs/` to the m - xmake package docs: https://xmake.io/mirror/manual/package_dependencies.html - mcpplibs org: https://github.com/mcpplibs - index repo: https://github.com/mcpplibs/mcpplibs-index +- xlings CI reference (cross-platform C++23 toolchain): https://github.com/d2learn/xlings/tree/main/.github/workflows ## Step 1: Gather Library Info @@ -110,7 +111,11 @@ Add an `includes()` line to `tests/xmake.lua`: includes("/") ``` -## Step 6: Verify Build +## Step 6: Update CI + +Add a new job to `.github/workflows/ci.yml` for the package. Each package has its own job with path-based triggering. Add path filter in `detect-changes` job and a new job block (see existing jobs as template). Also add the package paths to the top-level `on.push.paths` and `on.pull_request.paths`. + +## Step 7: Verify Build ```bash # Clean any cached package @@ -129,20 +134,69 @@ xmake run _test All three commands must succeed before proceeding. -## Step 7: Create Branch, Commit & Push +## Step 8: Create Branch, Commit & Push ```bash git checkout -b add--library git add packages///xmake.lua \ tests///xmake.lua \ tests///main.cpp \ - tests/xmake.lua + tests/xmake.lua \ + .github/workflows/ci.yml git commit -m "add library" git push -u upstream add--library ``` Use `upstream` (SSH remote) for push, not `origin` (HTTPS, no auth). +## C++23 Toolchain Reference + +All mcpplibs packages require C++23 with modules support. Below are the toolchain configurations for each platform, referenced from [xlings CI](https://github.com/d2learn/xlings/tree/main/.github/workflows). + +All toolchains are installed via [xlings](https://github.com/d2learn/xlings). xlings bundles xmake, no separate install needed. + +### Install xlings + +```bash +# Linux / macOS +curl -fsSL https://raw.githubusercontent.com/d2learn/xlings/main/tools/other/quick_install.sh | bash +export PATH="$HOME/.xlings/subos/current/bin:$PATH" + +# Windows (PowerShell) +irm https://raw.githubusercontent.com/d2learn/xlings/refs/heads/main/tools/other/quick_install.ps1 | iex +$env:PATH = "$env:USERPROFILE\.xlings\subos\current\bin;$env:PATH" +``` + +### Linux — GCC 15 (Ubuntu 24.04) + +```bash +xlings install gcc@15 -y +xmake f -y +``` + +### macOS — LLVM 20 (macOS 15) + +```bash +xlings install llvm@20 -y +xmake f -y +``` + +### Windows — MSVC (windows-latest) + +```bash +xmake f -y # auto-selects MSVC +``` + +No special configuration needed. MSVC from Visual Studio supports C++23. + +### Toolchain Version Summary + +| Platform | Compiler | Version | Install | +|----------|----------|---------|---------| +| Linux | GCC | 15.1.0 | `xlings install gcc@15 -y` | +| macOS | LLVM/Clang | 20 | `xlings install llvm@20 -y` | +| Windows | MSVC | latest | auto-detected | + ## Checklist - [ ] Package directory name == `package("xxx")` name @@ -151,6 +205,7 @@ Use `upstream` (SSH remote) for push, not `origin` (HTTPS, no auth). - [ ] Extra headers copied in `on_install` if needed by cppm - [ ] Test does NOT have `add_repositories()` (top-level handles it) - [ ] Test registered in `tests/xmake.lua` via `includes()` +- [ ] CI matrix updated with new test entry - [ ] `xmake build` succeeds - [ ] `xmake run` produces expected output - [ ] Committed and pushed to upstream diff --git a/.github/actions/setup-toolchain/action.yml b/.github/actions/setup-toolchain/action.yml new file mode 100644 index 0000000..d5e7001 --- /dev/null +++ b/.github/actions/setup-toolchain/action.yml @@ -0,0 +1,54 @@ +name: Setup C++23 Toolchain +description: Install xlings and C++23 toolchain for the current platform + +runs: + using: composite + steps: + - name: Setup (linux) + if: runner.os == 'Linux' + shell: bash + run: | + LATEST_VERSION=$(gh release view --repo d2learn/xlings --json tagName -q '.tagName') + VERSION_NUM=${LATEST_VERSION#v} + TARBALL="xlings-${VERSION_NUM}-linux-x86_64.tar.gz" + gh release download "$LATEST_VERSION" --repo d2learn/xlings --pattern "$TARBALL" --dir /tmp + mkdir -p "$HOME/.xlings" + tar -xzf "/tmp/$TARBALL" -C "$HOME/.xlings" --strip-components=1 + "$HOME/.xlings/bin/xlings" self install + env: + GH_TOKEN: ${{ github.token }} + + - name: Setup (macos) + if: runner.os == 'macOS' + shell: bash + run: | + LATEST_VERSION=$(gh release view --repo d2learn/xlings --json tagName -q '.tagName') + VERSION_NUM=${LATEST_VERSION#v} + ARCH=$(uname -m) + TARBALL="xlings-${VERSION_NUM}-macosx-${ARCH}.tar.gz" + gh release download "$LATEST_VERSION" --repo d2learn/xlings --pattern "$TARBALL" --dir /tmp + mkdir -p "$HOME/.xlings" + tar -xzf "/tmp/$TARBALL" -C "$HOME/.xlings" --strip-components=1 + xattr -dr com.apple.quarantine "$HOME/.xlings" 2>/dev/null || true + "$HOME/.xlings/bin/xlings" self install + env: + GH_TOKEN: ${{ github.token }} + + - name: Setup (windows) + if: runner.os == 'Windows' + shell: pwsh + run: irm https://raw.githubusercontent.com/d2learn/xlings/refs/heads/main/tools/other/quick_install.ps1 | iex + + - name: Install toolchain (linux) + if: runner.os == 'Linux' + shell: bash + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xlings install gcc@15 -y + + - name: Install toolchain (macos) + if: runner.os == 'macOS' + shell: bash + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xlings install llvm@20 -y diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3d91f9e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,152 @@ +name: CI + +on: + push: + branches: [main] + paths: + - 'packages/**' + - 'tests/**' + - '.github/workflows/ci.yml' + pull_request: + branches: [main] + paths: + - 'packages/**' + - 'tests/**' + - '.github/workflows/ci.yml' + +env: + XLINGS_NON_INTERACTIVE: 1 + +jobs: + detect-changes: + runs-on: ubuntu-24.04 + outputs: + templates: ${{ steps.filter.outputs.templates }} + cmdline: ${{ steps.filter.outputs.cmdline }} + llmapi: ${{ steps.filter.outputs.llmapi }} + lua: ${{ steps.filter.outputs.lua }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + templates: + - 'packages/t/templates/**' + - 'tests/t/templates/**' + - '.github/workflows/ci.yml' + cmdline: + - 'packages/c/cmdline/**' + - 'tests/c/cmdline/**' + - '.github/workflows/ci.yml' + llmapi: + - 'packages/l/llmapi/**' + - 'tests/l/llmapi/**' + - '.github/workflows/ci.yml' + lua: + - 'packages/m/mcpplibs-capi-lua/**' + - 'tests/l/lua/**' + - '.github/workflows/ci.yml' + + build: + needs: detect-changes + if: >- + needs.detect-changes.outputs.templates == 'true' || + needs.detect-changes.outputs.cmdline == 'true' || + needs.detect-changes.outputs.llmapi == 'true' || + needs.detect-changes.outputs.lua == 'true' + strategy: + fail-fast: false + matrix: + include: + - { os: ubuntu-24.04, shell: bash } + - { os: macos-15, shell: bash } + - { os: windows-latest, shell: pwsh } + runs-on: ${{ matrix.os }} + name: build (${{ matrix.os }}) + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-toolchain + + - name: Configure (linux) + if: runner.os == 'Linux' + working-directory: tests + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xmake f -P . -y + + - name: Configure (macos) + if: runner.os == 'macOS' + working-directory: tests + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xmake f -P . -y --toolchain=llvm + + - name: Configure (windows) + if: runner.os == 'Windows' + working-directory: tests + run: | + $env:PATH = "$env:USERPROFILE\.xlings\subos\current\bin;$env:PATH" + xmake f -P . -y + + # templates + - name: templates (unix) + if: runner.os != 'Windows' && needs.detect-changes.outputs.templates == 'true' + working-directory: tests + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xmake build -P . -y templates_test + xmake run -P . templates_test + - name: templates (windows) + if: runner.os == 'Windows' && needs.detect-changes.outputs.templates == 'true' + working-directory: tests + run: | + $env:PATH = "$env:USERPROFILE\.xlings\subos\current\bin;$env:PATH" + xmake build -P . -y templates_test + xmake run -P . templates_test + + # cmdline + - name: cmdline (unix) + if: runner.os != 'Windows' && needs.detect-changes.outputs.cmdline == 'true' + working-directory: tests + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xmake build -P . -y cmdline_test + xmake run -P . cmdline_test test_input + - name: cmdline (windows) + if: runner.os == 'Windows' && needs.detect-changes.outputs.cmdline == 'true' + working-directory: tests + run: | + $env:PATH = "$env:USERPROFILE\.xlings\subos\current\bin;$env:PATH" + xmake build -P . -y cmdline_test + xmake run -P . cmdline_test test_input + + # llmapi (build only, needs API key to run) + - name: llmapi (unix) + if: runner.os != 'Windows' && needs.detect-changes.outputs.llmapi == 'true' + working-directory: tests + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xmake build -P . -y llmapi_test + - name: llmapi (windows) + if: runner.os == 'Windows' && needs.detect-changes.outputs.llmapi == 'true' + working-directory: tests + run: | + $env:PATH = "$env:USERPROFILE\.xlings\subos\current\bin;$env:PATH" + xmake build -P . -y llmapi_test + + # lua + - name: lua (unix) + if: runner.os != 'Windows' && needs.detect-changes.outputs.lua == 'true' + working-directory: tests + run: | + export PATH="$HOME/.xlings/subos/current/bin:$PATH" + xmake build -P . -y lua_test + xmake run -P . lua_test + - name: lua (windows) + if: runner.os == 'Windows' && needs.detect-changes.outputs.lua == 'true' + working-directory: tests + run: | + $env:PATH = "$env:USERPROFILE\.xlings\subos\current\bin;$env:PATH" + xmake build -P . -y lua_test + xmake run -P . lua_test diff --git a/packages/l/llmapi/xmake.lua b/packages/l/llmapi/xmake.lua index 7125b97..553b876 100644 --- a/packages/l/llmapi/xmake.lua +++ b/packages/l/llmapi/xmake.lua @@ -14,15 +14,10 @@ package("llmapi") add_versions("0.0.1", "174f86d3afdf48a57ad1cc9688718d1f1100a78a7e56686c823c573c3ccf99f4") - add_configs("capi", {description = "Link with llmapi_c (C API) by default", default = false, type = "boolean"}) - add_includedirs("include") add_deps("libcurl 8.11.0") on_load(function (package) - if package:config("capi") then - package:add("links", "llmapi_c") - end package:add("links", "llmapi") end) diff --git a/tests/l/llmapi/capi/main.c b/tests/l/llmapi/capi/main.c deleted file mode 100644 index 3083e50..0000000 --- a/tests/l/llmapi/capi/main.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - -#include "llmapi.h" - -void stream_print(const char* s, size_t len, void* data) { - printf("%.*s", (int)len, s); - fflush(stdout); -} - -int main(void) { - llmapi_client_t* c = llmapi_client_create(getenv("OPENAI_API_KEY"), LLMAPI_URL_POE); - - c->set_model(c, "gpt-5"); - c->add_system_message(c, "You are a helpful assistant."); - c->add_user_message(c, "In one sentence, introduce modern C++. 并给出中文翻译"); - c->request_stream(c, stream_print, NULL); - - c->destroy(c); - return 0; -} \ No newline at end of file diff --git a/tests/l/llmapi/capi/xmake.lua b/tests/l/llmapi/capi/xmake.lua deleted file mode 100644 index 6e7d642..0000000 --- a/tests/l/llmapi/capi/xmake.lua +++ /dev/null @@ -1,6 +0,0 @@ -add_requires("llmapi 0.0.1", {configs = { capi = true }}) - -target("llmapi_test_c") - set_kind("binary") - add_files("main.c") - add_packages("llmapi") \ No newline at end of file diff --git a/tests/xmake.lua b/tests/xmake.lua index 290f15d..f20ce2d 100644 --- a/tests/xmake.lua +++ b/tests/xmake.lua @@ -1,7 +1,6 @@ add_repositories("mcpplibs-index ../") includes("l/llmapi") -includes("l/llmapi/capi") includes("l/lua") includes("c/cmdline") includes("t/templates")