diff --git a/.github/workflows/riscv64-linux.yaml b/.github/workflows/riscv64-linux.yaml new file mode 100644 index 000000000..04d196a8f --- /dev/null +++ b/.github/workflows/riscv64-linux.yaml @@ -0,0 +1,205 @@ +name: riscv64-linux + +on: + push: + branches: + - master + paths: + - '.github/workflows/riscv64-linux.yaml' + - 'CMakeLists.txt' + - 'cmake/**' + - 'sherpa-onnx/csrc/*' + - 'toolchains/riscv64-linux-gnu.toolchain.cmake' + - 'build-riscv64-linux-gnu.sh' + tags: + - '*' + pull_request: + branches: + - master + paths: + - '.github/workflows/riscv64-linux.yaml' + - 'CMakeLists.txt' + - 'cmake/**' + - 'sherpa-onnx/csrc/*' + - 'toolchains/riscv64-linux-gnu.toolchain.cmake' + - 'build-riscv64-linux-gnu.sh' + + workflow_dispatch: + +concurrency: + group: riscv64-linux-${{ github.ref }} + cancel-in-progress: true + +jobs: + riscv64_linux: + runs-on: ${{ matrix.os }} + name: ${{ matrix.os }} ${{ matrix.lib_type }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + lib_type: [static, shared] + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ matrix.os }}-riscv64-${{ matrix.lib_type }} + + - name: cache-qemu + id: cache-qemu + uses: actions/cache@v4 + with: + path: qemu-install + key: qemu-riscv-install-20240225 + + - name: install-qemu-build-deps + if: steps.cache-qemu.outputs.cache-hit != 'true' + run: | + sudo apt-get update + sudo apt-get install autoconf automake autotools-dev ninja-build + + - name: checkout-qemu + if: steps.cache-qemu.outputs.cache-hit != 'true' + uses: actions/checkout@v3 + with: + repository: qemu/qemu + path: qemu + + - name: qemu + if: steps.cache-qemu.outputs.cache-hit != 'true' + run: | + cd qemu + ./configure --prefix=$GITHUB_WORKSPACE/qemu-install --target-list=riscv64-linux-user --disable-system + make -j2 + make install + ls -lh $GITHUB_WORKSPACE/qemu-install + ls -lh $GITHUB_WORKSPACE/qemu-install/bin + + - name: cache-toolchain + id: cache-toolchain + uses: actions/cache@v4 + with: + path: toolchain + key: riscv64-glibc-ubuntu-20.04-gcc-nightly-2023.10.17-nightly + + - name: Download toolchain + if: steps.cache-toolchain.outputs.cache-hit != 'true' + shell: bash + run: | + mkdir $GITHUB_WORKSPACE/toolchain + wget -q https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2023.10.17/riscv64-glibc-ubuntu-20.04-gcc-nightly-2023.10.17-nightly.tar.gz + tar xvf ./riscv64-glibc-ubuntu-20.04-gcc-nightly-2023.10.17-nightly.tar.gz --strip-components 1 -C $GITHUB_WORKSPACE/toolchain + + - name: Display toolchain info + shell: bash + run: | + export PATH=$GITHUB_WORKSPACE/toolchain/bin:$PATH + riscv64-unknown-linux-gnu-gcc --version + + - name: Display qemu-riscv64 -h + shell: bash + run: | + export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH + export QEMU_LD_PREFIX=$GITHUB_WORKSPACE/toolchain/sysroot + qemu-riscv64 -h + + - name: build riscv64-linux + shell: bash + run: | + export PATH=$GITHUB_WORKSPACE/toolchain/bin:$PATH + + export CMAKE_CXX_COMPILER_LAUNCHER=ccache + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + + cmake --version + + lib_type=${{ matrix.lib_type }} + + if [[ $lib_type == "shared" ]]; then + export BUILD_SHARED_LIBS=ON + else + export BUILD_SHARED_LIBS=OFF + fi + + ./build-riscv64-linux-gnu.sh + + ls -lh build-riscv64-linux-gnu/bin + ls -lh build-riscv64-linux-gnu/lib + + file build-riscv64-linux-gnu/bin/sherpa-onnx + + - name: Test sherpa-onnx + shell: bash + run: | + export PATH=$GITHUB_WORKSPACE/toolchain/bin:$PATH + export PATH=$GITHUB_WORKSPACE/qemu-install/bin:$PATH + export QEMU_LD_PREFIX=$GITHUB_WORKSPACE/toolchain/sysroot + + ls -lh ./build-riscv64-linux-gnu/bin + + echo "----------sherpa-onnx----------" + qemu-riscv64 ./build-riscv64-linux-gnu/bin/sherpa-onnx --help + readelf -d ./build-riscv64-linux-gnu/bin/sherpa-onnx + + echo "----------sherpa-onnx-offline----------" + qemu-riscv64 ./build-riscv64-linux-gnu/bin/sherpa-onnx-offline --help + readelf -d ./build-riscv64-linux-gnu/bin/sherpa-onnx-offline + + echo "----------sherpa-onnx-offline-tts----------" + qemu-riscv64 ./build-riscv64-linux-gnu/bin/sherpa-onnx-offline-tts --help + readelf -d ./build-riscv64-linux-gnu/bin/sherpa-onnx-offline-tts + + - name: Copy files + shell: bash + run: | + export PATH=$GITHUB_WORKSPACE/toolchain/bin:$PATH + riscv64-unknown-linux-gnu-strip --version + + SHERPA_ONNX_VERSION=v$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2) + + dst=sherpa-onnx-${SHERPA_ONNX_VERSION}-linux-riscv64-${{ matrix.lib_type }} + mkdir $dst + + ls -lh build-riscv64-linux-gnu/install/lib + + cp -a build-riscv64-linux-gnu/install/bin $dst/ + ls -lh $dst/bin/* + riscv64-unknown-linux-gnu-strip $dst/bin/* + ls -lh $dst + + lib_type=${{ matrix.lib_type }} + if [[ $lib_type == "shared" ]]; then + cp -a build-riscv64-linux-gnu/install/lib $dst/ + rm -fv $dst/lib/libasound.so + rm -fv $dst/lib/libonnxruntime.so + rm -fv $dst/lib/libsherpa-onnx-fst.so + fi + + tree $dst + + tar cjvf ${dst}.tar.bz2 $dst + + - uses: actions/upload-artifact@v4 + if: matrix.lib_type == 'shared' + with: + name: sherpa-onnx-linux-riscv64-shared + path: sherpa-onnx-*linux-riscv64-shared.tar.bz2 + + - uses: actions/upload-artifact@v4 + if: matrix.lib_type == 'static' + with: + name: sherpa-onnx-linux-riscv64-static + path: sherpa-onnx-*linux-riscv64-static.tar.bz2 + + - name: Release pre-compiled binaries and libs for riscv64 linux ${{ matrix.lib_type }} + if: github.repository_owner == 'csukuangfj' || github.repository_owner == 'k2-fsa' && github.event_name == 'push' && contains(github.ref, 'refs/tags/') + uses: svenstaro/upload-release-action@v2 + with: + file_glob: true + overwrite: true + file: sherpa-onnx-*linux-riscv64*.tar.bz2 diff --git a/build-riscv64-linux-gnu.sh b/build-riscv64-linux-gnu.sh new file mode 100755 index 000000000..96d65b446 --- /dev/null +++ b/build-riscv64-linux-gnu.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash + +if ! command -v riscv64-unknown-linux-gnu-g++ &> /dev/null; then + echo "Please install the toolchain first." + echo + echo "You can use the following command to install the toolchain:" + echo + echo " mkdir -p $HOME/software" + echo " cd $HOME/software" + echo " mkdir riscv64-glibc-ubuntu-18.04-nightly-2022.11.12-nightly" + echo " cd riscv64-glibc-ubuntu-18.04-nightly-2022.11.12-nightly" + echo " wget https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2022.11.12/riscv64-glibc-ubuntu-18.04-nightly-2022.11.12-nightly.tar.gz" + echo " tar xvf riscv64-glibc-ubuntu-18.04-nightly-2022.11.12-nightly.tar.gz --strip-components=1" + echo " export PATH=$HOME/software/riscv64-glibc-ubuntu-18.04-nightly-2022.11.12-nightly/bin" + echo + exit 1 +fi + +if [ x$dir = x"" ]; then + dir=build-riscv64-linux-gnu +fi +mkdir -p $dir +cd $dir + +if [ ! -f alsa-lib/src/.libs/libasound.so ]; then + echo "Start to cross-compile alsa-lib" + if [ ! -d alsa-lib ]; then + git clone --depth 1 https://github.com/alsa-project/alsa-lib + fi + # If it shows: + # ./gitcompile: line 79: libtoolize: command not found + # Please use: + # sudo apt-get install libtool m4 automake + # + pushd alsa-lib + CC=riscv64-unknown-linux-gnu-gcc ./gitcompile --host=riscv64-unknown-linux-gnu + popd + echo "Finish cross-compiling alsa-lib" +fi + +export CPLUS_INCLUDE_PATH=$PWD/alsa-lib/include:$CPLUS_INCLUDE_PATH +export SHERPA_ONNX_ALSA_LIB_DIR=$PWD/alsa-lib/src/.libs + +if [[ x"$BUILD_SHARED_LIBS" == x"" ]]; then + # By default, use static link + BUILD_SHARED_LIBS=OFF +fi + +cmake \ + -DBUILD_PIPER_PHONMIZE_EXE=OFF \ + -DBUILD_PIPER_PHONMIZE_TESTS=OFF \ + -DBUILD_ESPEAK_NG_EXE=OFF \ + -DBUILD_ESPEAK_NG_TESTS=OFF \ + -DCMAKE_INSTALL_PREFIX=./install \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS \ + -DSHERPA_ONNX_ENABLE_TESTS=OFF \ + -DSHERPA_ONNX_ENABLE_PYTHON=OFF \ + -DSHERPA_ONNX_ENABLE_CHECK=OFF \ + -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ + -DSHERPA_ONNX_ENABLE_JNI=OFF \ + -DSHERPA_ONNX_ENABLE_C_API=OFF \ + -DSHERPA_ONNX_ENABLE_WEBSOCKET=OFF \ + -DCMAKE_TOOLCHAIN_FILE=../toolchains/riscv64-linux-gnu.toolchain.cmake \ + .. + +make VERBOSE=1 -j4 +make install/strip + +# Enable it if only needed +# cp -v $SHERPA_ONNX_ALSA_LIB_DIR/libasound.so* ./install/lib/ diff --git a/cmake/onnxruntime-linux-riscv64-static.cmake b/cmake/onnxruntime-linux-riscv64-static.cmake new file mode 100644 index 000000000..8e7c2611f --- /dev/null +++ b/cmake/onnxruntime-linux-riscv64-static.cmake @@ -0,0 +1,64 @@ +# Copyright (c) 2022-2024 Xiaomi Corporation +message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") +message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") + +if(NOT CMAKE_SYSTEM_NAME STREQUAL Linux) + message(FATAL_ERROR "This file is for Linux only. Given: ${CMAKE_SYSTEM_NAME}") +endif() + +if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL riscv64) + message(FATAL_ERROR "This file is for riscv64 only. Given: ${CMAKE_SYSTEM_PROCESSOR}") +endif() + +if(BUILD_SHARED_LIBS) + message(FATAL_ERROR "This file is for building static libraries. BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") +endif() + +set(onnxruntime_URL "https://github.com/csukuangfj/onnxruntime-libs/releases/download/v1.18.0/onnxruntime-linux-riscv64-static_lib-1.18.0.zip") +set(onnxruntime_URL2 "https://hub.nuaa.cf/csukuangfj/onnxruntime-libs/releases/download/v1.18.0/onnxruntime-linux-riscv64-static_lib-1.18.0.zip") +set(onnxruntime_HASH "SHA256=6791d695d17118db6815364c975a9d7ea9a8909754516ed1b089fe015c20912e") + +# If you don't have access to the Internet, +# please download onnxruntime to one of the following locations. +# You can add more if you want. +set(possible_file_locations + $ENV{HOME}/Downloads/onnxruntime-linux-riscv64-static_lib-1.18.0.zip + ${CMAKE_SOURCE_DIR}/onnxruntime-linux-riscv64-static_lib-1.18.0.zip + ${CMAKE_BINARY_DIR}/onnxruntime-linux-riscv64-static_lib-1.18.0.zip + /tmp/onnxruntime-linux-riscv64-static_lib-1.18.0.zip + /star-fj/fangjun/download/github/onnxruntime-linux-riscv64-static_lib-1.18.0.zip +) + +foreach(f IN LISTS possible_file_locations) + if(EXISTS ${f}) + set(onnxruntime_URL "${f}") + file(TO_CMAKE_PATH "${onnxruntime_URL}" onnxruntime_URL) + message(STATUS "Found local downloaded onnxruntime: ${onnxruntime_URL}") + set(onnxruntime_URL2) + break() + endif() +endforeach() + +FetchContent_Declare(onnxruntime + URL + ${onnxruntime_URL} + ${onnxruntime_URL2} + URL_HASH ${onnxruntime_HASH} +) + +FetchContent_GetProperties(onnxruntime) +if(NOT onnxruntime_POPULATED) + message(STATUS "Downloading onnxruntime from ${onnxruntime_URL}") + FetchContent_Populate(onnxruntime) +endif() +message(STATUS "onnxruntime is downloaded to ${onnxruntime_SOURCE_DIR}") + +# for static libraries, we use onnxruntime_lib_files directly below +include_directories(${onnxruntime_SOURCE_DIR}/include) + +file(GLOB onnxruntime_lib_files "${onnxruntime_SOURCE_DIR}/lib/lib*.a") + +set(onnxruntime_lib_files ${onnxruntime_lib_files} PARENT_SCOPE) + +message(STATUS "onnxruntime lib files: ${onnxruntime_lib_files}") +install(FILES ${onnxruntime_lib_files} DESTINATION lib) diff --git a/cmake/onnxruntime-linux-riscv64.cmake b/cmake/onnxruntime-linux-riscv64.cmake new file mode 100644 index 000000000..748a2bb52 --- /dev/null +++ b/cmake/onnxruntime-linux-riscv64.cmake @@ -0,0 +1,73 @@ +# Copyright (c) 2022-2024 Xiaomi Corporation +message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") +message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") + +if(NOT CMAKE_SYSTEM_NAME STREQUAL Linux) + message(FATAL_ERROR "This file is for Linux only. Given: ${CMAKE_SYSTEM_NAME}") +endif() + +if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL riscv64) + message(FATAL_ERROR "This file is for riscv64 only. Given: ${CMAKE_SYSTEM_PROCESSOR}") +endif() + +if(NOT BUILD_SHARED_LIBS) + message(FATAL_ERROR "This file is for building shared libraries. BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}") +endif() + +set(onnxruntime_URL "https://github.com/csukuangfj/onnxruntime-libs/releases/download/v1.18.0/onnxruntime-linux-riscv64-1.18.0.zip") +set(onnxruntime_URL2 "https://hub.nuaa.cf/csukuangfj/onnxruntime-libs/releases/download/v1.18.0/onnxruntime-linux-riscv64-1.18.0.zip") +set(onnxruntime_HASH "SHA256=87ef36dbba28ee332069e7e511dcb409913bdeeed231b45172fe200d71c690a2") + +# If you don't have access to the Internet, +# please download onnxruntime to one of the following locations. +# You can add more if you want. +set(possible_file_locations + $ENV{HOME}/Downloads/onnxruntime-linux-riscv64-1.18.0.zip + ${CMAKE_SOURCE_DIR}/onnxruntime-linux-riscv64-1.18.0.zip + ${CMAKE_BINARY_DIR}/onnxruntime-linux-riscv64-1.18.0.zip + /tmp/onnxruntime-linux-riscv64-1.18.0.zip + /star-fj/fangjun/download/github/onnxruntime-linux-riscv64-1.18.0.zip +) + +foreach(f IN LISTS possible_file_locations) + if(EXISTS ${f}) + set(onnxruntime_URL "${f}") + file(TO_CMAKE_PATH "${onnxruntime_URL}" onnxruntime_URL) + message(STATUS "Found local downloaded onnxruntime: ${onnxruntime_URL}") + set(onnxruntime_URL2) + break() + endif() +endforeach() + +FetchContent_Declare(onnxruntime + URL + ${onnxruntime_URL} + ${onnxruntime_URL2} + URL_HASH ${onnxruntime_HASH} +) + +FetchContent_GetProperties(onnxruntime) +if(NOT onnxruntime_POPULATED) + message(STATUS "Downloading onnxruntime from ${onnxruntime_URL}") + FetchContent_Populate(onnxruntime) +endif() +message(STATUS "onnxruntime is downloaded to ${onnxruntime_SOURCE_DIR}") + +find_library(location_onnxruntime onnxruntime + PATHS + "${onnxruntime_SOURCE_DIR}/lib" + NO_CMAKE_SYSTEM_PATH +) + +message(STATUS "location_onnxruntime: ${location_onnxruntime}") + +add_library(onnxruntime SHARED IMPORTED) + +set_target_properties(onnxruntime PROPERTIES + IMPORTED_LOCATION ${location_onnxruntime} + INTERFACE_INCLUDE_DIRECTORIES "${onnxruntime_SOURCE_DIR}/include/onnxruntime" +) + +file(GLOB onnxruntime_lib_files "${onnxruntime_SOURCE_DIR}/lib/libonnxruntime*") +message(STATUS "onnxruntime lib files: ${onnxruntime_lib_files}") +install(FILES ${onnxruntime_lib_files} DESTINATION lib) diff --git a/cmake/onnxruntime.cmake b/cmake/onnxruntime.cmake index a92ffa4eb..9dda2b148 100644 --- a/cmake/onnxruntime.cmake +++ b/cmake/onnxruntime.cmake @@ -6,6 +6,12 @@ function(download_onnxruntime) message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") if(SHERPA_ONNX_ENABLE_WASM) include(onnxruntime-wasm-simd) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL riscv64) + if(BUILD_SHARED_LIBS) + include(onnxruntime-linux-riscv64) + else() + include(onnxruntime-linux-riscv64-static) + endif() elseif(CMAKE_SYSTEM_NAME STREQUAL Linux AND CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) if(BUILD_SHARED_LIBS) include(onnxruntime-linux-aarch64) diff --git a/cmake/piper-phonemize.cmake b/cmake/piper-phonemize.cmake index 9c0ffa4cc..4facf7e17 100644 --- a/cmake/piper-phonemize.cmake +++ b/cmake/piper-phonemize.cmake @@ -2,7 +2,7 @@ function(download_piper_phonemize) include(FetchContent) set(piper_phonemize_URL "https://github.com/csukuangfj/piper-phonemize/archive/dc6b5f4441bffe521047086930b0fc12686acd56.zip") - set(piper_phonemize_URL2 "") + set(piper_phonemize_URL2 "https://hub.nuaa.cf/csukuangfj/piper-phonemize/archive/dc6b5f4441bffe521047086930b0fc12686acd56.zip") set(piper_phonemize_HASH "SHA256=b9faa04204b1756fa455a962abb1f037041c040133d55be58d11f11ab9b3ce14") # If you don't have access to the Internet, diff --git a/toolchains/riscv64-linux-gnu.toolchain.cmake b/toolchains/riscv64-linux-gnu.toolchain.cmake new file mode 100644 index 000000000..8f07b964c --- /dev/null +++ b/toolchains/riscv64-linux-gnu.toolchain.cmake @@ -0,0 +1,17 @@ +# Copied from https://github.com/Tencent/ncnn/blob/master/toolchains/riscv64-linux-gnu.toolchain.cmake +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR riscv64) + +set(CMAKE_C_COMPILER "riscv64-unknown-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "riscv64-unknown-linux-gnu-g++") + +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_C_FLAGS "-march=rv64gc") +set(CMAKE_CXX_FLAGS "-march=rv64gc") + +# cache flags +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags")