Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/variables.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
SPACEMIT_TOOLCHAIN_URL=https://github.com/spacemit-com/toolchain/releases/download/v1.1.2/spacemit-toolchain-linux-glibc-x86_64-v1.1.2.tar.xz
SPACEMIT_ORT_URL=https://github.com/spacemit-com/onnxruntime/releases/download/2.0.2/spacemit-ort.riscv64.2.0.2.tar.gz
SPACEMIT_ORT_URL=https://github.com/spacemit-com/onnxruntime/releases/download/2.0.5/spacemit-ort.riscv64.2.0.5.tar.gz
SPACEMIT_MTMD_PACKAGE_PREFIX=spacemit-llama.cpp.riscv64
SPACEMIT_TOOLCHAIN_ARCHIVE=.cache/spacemit-toolchain.tar.xz
SPACEMIT_ORT_ARCHIVE=.cache/spacemit-ort.tar.gz
SPACEMIT_TOOLCHAIN_DIR=spacemit_toolchain
SPACEMIT_TOOLCHAIN_OHOS_URL=https://nexus.bianbu.xyz/repository/toolchain/llvm-gcc/spacemit-toolchain-linux-musl-x86_64-oh-20260630.tar.xz
SPACEMIT_ORT_OHOS_URL=https://github.com/spacemit-com/onnxruntime/releases/download/2.0.5/spacemit-ort.riscv64.ohos.2.0.5.tar.gz
SPACEMIT_MTMD_OHOS_PACKAGE_PREFIX=spacemit-llama.cpp.riscv64.ohos
SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE=.cache/spacemit-toolchain-ohos.tar.xz
SPACEMIT_ORT_OHOS_ARCHIVE=.cache/spacemit-ort-ohos.tar.gz
SPACEMIT_TOOLCHAIN_OHOS_DIR=spacemit_toolchain_ohos
210 changes: 210 additions & 0 deletions .github/workflows/build-spacemit-mtmd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ on:
pull_request:
branches:
- spacemit-mtmd
workflow_dispatch:
inputs:
build_ohos:
description: "Also run the OHOS (OpenHarmony, musl) build job"
required: false
default: "true"

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
Expand All @@ -20,6 +26,11 @@ jobs:
name: Build and Publish SpacemiT MTMD
runs-on: ubuntu-24.04

outputs:
should_publish: ${{ steps.release_guard.outputs.should_publish }}
release_tag: ${{ steps.vars.outputs.release_tag }}
version_number: ${{ steps.vars.outputs.version_number }}

steps:
- name: Clone
uses: actions/checkout@v6
Expand Down Expand Up @@ -285,3 +296,202 @@ jobs:
make_latest: false
overwrite_files: true
fail_on_unmatched_files: true

build-ohos:
name: Build and Publish SpacemiT MTMD (OHOS)
runs-on: ubuntu-24.04
# Runs alongside the glibc `build` job on push / pull_request (and manual
# dispatch). It depends on `build` so that, on a release push, the glibc job
# creates the GitHub release first and this job then attaches its OHOS
# package to the same tag (overwrite_files: true). Requires the two
# SPACEMIT_*_OHOS_URL values in .github/variables.env to point at real
# published artifacts; the "Load shared variables" step hard-fails while
# they are still TODO_ placeholders.
needs: build
if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.build_ohos == 'true' }}

steps:
- name: Clone
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true

- name: Load shared variables
id: vars
shell: bash
run: |
set -euo pipefail
set -a
source .github/variables.env
set +a

if [[ "${SPACEMIT_TOOLCHAIN_OHOS_URL}" == TODO_* || "${SPACEMIT_ORT_OHOS_URL}" == TODO_* ]]; then
echo "::error::OHOS artifact URLs are still placeholders in .github/variables.env."
echo "::error::Set SPACEMIT_TOOLCHAIN_OHOS_URL and SPACEMIT_ORT_OHOS_URL before running this job."
exit 1
fi

VERSION_NUMBER=$(tr -d '[:space:]' < VERSION_NUMBER)
if [[ -z "${VERSION_NUMBER}" ]]; then
echo "error: VERSION_NUMBER is empty" >&2
exit 1
fi

SPACEMIT_MTMD_OHOS_PACKAGE_NAME="${SPACEMIT_MTMD_OHOS_PACKAGE_PREFIX}.${VERSION_NUMBER}"

{
echo "SPACEMIT_TOOLCHAIN_OHOS_URL=${SPACEMIT_TOOLCHAIN_OHOS_URL}"
echo "SPACEMIT_ORT_OHOS_URL=${SPACEMIT_ORT_OHOS_URL}"
echo "SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE=${SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE}"
echo "SPACEMIT_ORT_OHOS_ARCHIVE=${SPACEMIT_ORT_OHOS_ARCHIVE}"
echo "SPACEMIT_TOOLCHAIN_OHOS_DIR=${SPACEMIT_TOOLCHAIN_OHOS_DIR}"
echo "SPACEMIT_MTMD_OHOS_PACKAGE_NAME=${SPACEMIT_MTMD_OHOS_PACKAGE_NAME}"
} >> "$GITHUB_ENV"

toolchain_cache_key=$(printf '%s' "$SPACEMIT_TOOLCHAIN_OHOS_URL" | sha256sum | cut -c1-16)
ort_cache_key=$(printf '%s' "$SPACEMIT_ORT_OHOS_URL" | sha256sum | cut -c1-16)

{
echo "version_number=${VERSION_NUMBER}"
echo "package_name=${SPACEMIT_MTMD_OHOS_PACKAGE_NAME}"
echo "toolchain_archive=${SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE}"
echo "ort_archive=${SPACEMIT_ORT_OHOS_ARCHIVE}"
echo "toolchain_cache_key=${toolchain_cache_key}"
echo "ort_cache_key=${ort_cache_key}"
} >> "$GITHUB_OUTPUT"

- name: Cache SpacemiT OHOS Toolchain archive
id: cache-toolchain
uses: actions/cache@v5
with:
path: ${{ steps.vars.outputs.toolchain_archive }}
key: spacemit-toolchain-ohos-archive-${{ steps.vars.outputs.toolchain_cache_key }}-${{ runner.os }}

- name: Cache SpacemiT OHOS ORT archive
id: cache-ort
uses: actions/cache@v5
with:
path: ${{ steps.vars.outputs.ort_archive }}
key: spacemit-ort-ohos-archive-${{ steps.vars.outputs.ort_cache_key }}-${{ runner.os }}

- name: Prepare SpacemiT OHOS Toolchain
shell: bash
run: |
set -euo pipefail

mkdir -p "$(dirname "$SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE")"
if [[ ! -f "$SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE" ]]; then
curl -L -k --fail --retry 5 --retry-all-errors \
-o "$SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE" \
"$SPACEMIT_TOOLCHAIN_OHOS_URL"
fi

rm -rf "$SPACEMIT_TOOLCHAIN_OHOS_DIR"
mkdir -p "$SPACEMIT_TOOLCHAIN_OHOS_DIR"
tar -xJf "$SPACEMIT_TOOLCHAIN_OHOS_ARCHIVE" -C "$SPACEMIT_TOOLCHAIN_OHOS_DIR" --strip-components=1

- name: Prepare SpacemiT OHOS ORT
shell: bash
run: |
set -euo pipefail
ORT_ROOT=third_party/spacemit-ort-ohos

mkdir -p "$(dirname "$SPACEMIT_ORT_OHOS_ARCHIVE")"
if [[ ! -f "$SPACEMIT_ORT_OHOS_ARCHIVE" ]]; then
curl -L --fail --retry 5 --retry-all-errors \
-o "$SPACEMIT_ORT_OHOS_ARCHIVE" \
"$SPACEMIT_ORT_OHOS_URL"
fi

rm -rf "$ORT_ROOT"
mkdir -p "$ORT_ROOT"
tar -xzf "$SPACEMIT_ORT_OHOS_ARCHIVE" -C "$ORT_ROOT"

ORT_DIR=$(find "$ORT_ROOT" -mindepth 1 -maxdepth 1 -type d | head -n 1)
if [[ -z "${ORT_DIR}" ]]; then
ORT_DIR="${PWD}/${ORT_ROOT}"
else
ORT_DIR="${PWD}/${ORT_DIR}"
fi

if [[ ! -d "${ORT_DIR}/include" || ! -d "${ORT_DIR}/lib" || ! -d "${ORT_DIR}/samples" ]]; then
echo "error: invalid SPACEMIT_ORT_DIR layout at ${ORT_DIR}" >&2
find "$ORT_ROOT" -maxdepth 2 -type d | sort
exit 1
fi

echo "SPACEMIT_ORT_DIR=${ORT_DIR}" >> "$GITHUB_ENV"

- name: Build (OHOS)
shell: bash
run: |
set -euo pipefail
export RISCV_ROOT_PATH="${PWD}/${SPACEMIT_TOOLCHAIN_OHOS_DIR}"

for d in include lib samples; do
if [[ ! -d "${SPACEMIT_ORT_DIR}/${d}" ]]; then
echo "error: ${d} directory not found under SPACEMIT_ORT_DIR: ${SPACEMIT_ORT_DIR}/${d}" >&2
exit 1
fi
done

echo "Using RISCV_ROOT_PATH=${RISCV_ROOT_PATH}"
echo "Using SPACEMIT_ORT_DIR=${SPACEMIT_ORT_DIR}"
bash build_spacemit.sh ohos

- name: Pack artifacts (OHOS)
shell: bash
run: |
set -euo pipefail
PACKAGE_DIR="release/${SPACEMIT_MTMD_OHOS_PACKAGE_NAME}"
ASSET_NAME="${SPACEMIT_MTMD_OHOS_PACKAGE_NAME}.tar.gz"

rm -rf "$PACKAGE_DIR"
mkdir -p "$PACKAGE_DIR"
cp -a build-ohos/installed/. "$PACKAGE_DIR/"
cp LICENSE README.md VERSION_NUMBER "$PACKAGE_DIR/"

if [[ -d "$PACKAGE_DIR/bin" ]]; then
find "$PACKAGE_DIR/bin" -maxdepth 1 \( -type f -o -type l \) \( -name 'test*' -o -name 'export-graph-ops*' \) -exec rm -f {} +
fi

tar -czf "release/${ASSET_NAME}" -C release "${SPACEMIT_MTMD_OHOS_PACKAGE_NAME}"

- name: Inspect package (OHOS)
shell: bash
run: |
set -euo pipefail

ASSET_NAME="${SPACEMIT_MTMD_OHOS_PACKAGE_NAME}.tar.gz"
echo "Package tree:"
find "release/${SPACEMIT_MTMD_OHOS_PACKAGE_NAME}" -maxdepth 2 -print | sort
echo "Package archive:"
tar -tzf "release/${ASSET_NAME}"

- name: Upload OHOS package for PR inspection
if: ${{ github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' }}
uses: actions/upload-artifact@v6
with:
name: spacemit-mtmd-ohos-package
path: release/${{ steps.vars.outputs.package_name }}.tar.gz
if-no-files-found: error
retention-days: 7

- name: Publish GitHub release (OHOS)
if: ${{ github.event_name == 'push' && needs.build.outputs.should_publish == 'true' }}
uses: softprops/action-gh-release@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ needs.build.outputs.release_tag }}
name: ${{ needs.build.outputs.release_tag }}
target_commitish: ${{ github.sha }}
files: release/${{ steps.vars.outputs.package_name }}.tar.gz
body: |
SpacemiT MTMD build for `spacemit-mtmd`.
Version: `${{ needs.build.outputs.version_number }}`
Package: `${{ steps.vars.outputs.package_name }}.tar.gz`
Commit: `${{ github.sha }}`
make_latest: false
overwrite_files: true
fail_on_unmatched_files: true
2 changes: 1 addition & 1 deletion VERSION_NUMBER
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.4
0.1.5
73 changes: 73 additions & 0 deletions cmake/riscv64-spacemit-ohos.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Toolchain file for cross-compiling llama.cpp for RISC-V 64 OpenHarmony (OHOS)
# using the SpacemiT musl clang toolchain
# (spacemit-toolchain-linux-musl-x86_64-oh-*).
#
# Mirrors spacemit-ep/cmake/oh_riscv64.toolchain.cmake, but leaves the
# `-march`/`-mabi` selection to ggml's own CPU feature detection
# (ggml/src/ggml-cpu/CMakeLists.txt), so we only inject the OHOS-specific
# global flags here (musl libc++ static linking, __OHOS__, stack size, lld).
#
# Usage:
# export RISCV_ROOT_PATH=/path/to/spacemit-toolchain-linux-musl-x86_64-oh-*
# cmake -DCMAKE_TOOLCHAIN_FILE=cmake/riscv64-spacemit-ohos.cmake ...

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR riscv64)
set(CMAKE_SYSTEM_VERSION 1)

if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(riscv)")
message(STATUS "HOST SYSTEM ${CMAKE_HOST_SYSTEM_PROCESSOR}")
set(CMAKE_C_COMPILER clang)
set(CMAKE_ASM_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
else()
if(DEFINED ENV{RISCV_ROOT_PATH})
file(TO_CMAKE_PATH $ENV{RISCV_ROOT_PATH} RISCV_ROOT_PATH)
else()
message(FATAL_ERROR "RISCV_ROOT_PATH env must be defined")
endif()

set(RISCV_ROOT_PATH ${RISCV_ROOT_PATH}
CACHE STRING "root path to riscv ohos toolchain")
set(CMAKE_C_COMPILER "${RISCV_ROOT_PATH}/bin/clang")
set(CMAKE_ASM_COMPILER "${RISCV_ROOT_PATH}/bin/clang")
set(CMAKE_CXX_COMPILER "${RISCV_ROOT_PATH}/bin/clang++")
set(CMAKE_STRIP ${RISCV_ROOT_PATH}/bin/llvm-strip)
set(CMAKE_FIND_ROOT_PATH ${RISCV_ROOT_PATH})
set(CMAKE_SYSROOT "${RISCV_ROOT_PATH}/sysroot")
set(CMAKE_INCLUDE_PATH "${RISCV_ROOT_PATH}/sysroot/usr/include/")
set(CMAKE_LIBRARY_PATH "${RISCV_ROOT_PATH}/sysroot/usr/lib/")
set(CMAKE_PROGRAM_PATH "${RISCV_ROOT_PATH}/sysroot/usr/bin/")
set(CMAKE_CROSSCOMPILING TRUE)
endif()

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

add_definitions(-D__OHOS__)

set(STACK_SIZE_BYTES 16777216)

# NOTE: -march / -mabi are intentionally NOT set here. ggml appends the
# correct `-march=rv64gc..._zfh_zvfh...` and `-mabi=lp64d` itself based on the
# GGML_RV_* options passed on the cmake command line. Setting them here as well
# would duplicate/conflict with ggml's selection.

set(CMAKE_C_FLAGS
"-Wno-unused-command-line-argument -fuse-ld=lld -Wl,-z,stack-size=${STACK_SIZE_BYTES} ${CMAKE_C_FLAGS}"
)
set(CMAKE_CXX_FLAGS
"-Wno-unused-command-line-argument -fuse-ld=lld -stdlib=libc++ -static-libstdc++ -Wl,--push-state,-Bstatic -lc++ -lc++abi -Wl,--pop-state -Wl,-z,stack-size=${STACK_SIZE_BYTES} ${CMAKE_CXX_FLAGS}"
)

set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++ -static-libgcc -static-libstdc++ -Wl,--push-state,-Bstatic -lgcc -lc++ -lc++abi -Wl,--pop-state -lm -Wl,-z,stack-size=${STACK_SIZE_BYTES}"
)

set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -latomic -lm -Wl,-z,stack-size=${STACK_SIZE_BYTES}"
)
set(CMAKE_MODULE_LINKER_FLAGS
"${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,stack-size=${STACK_SIZE_BYTES}")
9 changes: 6 additions & 3 deletions ggml/src/ggml-cpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,12 @@ function(ggml_add_cpu_backend_variant_impl tag_name)
string(APPEND MARCH_STR "_zba")
endif()
if (GGML_CPU_RISCV64_SPACEMIT)
# `xsmtvdotii' is only required for GCC >= 15.
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15)
# `xsmtvdotii' is required for GCC >= 15 and for Clang
# (the SpacemiT musl/OHOS clang toolchain needs it to emit
# the IME `vmadot` family of instructions).
if ((CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15) OR
CMAKE_C_COMPILER_ID MATCHES "Clang")
string(APPEND MARCH_STR "_xsmtvdotii")
endif()
endif()
Expand Down
5 changes: 3 additions & 2 deletions ggml/src/ggml-cpu/cmake/FindSMTIME.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ include(CheckCSourceRuns)

if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv)" AND GGML_CPU_RISCV64_SPACEMIT)
set(SMT_MARCH_STR "-march=rv64gcv_zfh_zvfh_zba_zicbop")
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15)
if ((CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 15) OR
CMAKE_C_COMPILER_ID MATCHES "Clang")
string(APPEND SMT_MARCH_STR "_xsmtvdotii")
endif()
set(CMAKE_REQUIRED_FLAGS "${SMT_MARCH_STR}")
Expand Down
2 changes: 1 addition & 1 deletion ggml/src/ggml-cpu/spacemit/rvv_kernels.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace spacemit_kernels {

constexpr auto div_round_up(auto up, auto down) {
template <typename T, typename U> constexpr auto div_round_up(T up, U down) {
return (up + down - 1) / down;
}

Expand Down
Loading