diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-linux.yml similarity index 91% rename from .github/workflows/ci.yml rename to .github/workflows/ci-linux.yml index c98c7f3..36bd0b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-linux.yml @@ -1,9 +1,11 @@ -name: ci +name: ci-linux -# Self-host CI: mcpp builds mcpp. The bootstrap mcpp comes from -# `xlings install mcpp` (xim:mcpp in the xlings package index), so -# this workflow no longer depends on a previous-release tarball — the +# Self-host CI on Linux: mcpp builds mcpp. The bootstrap mcpp comes from +# `xlings install mcpp` (xim:mcpp in the xlings package index), so this +# workflow no longer depends on a previous-release tarball — the # chicken-and-egg now lives upstream in the xlings index. +# +# Paired workflows: ci-macos.yml, ci-windows.yml. on: push: @@ -104,6 +106,12 @@ jobs: "$MCPP_FRESH" test - name: E2E suite + # Step-level guard: a single hung test (historically 10_env_command.sh + # on slow xlings/network) used to eat the full 60-min job budget. + # Cap the suite at 25 min so a hang fails fast and we still have room + # for the downstream toolchain steps. Per-test 600s timeout lives in + # tests/e2e/run_all.sh and identifies WHICH test hung. + timeout-minutes: 25 run: | # Point the e2e runner at the freshly-built binary, not the # bootstrap one. Tests cd into mktemp -d, so $MCPP must be diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 116f154..00427ee 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -292,6 +292,9 @@ jobs: "$MCPP" test - name: E2E suite + # See ci-linux.yml — fail-fast on hung tests instead of burning the + # whole job budget. Per-test 600s timeout lives in run_all.sh. + timeout-minutes: 25 run: | MCPP=$(find target -path "*/bin/mcpp" | head -1) MCPP=$(cd "$(dirname "$MCPP")" && pwd)/$(basename "$MCPP") diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index c74b862..4796bb1 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -1,6 +1,6 @@ name: ci-windows -# Windows CI for mcpp — same flow as Linux (ci.yml) and macOS (ci-macos.yml): +# Windows CI for mcpp — same flow as Linux (ci-linux.yml) and macOS (ci-macos.yml): # xlings install mcpp → self-host build → E2E → smoke → package on: @@ -178,6 +178,9 @@ jobs: - name: E2E suite shell: bash + # See ci-linux.yml — fail-fast on hung tests instead of burning the + # whole job budget. Per-test 600s timeout lives in run_all.sh. + timeout-minutes: 25 run: | export MCPP="$MCPP_SELF" export MCPP_VENDORED_XLINGS="$XLINGS_BIN" diff --git a/README.md b/README.md index 367c1d4..20f9ce1 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,14 @@ [![Release](https://img.shields.io/github/v/release/mcpp-community/mcpp)](https://github.com/mcpp-community/mcpp/releases) [![C++23](https://img.shields.io/badge/C%2B%2B-23-blue.svg)](https://en.cppreference.com/w/cpp/23) -[![Self-hosted](https://img.shields.io/badge/build-self--hosted-brightgreen)]() [![Module](https://img.shields.io/badge/module-ok-green.svg)](https://en.cppreference.com/w/cpp/language/modules) [![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](LICENSE) +| [文档](docs/) · [快速开始](docs/00-getting-started.md) · [mcpp.toml 指南](docs/05-mcpp-toml.md) · [示例项目](docs/01-examples.md) · [工具链管理](docs/03-toolchains.md) | +|:---:| +| [包索引 mcpp-index](https://github.com/mcpp-community/mcpp-index) · [模块化库 mcpplibs](https://github.com/mcpplibs) · [社区论坛](https://forum.d2learn.org/category/20) · [Issues](https://github.com/mcpp-community/mcpp/issues) · [Releases](https://github.com/mcpp-community/mcpp/releases) | +| [![ci-linux](https://github.com/mcpp-community/mcpp/actions/workflows/ci-linux.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-linux.yml) [![ci-macos](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml) [![ci-windows](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml) | +

mcpp demo

@@ -209,12 +213,16 @@ import mcpplibs.cmdline; | Linux aarch64 | 🔄 | 🔄 | 🔄 | — | | macOS arm64 | — | — | ✅ *默认* | — | | macOS x86_64 | — | — | 🔄 | — | -| Windows | — | — | 🔄 | 🔄 | +| Windows x86_64 | — | — | ✅ ¹ *默认* | 🔄 | ✅ 已支持 | 🔄 计划中 > *默认*:Linux 默认工具链为 musl-gcc,release 二进制走 musl 全静态; -> macOS ARM64 默认工具链为 LLVM/Clang。 +> macOS ARM64 / Windows x86_64 默认工具链均为 LLVM/Clang。 +> +> ¹ Windows 上 Clang/LLVM 当前依赖系统已安装 **MSVC BuildTools 或 Visual Studio** +> (提供 UCRT、Windows SDK、MSVC STL)。零-MSVC 依赖的 `llvm-mingw` 路线在规划中 +> ([讨论](https://github.com/mcpp-community/mcpp/issues))。 ## 文档 diff --git a/tests/e2e/run_all.sh b/tests/e2e/run_all.sh index 29cc389..c3d7d5a 100755 --- a/tests/e2e/run_all.sh +++ b/tests/e2e/run_all.sh @@ -123,10 +123,28 @@ check_requires() { return 1 # all satisfied → don't skip } +# Per-test timeout: bail out of an individual test that gets stuck (e.g. +# 10_env_command.sh has been observed hanging for the full job budget on +# slow xlings/network combinations). 600s default; override via env. +# Linux + git-bash on Windows have GNU `timeout`; macOS may need `gtimeout` +# (coreutils). If neither is present, we run without a wrapper and rely on +# the step-level GitHub Actions timeout-minutes as the backstop. +E2E_TEST_TIMEOUT="${E2E_TEST_TIMEOUT:-600}" +TIMEOUT_CMD="" +if command -v timeout &>/dev/null; then TIMEOUT_CMD=timeout +elif command -v gtimeout &>/dev/null; then TIMEOUT_CMD=gtimeout +fi +if [[ -n "$TIMEOUT_CMD" ]]; then + echo "Per-test timeout: ${E2E_TEST_TIMEOUT}s (via $TIMEOUT_CMD)" +else + echo "Per-test timeout: (no timeout/gtimeout on PATH)" +fi + PASS=0 FAIL=0 SKIP=0 FAILED_TESTS=() +TIMED_OUT_TESTS=() for test in "$HERE"/[0-9]*.sh; do name="$(basename "$test")" @@ -138,21 +156,36 @@ for test in "$HERE"/[0-9]*.sh; do continue fi echo "=== $name ===" - if MCPP="$MCPP" bash "$test"; then + if [[ -n "$TIMEOUT_CMD" ]]; then + MCPP="$MCPP" "$TIMEOUT_CMD" "$E2E_TEST_TIMEOUT" bash "$test" + else + MCPP="$MCPP" bash "$test" + fi + rc=$? + if [[ $rc -eq 0 ]]; then echo "PASS: $name" ((PASS++)) + elif [[ $rc -eq 124 ]]; then + # GNU timeout: 124 = killed after deadline (TERM); 137 = SIGKILL after grace. + echo "TIMEOUT: $name (exceeded ${E2E_TEST_TIMEOUT}s — likely network / xlings stall)" + ((FAIL++)) + FAILED_TESTS+=("$name (TIMEOUT)") + TIMED_OUT_TESTS+=("$name") else - echo "FAIL: $name" + echo "FAIL: $name (exit $rc)" ((FAIL++)) - FAILED_TESTS+=("$name") + FAILED_TESTS+=("$name (exit $rc)") fi done echo echo "===============================================" echo "E2E Summary: $PASS passed, $FAIL failed, $SKIP skipped" +if [[ ${#TIMED_OUT_TESTS[@]} -gt 0 ]]; then + echo "Timed out: ${TIMED_OUT_TESTS[*]}" +fi if [[ $FAIL -gt 0 ]]; then - echo "Failed: ${FAILED_TESTS[@]}" + echo "Failed: ${FAILED_TESTS[*]}" exit 1 fi exit 0