Skip to content

Commit 8876f2c

Browse files
authored
Merge pull request #1 from mcpplibs/feat/llamacpp-0.1.0
feat: package llama.cpp b10069 as a C++23 module
2 parents 00b70bf + d91cc71 commit 8876f2c

3,272 files changed

Lines changed: 1327609 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
third_party/llama.cpp/** -whitespace

.github/workflows/ci.yml

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
env:
13+
MCPP_VERSION: "2026.7.28.2"
14+
MCPP_RELEASE_BASE: https://github.com/mcpp-community/mcpp/releases/download
15+
16+
jobs:
17+
unit-and-import:
18+
runs-on: ubuntu-24.04
19+
steps:
20+
- uses: actions/checkout@v4
21+
- uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.12"
24+
- name: Install pinned mcpp
25+
shell: bash
26+
run: |
27+
set -euo pipefail
28+
asset="mcpp-${MCPP_VERSION}-linux-x86_64.tar.gz"
29+
wrapper="${asset%.tar.gz}"
30+
url="${MCPP_RELEASE_BASE}/v${MCPP_VERSION}/${asset}"
31+
curl --fail --location --retry 5 --retry-all-errors \
32+
--retry-delay 2 --output "${RUNNER_TEMP}/${asset}" "${url}"
33+
curl --fail --location --retry 5 --retry-all-errors \
34+
--retry-delay 2 --output "${RUNNER_TEMP}/${asset}.sha256" \
35+
"${url}.sha256"
36+
(cd "${RUNNER_TEMP}" && sha256sum -c "${asset}.sha256")
37+
tar -xzf "${RUNNER_TEMP}/${asset}" -C "${RUNNER_TEMP}"
38+
echo "${RUNNER_TEMP}/${wrapper}/bin" >> "${GITHUB_PATH}"
39+
- name: Unit and repository checks
40+
run: python3 -m unittest discover -s tests/unit -p 'test_*.py' -v
41+
- name: Verify vendored upstream and generated API
42+
env:
43+
GITHUB_TOKEN: ${{ github.token }}
44+
run: |
45+
python3 tools/import_upstream.py --lock upstream.lock --check --verify-tag
46+
python3 tools/gen_exports.py --check
47+
python3 tools/audit_snapshot.py --check snapshots/b10069.json
48+
- name: Cold CPU package build
49+
run: |
50+
rm -rf target
51+
mcpp --version | grep -F "${MCPP_VERSION}"
52+
mcpp build --strict --no-cache
53+
54+
cpu:
55+
name: cpu (${{ matrix.os }})
56+
runs-on: ${{ matrix.os }}
57+
strategy:
58+
fail-fast: false
59+
matrix:
60+
include:
61+
- os: ubuntu-24.04
62+
platform: linux-x86_64
63+
format: tar.gz
64+
- os: windows-latest
65+
platform: windows-x86_64
66+
format: zip
67+
- os: macos-15
68+
platform: macosx-arm64
69+
format: tar.gz
70+
steps:
71+
- uses: actions/checkout@v4
72+
- uses: actions/setup-python@v5
73+
with:
74+
python-version: "3.12"
75+
- name: Install pinned mcpp (Unix)
76+
if: runner.os != 'Windows'
77+
shell: bash
78+
run: |
79+
set -euo pipefail
80+
asset="mcpp-${MCPP_VERSION}-${{ matrix.platform }}.${{ matrix.format }}"
81+
wrapper="mcpp-${MCPP_VERSION}-${{ matrix.platform }}"
82+
url="${MCPP_RELEASE_BASE}/v${MCPP_VERSION}/${asset}"
83+
curl --fail --location --retry 5 --retry-all-errors \
84+
--retry-delay 2 --output "${RUNNER_TEMP}/${asset}" "${url}"
85+
curl --fail --location --retry 5 --retry-all-errors \
86+
--retry-delay 2 --output "${RUNNER_TEMP}/${asset}.sha256" \
87+
"${url}.sha256"
88+
if [[ "${RUNNER_OS}" == "macOS" ]]; then
89+
(cd "${RUNNER_TEMP}" && shasum -a 256 -c "${asset}.sha256")
90+
else
91+
(cd "${RUNNER_TEMP}" && sha256sum -c "${asset}.sha256")
92+
fi
93+
tar -xzf "${RUNNER_TEMP}/${asset}" -C "${RUNNER_TEMP}"
94+
echo "${RUNNER_TEMP}/${wrapper}/bin" >> "${GITHUB_PATH}"
95+
- name: Install pinned mcpp (Windows)
96+
if: runner.os == 'Windows'
97+
shell: pwsh
98+
run: |
99+
$asset = "mcpp-$env:MCPP_VERSION-${{ matrix.platform }}.${{ matrix.format }}"
100+
$wrapper = "mcpp-$env:MCPP_VERSION-${{ matrix.platform }}"
101+
$url = "$env:MCPP_RELEASE_BASE/v$env:MCPP_VERSION/$asset"
102+
curl.exe --fail --location --retry 5 --retry-all-errors `
103+
--retry-delay 2 --output "$env:RUNNER_TEMP/$asset" $url
104+
curl.exe --fail --location --retry 5 --retry-all-errors `
105+
--retry-delay 2 --output "$env:RUNNER_TEMP/$asset.sha256" `
106+
"$url.sha256"
107+
$expected = (Get-Content "$env:RUNNER_TEMP/$asset.sha256").Split()[0]
108+
$actual = (Get-FileHash "$env:RUNNER_TEMP/$asset" -Algorithm SHA256).Hash.ToLower()
109+
if ($actual -ne $expected) { throw "mcpp archive checksum mismatch" }
110+
Expand-Archive "$env:RUNNER_TEMP/$asset" -DestinationPath $env:RUNNER_TEMP
111+
"$env:RUNNER_TEMP/$wrapper/bin" | Out-File -FilePath $env:GITHUB_PATH -Append
112+
- name: Fetch pinned model (Unix)
113+
if: runner.os != 'Windows'
114+
shell: bash
115+
run: python3 tests/support/fetch_model.py --output "${RUNNER_TEMP}/stories15M.gguf"
116+
- name: Fetch pinned model (Windows)
117+
if: runner.os == 'Windows'
118+
shell: pwsh
119+
run: python tests/support/fetch_model.py --output "$env:RUNNER_TEMP/stories15M.gguf"
120+
- name: Run CPU inference (Unix)
121+
if: runner.os != 'Windows'
122+
shell: bash
123+
run: |
124+
set -euo pipefail
125+
rm -rf target
126+
LLAMACPP_TEST_MODEL="${RUNNER_TEMP}/stories15M.gguf" \
127+
mcpp test cpu_decode --strict 2>&1 | tee cpu.log
128+
grep -F "LLAMACPP_CPU_TEST=PASS" cpu.log
129+
- name: Run CPU inference (Windows)
130+
if: runner.os == 'Windows'
131+
shell: pwsh
132+
run: |
133+
Remove-Item -Recurse -Force target -ErrorAction SilentlyContinue
134+
$env:LLAMACPP_TEST_MODEL = "$env:RUNNER_TEMP/stories15M.gguf"
135+
& mcpp test cpu_decode --strict 2>&1 | Tee-Object -FilePath cpu.log
136+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
137+
if (-not (Select-String -Quiet -SimpleMatch "LLAMACPP_CPU_TEST=PASS" cpu.log)) {
138+
throw "CPU pass marker missing"
139+
}
140+
141+
linux-arm64:
142+
runs-on: ubuntu-24.04-arm
143+
steps:
144+
- uses: actions/checkout@v4
145+
- name: Native ARM64 CPU inference in Ubuntu container
146+
shell: bash
147+
run: |
148+
docker run --rm \
149+
-e MCPP_VERSION="${MCPP_VERSION}" \
150+
-v "${GITHUB_WORKSPACE}:/workspace" \
151+
-w /workspace \
152+
ubuntu:24.04 bash -euxo pipefail -c '
153+
sed -i \
154+
"s|http://ports.ubuntu.com/ubuntu-ports|http://mirrors.ustc.edu.cn/ubuntu-ports|g" \
155+
/etc/apt/sources.list.d/ubuntu.sources
156+
cat /etc/apt/sources.list.d/ubuntu.sources
157+
apt-get update
158+
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
159+
ca-certificates curl python3 file binutils
160+
161+
asset="mcpp-${MCPP_VERSION}-linux-aarch64.tar.gz"
162+
wrapper="${asset%.tar.gz}"
163+
url="https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/${asset}"
164+
curl --fail --location --retry 5 --retry-all-errors \
165+
--retry-delay 2 --output "/tmp/${asset}" "${url}"
166+
curl --fail --location --retry 5 --retry-all-errors \
167+
--retry-delay 2 --output "/tmp/${asset}.sha256" "${url}.sha256"
168+
(cd /tmp && sha256sum -c "${asset}.sha256")
169+
mkdir -p /opt/mcpp
170+
tar -xzf "/tmp/${asset}" -C /opt/mcpp
171+
export PATH="/opt/mcpp/${wrapper}/bin:${PATH}"
172+
export MCPP_HOME=/tmp/llamacpp-mcpp-home
173+
export MCPP_VENDORED_XLINGS="/opt/mcpp/${wrapper}/registry/bin/xlings"
174+
mcpp --version | grep -F "${MCPP_VERSION}"
175+
176+
python3 tests/support/fetch_model.py --output /tmp/stories15M.gguf
177+
rm -rf target
178+
LLAMACPP_TEST_MODEL=/tmp/stories15M.gguf \
179+
mcpp test cpu_decode --strict 2>&1 | tee /tmp/cpu.log
180+
grep -F "LLAMACPP_CPU_TEST=PASS" /tmp/cpu.log
181+
182+
helper=target/.build-mcpp/build.mcpp.bin
183+
test_bin=$(find target -type f -path "*/bin/cpu_decode" -print -quit)
184+
test -x "${helper}"
185+
test -n "${test_bin}"
186+
for binary in "${helper}" "${test_bin}"; do
187+
file "${binary}" | tee /tmp/file.log
188+
grep -F "ARM aarch64" /tmp/file.log
189+
grep -F "statically linked" /tmp/file.log
190+
if readelf -l "${binary}" | grep -q INTERP; then
191+
echo "PT_INTERP present in ${binary}"
192+
exit 1
193+
fi
194+
echo "PT_INTERP absent in ${binary}"
195+
done
196+
197+
test -f compile_commands.json
198+
grep -F "/arch/arm/quants.c" compile_commands.json
199+
grep -F "/arch/arm/repack.cpp" compile_commands.json
200+
if grep -F "/arch/x86/" compile_commands.json; then
201+
echo "x86 sources selected on ARM64"
202+
exit 1
203+
fi
204+
'
205+
206+
metal:
207+
runs-on: macos-15
208+
steps:
209+
- uses: actions/checkout@v4
210+
- uses: actions/setup-python@v5
211+
with:
212+
python-version: "3.12"
213+
- name: Install pinned mcpp
214+
shell: bash
215+
run: |
216+
set -euo pipefail
217+
asset="mcpp-${MCPP_VERSION}-macosx-arm64.tar.gz"
218+
wrapper="${asset%.tar.gz}"
219+
url="${MCPP_RELEASE_BASE}/v${MCPP_VERSION}/${asset}"
220+
curl --fail --location --retry 5 --retry-all-errors \
221+
--retry-delay 2 --output "${RUNNER_TEMP}/${asset}" "${url}"
222+
curl --fail --location --retry 5 --retry-all-errors \
223+
--retry-delay 2 --output "${RUNNER_TEMP}/${asset}.sha256" \
224+
"${url}.sha256"
225+
(cd "${RUNNER_TEMP}" && shasum -a 256 -c "${asset}.sha256")
226+
tar -xzf "${RUNNER_TEMP}/${asset}" -C "${RUNNER_TEMP}"
227+
echo "${RUNNER_TEMP}/${wrapper}/bin" >> "${GITHUB_PATH}"
228+
- name: Run real Metal inference
229+
shell: bash
230+
run: |
231+
set -euo pipefail
232+
python3 tests/support/fetch_model.py --output "${RUNNER_TEMP}/stories15M.gguf"
233+
rm -rf target
234+
LLAMACPP_TEST_MODEL="${RUNNER_TEMP}/stories15M.gguf" \
235+
mcpp test metal_decode --features backend-metal --strict \
236+
2>&1 | tee metal.log
237+
grep -F "LLAMACPP_METAL_TEST=PASS" metal.log
238+
grep -F "using embedded metal library" metal.log
239+
grep -E "offloaded [1-9][0-9]*/[1-9][0-9]* layers to GPU" metal.log
240+
241+
release-contract:
242+
runs-on: ubuntu-24.04
243+
needs: [unit-and-import, cpu, linux-arm64, metal]
244+
steps:
245+
- uses: actions/checkout@v4
246+
with:
247+
fetch-depth: 0
248+
- uses: actions/setup-python@v5
249+
with:
250+
python-version: "3.12"
251+
- name: Verify release mapping and reproducibility
252+
env:
253+
GITHUB_TOKEN: ${{ github.token }}
254+
run: python3 tools/check_release.py --tag v0.1.0

.github/workflows/release.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: release
2+
3+
on:
4+
push:
5+
tags: ["v*"]
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
verify:
12+
runs-on: ubuntu-24.04
13+
permissions:
14+
actions: read
15+
contents: read
16+
outputs:
17+
mapping: ${{ steps.contract.outputs.mapping }}
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0
22+
- uses: actions/setup-python@v5
23+
with:
24+
python-version: "3.12"
25+
- name: Run complete unit suite
26+
run: python3 -m unittest discover -s tests/unit -p 'test_*.py' -v
27+
- name: Verify immutable release contract
28+
id: contract
29+
env:
30+
GITHUB_TOKEN: ${{ github.token }}
31+
shell: bash
32+
run: |
33+
set -euo pipefail
34+
mapping=$(python3 tools/check_release.py --tag "${GITHUB_REF_NAME}" | tail -n 1)
35+
echo "${mapping}"
36+
echo "mapping=${mapping}" >> "${GITHUB_OUTPUT}"
37+
- name: Require latest successful CI run for the tag commit
38+
env:
39+
GH_TOKEN: ${{ github.token }}
40+
shell: bash
41+
run: |
42+
set -euo pipefail
43+
output="${RUNNER_TEMP}/ci-runs.json"
44+
downloaded=0
45+
for attempt in 1 2 3 4 5; do
46+
if gh api \
47+
"repos/${GITHUB_REPOSITORY}/actions/workflows/ci.yml/runs?head_sha=${GITHUB_SHA}&per_page=100" \
48+
> "${output}"; then
49+
downloaded=1
50+
break
51+
fi
52+
if [[ "${attempt}" -lt 5 ]]; then sleep $((attempt * 2)); fi
53+
done
54+
if [[ "${downloaded}" -ne 1 ]]; then
55+
echo "failed to query CI workflow runs after 5 attempts"
56+
exit 1
57+
fi
58+
python3 tools/check_ci_run.py --runs "${output}" --sha "${GITHUB_SHA}"
59+
60+
publish:
61+
needs: verify
62+
runs-on: ubuntu-24.04
63+
permissions:
64+
contents: write
65+
steps:
66+
- uses: actions/checkout@v4
67+
with:
68+
fetch-depth: 0
69+
- name: Create release notes for the immutable tag archive
70+
env:
71+
GH_TOKEN: ${{ github.token }}
72+
RELEASE_MAPPING: ${{ needs.verify.outputs.mapping }}
73+
shell: bash
74+
run: |
75+
set -euo pipefail
76+
if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then
77+
echo "release ${GITHUB_REF_NAME} already exists; refusing to mutate it"
78+
exit 1
79+
fi
80+
gh release create "${GITHUB_REF_NAME}" \
81+
--verify-tag \
82+
--title "llama.cpp-m ${GITHUB_REF_NAME#v}" \
83+
--notes "${RELEASE_MAPPING}"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: upstream check
2+
3+
on:
4+
schedule:
5+
- cron: "17 3 * * 1"
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
report:
13+
runs-on: ubuntu-24.04
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.12"
19+
- name: Report upstream movement
20+
env:
21+
GITHUB_TOKEN: ${{ github.token }}
22+
run: python3 tools/check_upstream.py >> "${GITHUB_STEP_SUMMARY}"

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.mcpp/
2+
target/
3+
generated/
4+
compile_commands.json
5+
__pycache__/
6+
*.pyc
7+
models/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 mcpplibs contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)