Files
clice/pixi.toml
ykiko 592b37417e feat: cross-compile & upgrade LLVM to 21.1.8 (#390)
## Summary

This PR adds cross-compilation support for three new target platforms,
upgrades LLVM to 21.1.8, and overhauls the CI pipelines around
cross-builds and testing.

## Cross-compilation

New target triples accepted via `-DCLICE_TARGET_TRIPLE=...`:

| Target triple | Host | Output |
|---|---|---|
| `x86_64-apple-darwin` | macos-15 (arm64) | macOS x64 |
| `aarch64-linux-gnu` | ubuntu-24.04 (x64) | Linux arm64 |
| `aarch64-pc-windows-msvc` | windows-2025 (x64) | Windows arm64 |

- `cmake/toolchain.cmake` — maps `CLICE_TARGET_TRIPLE` to
`CMAKE_SYSTEM_NAME`/`CMAKE_SYSTEM_PROCESSOR`/compiler `--target`; picks
up conda aarch64 sysroot when cross-compiling Linux.
- `cmake/llvm.cmake` — forwards target platform/arch to `setup-llvm.py`
so the right prebuilt LLVM is downloaded for the target.
- `CMakeLists.txt` — uses a host-side `flatc` from `PATH` under
`CMAKE_CROSSCOMPILING` instead of the in-tree target build.
- `pixi.toml`:
  - Adds `osx-64`, `linux-aarch64`, `win-arm64` platforms.
- New environments: `cross-macos-x64`, `cross-linux-aarch64` (adds
`gcc_linux-aarch64` + `sysroot_linux-aarch64`), `cross-windows-arm64`.
- New lightweight `test-run` env used on native ARM/x64 runners to
execute cross-built artifacts (pulls in upstream clang+lld on macOS so
tests don't fall back to Apple clang).
- `scripts/activate_cross_linux.sh` — exports `CONDA_PREFIX`-relative
paths for the aarch64 toolchain.
- `scripts/build-llvm.py` — `--target-triple` support and a
`build_native_tools()` helper that produces host `llvm-tblgen` /
`clang-tblgen` needed when cross-compiling LLVM itself.

## LLVM upgrade 21.1.4 → 21.1.8

- `cmake/package.cmake` bumps `setup_llvm("21.1.8")`.
- `config/llvm-manifest.json` regenerated with 6 new cross-compiled
entries and a new `arch` field on every entry so lookup is `(version,
platform, arch, lto, build_type)`.
- `scripts/setup-llvm.py` — honours the new `arch` field when resolving
artifacts.
- `scripts/update-llvm-version.py` (new) — single-call version bump
across `package.cmake` + manifest.
- `scripts/validate-llvm-components.py` (new) — scans the LLVM source
tree for library targets and diffs them against
`scripts/llvm-components.json` to catch stale/misspelled component names
before a build.
- `scripts/llvm-components.json` (new) — explicit allow-list of required
LLVM/Clang library targets used by `build-llvm.py`.

## CI changes

- `.github/workflows/build-llvm.yml`:
- Adds `workflow_dispatch` with `llvm_version`, `skip_upload`, `skip_pr`
inputs.
- Matrix extended with the 6 cross-compile entries (2 per new platform:
RelWithDebInfo ± LTO).
- `build clice` / test / prune steps gated on `!matrix.target_triple`
for cross-builds; cross-built LTO entries apply the native prune
manifest (arch-independent).
  - Cross-compiled binary architecture is verified with `file(1)`.
- New `upload` job triggered by `workflow_dispatch` pushes artifacts to
`clice-io/clice-llvm` and hands the manifest off to the next job.
- `.github/workflows/test-cmake.yml`:
- Build matrix gains three `build_only: true` cross entries that upload
`bin/` + `lib/` artifacts.
- New `test-cross` job runs on native `macos-15-intel`,
`ubuntu-24.04-arm`, `windows-11-arm` runners, downloads the cross-built
artifacts, and runs unit / integration / smoke tests under the
`test-run` pixi env.
- Cache keys now include `target_triple` so native and cross builds
don't collide.
- `.github/workflows/publish-clice.yml`:
- Three additional release artifacts for the new targets
(`clice-x86_64-macos-darwin`, `clice-aarch64-linux-gnu`,
`clice-aarch64-windows-msvc`), each with a matching `-symbol` archive.

## Compatibility

- All existing native builds and tests are preserved; cross entries are
additive.
- `Debug` + ASAN remains disabled on Windows (`llvm_mode == Debug && os
== windows-*` no longer appends `-asan`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 00:17:39 +08:00

289 lines
9.1 KiB
TOML

# tombi: format.rules.table-keys-order.disabled = true
[workspace]
name = "clice"
version = "0.1.0"
description = "A next-generation C++ language server for modern C++"
authors = [
"ykiko <ykiko@clice.io>",
"clice contributors <clice@clice.io>",
]
license = "Apache-2.0"
license-file = "LICENSE"
readme = "README.md"
documentation = "https://docs.clice.io/clice/"
repository = "https://github.com/clice-io/clice"
channels = ["conda-forge"]
platforms = ["win-64", "linux-64", "osx-arm64", "osx-64", "linux-aarch64", "win-arm64"]
[environments]
default = ["build", "test"]
package = ["build", "test", "package"]
cross-macos-x64 = ["build", "package", "cross-macos-x64"]
cross-linux-aarch64 = ["build", "package", "cross-linux-aarch64"]
cross-windows-arm64 = ["build", "package", "cross-windows-arm64"]
node = ["node"]
format = ["format"]
test-run = ["test"]
# ============================================================================== #
# DEPENDENCIES #
# ============================================================================== #
[feature.build]
platforms = ["win-64", "linux-64", "osx-arm64", "osx-64", "linux-aarch64"]
[feature.build.dependencies]
python = ">=3.13"
cmake = ">=3.30"
ninja = "*"
clang = "==20.1.8"
clangxx = "==20.1.8"
lld = "==20.1.8"
llvm-tools = "==20.1.8"
clang-tools = "==20.1.8"
compiler-rt = "==20.1.8"
flatbuffers = "==25.9.23"
[feature.build.target.win-64.dependencies]
sccache = "*"
[feature.build.target.linux-64.dependencies]
sysroot_linux-64 = "==2.17"
gcc = "==14.2.0"
gxx = "==14.2.0"
ccache = "*"
[feature.build.target.osx-arm64.dependencies]
ccache = "*"
[feature.build.target.linux-64.activation]
scripts = ["scripts/activate_linux.sh"]
[feature.build.target.win-64.activation]
scripts = ["scripts/activate_asan.bat"]
# macOS x64 (from arm64): clang natively supports cross-arch, no extra deps.
[feature.cross-macos-x64.target.osx-arm64.dependencies]
[feature.cross-macos-x64.target.osx-arm64.activation]
scripts = ["scripts/activate_cross_macos.sh"]
# Linux aarch64 (from x64): needs aarch64 sysroot and cross gcc for libstdc++.
[feature.cross-linux-aarch64.target.linux-64.dependencies]
sysroot_linux-aarch64 = "==2.17"
gcc_linux-aarch64 = "==14.2.0"
gxx_linux-aarch64 = "==14.2.0"
[feature.cross-linux-aarch64.target.linux-64.activation]
scripts = ["scripts/activate_cross_linux.sh"]
# Windows arm64 (from x64): Windows SDK on CI already includes ARM64 libs.
[feature.cross-windows-arm64.target.win-64.dependencies]
[feature.cross-windows-arm64.target.win-64.activation]
scripts = ["scripts/activate_cross_windows.bat"]
[feature.test.dependencies]
python = ">=3.13"
# On macOS, the system Apple clang emits vendor-specific flags that upstream
# LLVM cannot parse. Providing upstream clang + lld in PATH prevents
# fallback to /usr/bin/clang++ and satisfies toolchain.cmake's -fuse-ld=lld.
[feature.test.target.osx-64.dependencies]
clang = "==20.1.8"
clangxx = "==20.1.8"
lld = "==20.1.8"
[feature.test.target.osx-arm64.dependencies]
clang = "==20.1.8"
clangxx = "==20.1.8"
lld = "==20.1.8"
[feature.test.pypi-dependencies]
pytest = "*"
pytest-asyncio = ">=1.1.0"
pygls = ">=2.0.0"
lsprotocol = ">=2024.0.0"
[feature.package.dependencies]
xz = ">=5.8.1,<6"
[feature.package.tasks.package-config]
args = [{ arg = "type", default = "RelWithDebInfo" }]
cmd = """
cmake -B build/{{ type }} -G Ninja \
-DCMAKE_BUILD_TYPE={{ type }} \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain.cmake \
-DCLICE_RELEASE=ON
"""
[feature.package.tasks.package]
args = [{ arg = "type", default = "RelWithDebInfo" }]
depends-on = [
{ task = "package-config", args = ["{{ type }}"] },
{ task = "cmake-build", args = ["{{ type }}"] },
]
# ============================================================================== #
# CMAKE #
# ============================================================================== #
[feature.build.tasks.cmake-config]
args = [
{ arg = "type", default = "RelWithDebInfo" },
{ arg = "ci", default = "OFF" },
]
cmd = """
cmake -B build/{{ type }} -G Ninja \
-DCMAKE_BUILD_TYPE={{ type }} \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain.cmake \
-DCLICE_ENABLE_TEST=ON \
-DCLICE_CI_ENVIRONMENT={{ ci }}
"""
[feature.build.tasks.cmake-build]
args = [{ arg = "type", default = "RelWithDebInfo" }]
cmd = "cmake --build build/{{ type }}"
[feature.build.tasks.build]
args = [
{ arg = "type", default = "RelWithDebInfo" },
{ arg = "ci", default = "OFF" },
]
depends-on = [
{ task = "cmake-config", args = ["{{ type }}", "{{ ci }}"] },
{ task = "cmake-build", args = ["{{ type }}"] },
]
[feature.build.tasks.clang-tidy]
args = [{ arg = "type", default = "RelWithDebInfo" }]
depends-on = [{ task = "lint-cpp", args = ["{{ type }}"] }]
[feature.test.tasks.unit-test]
args = [{ arg = "type", default = "RelWithDebInfo" }]
cmd = './build/{{ type }}/bin/unit_tests --test-dir="./tests/data"'
[feature.test.tasks.integration-test]
args = [{ arg = "type", default = "RelWithDebInfo" }]
cmd = """
pytest -s --log-cli-level=INFO tests/integration \
--executable=./build/{{ type }}/bin/clice
"""
[feature.test.tasks.smoke-test]
args = [{ arg = "type", default = "RelWithDebInfo" }]
cmd = """
python tests/replay.py tests/smoke/*.jsonl \
--clice=./build/{{ type }}/bin/clice
"""
[feature.test.tasks.test]
args = [{ arg = "type", default = "RelWithDebInfo" }]
depends-on = [
{ task = "unit-test", args = ["{{ type }}"] },
{ task = "integration-test", args = ["{{ type }}"] },
{ task = "smoke-test", args = ["{{ type }}"] },
]
# ============================================================================== #
# HELPER TASKS #
# ============================================================================== #
[tasks.build-llvm]
cmd = ["python3", "scripts/build-llvm.py"]
[tasks.upload-llvm]
args = ["workflow_id", "llvm_version", { "arg" = "branch", default = "main" }]
cmd = """
gh workflow run upload-llvm.yml \
--ref {{ branch }} \
--field workflow_id={{workflow_id}} \
--field version={{llvm_version}}
"""
[tasks.delete-artifacts]
args = ["file_name"]
cmd = ["scripts/delete-artifacts.bash", "{{ file_name }}"]
[dependencies]
# ============================================================================== #
# DOCS & VSCODE EXTENSION #
# ============================================================================== #
[feature.node]
platforms = ["win-64", "linux-64", "osx-arm64", "osx-64", "linux-aarch64"]
[feature.node.dependencies]
nodejs = ">=20"
pnpm = "*"
[feature.node.tasks]
build-docs = { cwd = "docs", cmd = "pnpm run docs:build", depends-on = ["install-docs"] }
preview-docs = { cwd = "docs", cmd = "pnpm run docs:preview", depends-on = ["install-docs"] }
build-vscode = { cwd = "editors/vscode", cmd = "pnpm run package", depends-on = ["install-vscode"] }
publish-vscode = { cwd = "editors/vscode", cmd = "pnpm run publish", depends-on = ["install-vscode"] }
[feature.node.tasks.install-docs]
cwd = "docs"
cmd = "pnpm install"
inputs = ["docs/package.json", "docs/pnpm-lock.yaml"]
outputs = ["docs/node_modules/.modules.yaml"]
[feature.node.tasks.install-vscode]
cwd = "editors/vscode"
cmd = "pnpm install"
inputs = ["editors/vscode/package.json", "editors/vscode/pnpm-lock.yaml"]
outputs = ["editors/vscode/node_modules/.modules.yaml"]
# ============================================================================== #
# FORMAT #
# ============================================================================== #
[feature.format]
platforms = ["win-64", "linux-64", "osx-arm64", "osx-64", "linux-aarch64"]
[feature.format.dependencies]
ruff = "*"
tombi = "*"
stylua = "*"
fd-find = "*"
prettier = "*"
clang-format = "==21.1.7"
[feature.format.tasks]
format-cpp = "fd -H -e cpp -e h -e cc -e hpp -e cppm -x clang-format -i"
format-python = "ruff format ."
format-lua = "stylua ."
format-web = "fd -H -e js -e ts -e css -x prettier --write"
format-markdown = "fd -H -e md -x prettier --write"
format-json = "fd -H -e json -E package-lock.json -x prettier --write"
format-toml = "fd -H -e toml -x tombi format"
format-yaml = """
fd -H -e yaml -e yml -E pnpm-lock.yaml -x prettier --write && \
fd -H "^\\.clang-(format|tidy)$" -x prettier --write --parser yaml
"""
format = { depends-on = [
"format-cpp",
"format-python",
"format-lua",
"format-web",
"format-markdown",
"format-json",
"format-toml",
"format-yaml"
] }
# ============================================================================== #
# LINT #
# ============================================================================== #
[feature.format.tasks.lint-python]
cmd = "ruff check ."
[feature.build.tasks.lint-cpp]
args = [{ arg = "type", default = "RelWithDebInfo" }]
cmd = "python scripts/run_clang_tidy.py build/{{ type }}"
[feature.build.tasks.lint]
args = [{ arg = "type", default = "RelWithDebInfo" }]
depends-on = [
"lint-python",
{ task = "lint-cpp", args = ["{{ type }}"] },
]