diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml new file mode 100644 index 00000000..ee37dfc2 --- /dev/null +++ b/.github/actions/setup-rust/action.yml @@ -0,0 +1,39 @@ +name: Setup pinned Rust +description: Install the Rust toolchain pinned by rust-toolchain.toml. + +inputs: + components: + description: Comma-separated Rust components to install. + required: false + default: "" + targets: + description: Comma-separated Rust targets to install. + required: false + default: "" + +outputs: + toolchain: + description: Rust toolchain channel installed by this action. + value: ${{ steps.toolchain.outputs.toolchain }} + +runs: + using: composite + steps: + - name: Read pinned toolchain + id: toolchain + shell: bash + run: | + set -euo pipefail + toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' "${GITHUB_WORKSPACE}/rust-toolchain.toml")" + if [ -z "${toolchain}" ]; then + echo "rust-toolchain.toml does not define a toolchain channel." >&2 + exit 1 + fi + echo "toolchain=${toolchain}" >> "${GITHUB_OUTPUT}" + + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ steps.toolchain.outputs.toolchain }} + components: ${{ inputs.components }} + targets: ${{ inputs.targets }} diff --git a/.github/actions/setup-sccache/action.yml b/.github/actions/setup-sccache/action.yml new file mode 100644 index 00000000..73ce1964 --- /dev/null +++ b/.github/actions/setup-sccache/action.yml @@ -0,0 +1,26 @@ +name: Setup sccache +description: Configure sccache for Rust and optional CMake builds. + +inputs: + cmake-launcher: + description: Also let crates that drive CMake use sccache as the C/C++ compiler launcher. + required: false + default: "false" + +runs: + using: composite + steps: + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.10 + + - name: Configure sccache + shell: bash + run: | + set -euo pipefail + echo "SCCACHE_GHA_ENABLED=true" >> "${GITHUB_ENV}" + echo "SCCACHE_BASEDIRS=${GITHUB_WORKSPACE}" >> "${GITHUB_ENV}" + echo "RUSTC_WRAPPER=sccache" >> "${GITHUB_ENV}" + echo "CARGO_INCREMENTAL=0" >> "${GITHUB_ENV}" + if [ "${{ inputs.cmake-launcher }}" = "true" ]; then + echo "VIDE_USE_SCCACHE_CMAKE=1" >> "${GITHUB_ENV}" + fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36316bb8..6d924de5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,9 +3,23 @@ name: CI on: push: branches: [master] + paths-ignore: + - "docs/**" + - "playground/**" + - "crates/vide-lsp-wasm/**" + - ".github/actions/setup-emscripten/**" + - ".github/workflows/docs-preview.yml" + - ".github/workflows/deploy-docs.yml" pull_request: types: [opened, synchronize, reopened] branches: ["**"] + paths-ignore: + - "docs/**" + - "playground/**" + - "crates/vide-lsp-wasm/**" + - ".github/actions/setup-emscripten/**" + - ".github/workflows/docs-preview.yml" + - ".github/workflows/deploy-docs.yml" workflow_dispatch: concurrency: @@ -18,16 +32,20 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - with: - submodules: recursive - name: Install Rust - uses: dtolnay/rust-toolchain@nightly + uses: ./.github/actions/setup-rust with: components: clippy, rustfmt + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" - name: Rust Cache uses: Swatinem/rust-cache@v2 continue-on-error: true with: + shared-key: rust-${{ runner.os }} + key: workspace-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'xtask/**') }} cache-workspace-crates: true cache-on-failure: true - name: Format Check @@ -43,20 +61,24 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] steps: - uses: actions/checkout@v4 - with: - submodules: recursive - name: Install Rust - uses: dtolnay/rust-toolchain@nightly + uses: ./.github/actions/setup-rust with: components: rustfmt + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" - name: Rust Cache uses: Swatinem/rust-cache@v2 continue-on-error: true with: + shared-key: rust-${{ runner.os }} + key: workspace-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'xtask/**') }} cache-workspace-crates: true cache-on-failure: true - name: Test - run: rustup run nightly cargo test --workspace + run: cargo test --workspace vscode-extension: name: VS Code Checks @@ -66,18 +88,6 @@ jobs: working-directory: editors/vscode steps: - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Install Rust - uses: dtolnay/rust-toolchain@nightly - with: - components: rustfmt - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - continue-on-error: true - with: - cache-workspace-crates: true - cache-on-failure: true - name: Setup Node uses: actions/setup-node@v4 with: @@ -111,16 +121,20 @@ jobs: working-directory: editors/vscode steps: - uses: actions/checkout@v4 - with: - submodules: recursive - name: Install Rust - uses: dtolnay/rust-toolchain@nightly + uses: ./.github/actions/setup-rust with: components: rustfmt + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" - name: Rust Cache uses: Swatinem/rust-cache@v2 continue-on-error: true with: + shared-key: rust-${{ runner.os }} + key: package-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'editors/vscode/scripts/**') }} cache-workspace-crates: true cache-on-failure: true - name: Setup Node @@ -160,8 +174,10 @@ jobs: include: - target: alpine-x64 image: ghcr.io/blackdex/rust-musl:x86_64-musl-nightly + rust-target: x86_64-unknown-linux-musl - target: alpine-arm64 image: ghcr.io/blackdex/rust-musl:aarch64-musl-nightly + rust-target: aarch64-unknown-linux-musl defaults: run: working-directory: editors/vscode @@ -172,19 +188,32 @@ jobs: apt-get update apt-get install -y --no-install-recommends ca-certificates cmake git python3 - - name: Install Rust components - working-directory: . - run: rustup component add --toolchain nightly-x86_64-unknown-linux-gnu rustfmt - - uses: actions/checkout@v4 - with: - submodules: recursive - name: Trust checkout directories working-directory: . run: | git config --global --add safe.directory "$GITHUB_WORKSPACE" - git config --global --add safe.directory "$GITHUB_WORKSPACE/crates/slang" + + - name: Install Rust + uses: ./.github/actions/setup-rust + with: + components: rustfmt + targets: ${{ matrix.rust-target }} + + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" + + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + continue-on-error: true + with: + shared-key: rust-${{ runner.os }}-${{ matrix.target }} + key: package-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'editors/vscode/scripts/**') }} + cache-workspace-crates: true + cache-on-failure: true - name: Setup Node uses: actions/setup-node@v4 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 6dea05fb..9ad49914 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -252,23 +252,45 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + + - name: Restore playground WASM cache + id: playground-wasm-cache + uses: actions/cache/restore@v4 with: - submodules: recursive + path: playground/public/wasm + key: playground-wasm-${{ runner.os }}-${{ env.EMSDK_VERSION }}-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'playground/scripts/build-vide-wasm.mjs', 'playground/scripts/script-utils.mjs', '.github/actions/setup-emscripten/**', '.github/actions/setup-rust/**') }} + + - name: Verify cached playground WASM + if: steps.playground-wasm-cache.outputs.cache-hit == 'true' + run: | + test -s playground/public/wasm/vide-lsp.js + test -s playground/public/wasm/vide-core.js + test -s playground/public/wasm/vide-core.wasm - name: Install Rust - uses: dtolnay/rust-toolchain@nightly + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/setup-rust with: components: rustfmt + - name: Setup sccache + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" + - name: Rust Cache + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' uses: Swatinem/rust-cache@v2 continue-on-error: true with: shared-key: docs-wasm-${{ runner.os }}-${{ env.EMSDK_VERSION }} + key: wasm-src-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'playground/scripts/build-vide-wasm.mjs', 'playground/scripts/script-utils.mjs', '.github/actions/setup-emscripten/**', '.github/actions/setup-rust/**') }} cache-workspace-crates: true cache-on-failure: true - name: Install Emscripten SDK + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' uses: ./.github/actions/setup-emscripten with: version: ${{ env.EMSDK_VERSION }} @@ -287,11 +309,20 @@ jobs: working-directory: playground - name: Build playground WASM + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' run: | source "${EMSDK}/emsdk_env.sh" npm run build:wasm working-directory: playground + - name: Save playground WASM cache + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + continue-on-error: true + with: + path: playground/public/wasm + key: ${{ steps.playground-wasm-cache.outputs.cache-primary-key }} + - name: Install dependencies run: npm ci working-directory: docs diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml index 5d0f5eab..024b317d 100644 --- a/.github/workflows/docs-preview.yml +++ b/.github/workflows/docs-preview.yml @@ -6,8 +6,14 @@ on: paths: - "docs/**" - "playground/**" - - "crates/vide-lsp-wasm/**" + - "src/**" + - "crates/**" + - "Cargo.toml" + - "Cargo.lock" + - "rust-toolchain.toml" - ".github/actions/setup-emscripten/**" + - ".github/actions/setup-rust/**" + - ".github/actions/setup-sccache/**" - ".github/workflows/docs-preview.yml" - ".github/workflows/deploy-docs.yml" pull_request: @@ -15,8 +21,14 @@ on: paths: - "docs/**" - "playground/**" - - "crates/vide-lsp-wasm/**" + - "src/**" + - "crates/**" + - "Cargo.toml" + - "Cargo.lock" + - "rust-toolchain.toml" - ".github/actions/setup-emscripten/**" + - ".github/actions/setup-rust/**" + - ".github/actions/setup-sccache/**" - ".github/workflows/docs-preview.yml" - ".github/workflows/deploy-docs.yml" @@ -71,23 +83,45 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + + - name: Restore playground WASM cache + id: playground-wasm-cache + uses: actions/cache/restore@v4 with: - submodules: recursive + path: playground/public/wasm + key: playground-wasm-${{ runner.os }}-${{ env.EMSDK_VERSION }}-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'playground/scripts/build-vide-wasm.mjs', 'playground/scripts/script-utils.mjs', '.github/actions/setup-emscripten/**', '.github/actions/setup-rust/**') }} + + - name: Verify cached playground WASM + if: steps.playground-wasm-cache.outputs.cache-hit == 'true' + run: | + test -s playground/public/wasm/vide-lsp.js + test -s playground/public/wasm/vide-core.js + test -s playground/public/wasm/vide-core.wasm - name: Install Rust - uses: dtolnay/rust-toolchain@nightly + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/setup-rust with: components: rustfmt + - name: Setup sccache + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" + - name: Rust Cache + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' uses: Swatinem/rust-cache@v2 continue-on-error: true with: shared-key: docs-wasm-${{ runner.os }}-${{ env.EMSDK_VERSION }} + key: wasm-src-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'playground/scripts/build-vide-wasm.mjs', 'playground/scripts/script-utils.mjs', '.github/actions/setup-emscripten/**', '.github/actions/setup-rust/**') }} cache-workspace-crates: true cache-on-failure: true - name: Install Emscripten SDK + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' uses: ./.github/actions/setup-emscripten with: version: ${{ env.EMSDK_VERSION }} @@ -106,11 +140,20 @@ jobs: working-directory: playground - name: Build playground WASM + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' run: | source "${EMSDK}/emsdk_env.sh" npm run build:wasm working-directory: playground + - name: Save playground WASM cache + if: steps.playground-wasm-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + continue-on-error: true + with: + path: playground/public/wasm + key: ${{ steps.playground-wasm-cache.outputs.cache-primary-key }} + - name: Install dependencies run: npm ci working-directory: docs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 86987b96..17b21a9b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -72,18 +72,23 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - submodules: recursive - name: Setup Rust - uses: dtolnay/rust-toolchain@nightly + uses: ./.github/actions/setup-rust with: components: rustfmt + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" + - name: Rust Cache uses: Swatinem/rust-cache@v2 continue-on-error: true with: + shared-key: rust-${{ runner.os }} + key: package-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'editors/vscode/scripts/**') }} cache-workspace-crates: true cache-on-failure: true @@ -126,26 +131,42 @@ jobs: include: - target: alpine-x64 image: ghcr.io/blackdex/rust-musl:x86_64-musl-nightly + rust-target: x86_64-unknown-linux-musl - target: alpine-arm64 image: ghcr.io/blackdex/rust-musl:aarch64-musl-nightly + rust-target: aarch64-unknown-linux-musl steps: - name: Install build dependencies run: | apt-get update apt-get install -y --no-install-recommends ca-certificates cmake git python3 - - name: Install Rust components - run: rustup component add --toolchain nightly-x86_64-unknown-linux-gnu rustfmt - - name: Checkout uses: actions/checkout@v4 - with: - submodules: recursive - name: Trust checkout directories run: | git config --global --add safe.directory "$GITHUB_WORKSPACE" - git config --global --add safe.directory "$GITHUB_WORKSPACE/crates/slang" + + - name: Setup Rust + uses: ./.github/actions/setup-rust + with: + components: rustfmt + targets: ${{ matrix.rust-target }} + + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + cmake-launcher: "true" + + - name: Rust Cache + uses: Swatinem/rust-cache@v2 + continue-on-error: true + with: + shared-key: rust-${{ runner.os }}-${{ matrix.target }} + key: package-${{ hashFiles('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', 'src/**', 'crates/**', 'editors/vscode/scripts/**') }} + cache-workspace-crates: true + cache-on-failure: true - name: Setup Node uses: actions/setup-node@v4 diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index a0c3e3a8..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "qihe"] - path = qihe - url = git@github.com:pascal-lab/qihe.git diff --git a/crates/slang/bindings/rust/build.rs b/crates/slang/bindings/rust/build.rs index e98350d6..da40babc 100644 --- a/crates/slang/bindings/rust/build.rs +++ b/crates/slang/bindings/rust/build.rs @@ -58,6 +58,13 @@ fn build_cpp_lib(cxxbridge_dir: &Path, debug: bool) -> PathBuf { } } + if let Some(sccache) = cmake_sccache_launcher() { + let launcher = sccache.to_string_lossy(); + config + .define("CMAKE_C_COMPILER_LAUNCHER", launcher.as_ref()) + .define("CMAKE_CXX_COMPILER_LAUNCHER", launcher.as_ref()); + } + if !emscripten && !debug && cfg!(target_env = "msvc") { // cmake-rs still sets config-specific MSVC flags for Visual Studio // generators to preserve /MD or /MT. That replaces CMake's built-in @@ -73,6 +80,12 @@ fn build_cpp_lib(cxxbridge_dir: &Path, debug: bool) -> PathBuf { config.build() } +fn cmake_sccache_launcher() -> Option { + env::var_os("VIDE_USE_SCCACHE_CMAKE")?; + + env::var_os("SCCACHE_PATH").map(PathBuf::from).or_else(|| which::which("sccache").ok()) +} + fn setup_linking(install_dir: &Path, debug: bool) { let lib_dir = install_dir.join("lib"); let emscripten = env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("emscripten"); diff --git a/playground/scripts/build-vide-wasm.mjs b/playground/scripts/build-vide-wasm.mjs index 51e46254..0f0e1974 100644 --- a/playground/scripts/build-vide-wasm.mjs +++ b/playground/scripts/build-vide-wasm.mjs @@ -18,7 +18,7 @@ if (!buildEnv.EM_CONFIG && existsSync(emConfig)) { buildEnv.EM_CONFIG = emConfig; } -run("rustup", ["target", "add", "--toolchain", "nightly", "wasm32-unknown-emscripten"], { env: buildEnv }); +run("rustup", ["target", "add", "wasm32-unknown-emscripten"], { env: buildEnv }); run("ninja", ["--version"], { env: buildEnv }); const linkArgs = [ @@ -43,7 +43,7 @@ Object.assign(buildEnv, { }); const crateManifest = resolve(workspaceRoot, "crates", "vide-lsp-wasm", "Cargo.toml"); -run("rustup", ["run", "nightly", "cargo", "build", "--manifest-path", crateManifest, "--target", "wasm32-unknown-emscripten", "--release"], { +run("cargo", ["build", "--manifest-path", crateManifest, "--target", "wasm32-unknown-emscripten", "--release"], { env: buildEnv, }); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5d56faf9..eb19ca57 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,4 @@ [toolchain] -channel = "nightly" +channel = "nightly-2026-05-24" +components = ["clippy", "rustfmt"] +profile = "minimal"