diff --git a/.github/workflows/kvrocks.yaml b/.github/workflows/kvrocks.yaml index 692ae78c212..5b83f430824 100644 --- a/.github/workflows/kvrocks.yaml +++ b/.github/workflows/kvrocks.yaml @@ -223,11 +223,21 @@ jobs: os: ubuntu-24.04-arm compiler: clang arm_linux: true + - name: Ubuntu RISC-V GCC without luaJIT (QEMU) + os: ubuntu-24.04 + riscv_toolchain: true + toolchain_file: cmake/riscv64.cmake + riscv_toolchain_url: "https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2025.07.03/riscv64-glibc-ubuntu-24.04-gcc-nightly-2025.07.03-nightly.tar.xz" + cmake_crosscompiling: -DCMAKE_CROSSCOMPILING=TRUE + cmake_system_name: -DCMAKE_SYSTEM_NAME=Linux + cmake_system_processor: -DCMAKE_SYSTEM_PROCESSOR=riscv64 + without_luajit: -DENABLE_LUAJIT=OFF runs-on: ${{ matrix.os }} env: SONARCLOUD_OUTPUT_DIR: sonarcloud-data FORCE_JAVASCRIPT_ACTIONS_TO_NODE20: true + RISCV_PATH: "/opt/riscv" steps: - name: Setup macOS if: ${{ startsWith(matrix.os, 'macos') }} @@ -253,6 +263,20 @@ jobs: if: ${{ matrix.arm_linux }} run: | sudo apt install -y git build-essential cmake libtool python3 python3-pip libssl-dev + - name: Setup RISC-V Toolchain + if: ${{ matrix.riscv_toolchain }} + run: | + sudo apt install -y wget build-essential cmake git python3 \ + libgflags-dev libsnappy-dev zlib1g-dev liblz4-dev libzstd-dev \ + qemu-user qemu-user-static + sudo mkdir -p $RISCV_PATH + wget "${{ matrix.riscv_toolchain_url }}" -O riscv-toolchain.tar.xz + sudo tar -xvf riscv-toolchain.tar.xz -C $RISCV_PATH --strip-components=1 + sudo sed -i "s|libdir='/mnt/riscv/riscv64-unknown-linux-gnu/lib'|libdir='$RISCV_PATH/riscv64-unknown-linux-gnu/lib'|g" \ + $RISCV_PATH/riscv64-unknown-linux-gnu/lib/libatomic.la + echo "PATH=$RISCV_PATH/bin:$PATH" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/opt/riscv/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV + echo "QEMU_LD_PREFIX=$RISCV_PATH/sysroot" >> $GITHUB_ENV - name: Cache redis id: cache-redis @@ -298,7 +322,7 @@ jobs: if: ${{ matrix.sonarcloud }} - name: Build Kvrocks - if: ${{ !matrix.sonarcloud }} + if: ${{ !matrix.sonarcloud && !matrix.riscv_toolchain }} run: | ./x.py build -j$NPROC --unittest --compiler ${{ matrix.compiler }} ${{ matrix.without_jemalloc }} \ ${{ matrix.without_luajit }} ${{ matrix.with_ninja }} ${{ matrix.with_sanitizer }} ${{ matrix.with_openssl }} \ @@ -311,6 +335,11 @@ jobs: cp -r build _build build-wrapper-linux-x86-64 --out-dir ${{ env.SONARCLOUD_OUTPUT_DIR }} ./x.py build -j$NPROC --unittest --compiler ${{ matrix.compiler }} ${{ matrix.sonarcloud }} + - name: Build Kvrocks (RISC-V) + if: ${{ matrix.riscv_toolchain }} + run: | + ./x.py build -j$NPROC --unittest --toolchain ${{ matrix.toolchain_file }} + - name: Setup Coredump if: ${{ startsWith(matrix.os, 'ubuntu') }} run: | diff --git a/cmake/jemalloc.cmake b/cmake/jemalloc.cmake index 02dbfc4297c..5042c2fe700 100644 --- a/cmake/jemalloc.cmake +++ b/cmake/jemalloc.cmake @@ -43,7 +43,7 @@ if(NOT jemalloc_POPULATED) execute_process(COMMAND autoconf WORKING_DIRECTORY ${jemalloc_SOURCE_DIR} ) - execute_process(COMMAND ${jemalloc_SOURCE_DIR}/configure CC=${CMAKE_C_COMPILER} -C --enable-autogen + execute_process(COMMAND ${jemalloc_SOURCE_DIR}/configure CC=${CMAKE_C_COMPILER} -C ${JEMALLOC_CROSS_FLAGS} --enable-autogen --disable-shared --disable-libdl ${DISABLE_CACHE_OBLIVIOUS} ${ENABLE_JEMALLOC_PROFILING} --with-jemalloc-prefix="" WORKING_DIRECTORY ${jemalloc_BINARY_DIR} diff --git a/cmake/riscv64.cmake b/cmake/riscv64.cmake new file mode 100644 index 00000000000..1534caf1323 --- /dev/null +++ b/cmake/riscv64.cmake @@ -0,0 +1,33 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR riscv64) +set(CMAKE_CROSSCOMPILING TRUE) + +set(CMAKE_C_COMPILER "riscv64-unknown-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "riscv64-unknown-linux-gnu-g++") + +add_compile_options("-march=rv64gc") + +set(JEMALLOC_CROSS_FLAGS + "--host=riscv64-unknown-linux-gnu" + "--build=${CMAKE_HOST_SYSTEM_PROCESSOR}-pc-linux-gnu" + "--with-lg-vaddr=48" + CACHE STRING "jemalloc flags for RISC-V cross-compilation" +) +set(ENABLE_LUAJIT OFF CACHE BOOL "Disable LuaJIT on RISC-V" FORCE) diff --git a/cmake/tbb.cmake b/cmake/tbb.cmake index bb54a00a2bc..d2badda36b0 100644 --- a/cmake/tbb.cmake +++ b/cmake/tbb.cmake @@ -20,8 +20,8 @@ include_guard() include(cmake/utils.cmake) FetchContent_DeclareGitHubWithMirror(tbb - uxlfoundation/oneTBB v2022.2.0 - MD5=b00d733b2adf0fba1d33855689631b4d + uxlfoundation/oneTBB v2022.1.0 + MD5=4a8940795f7e414727a1c443b94fd686 ) FetchContent_MakeAvailableWithArgs(tbb diff --git a/x.py b/x.py index 686effc968c..76dda1e64ca 100755 --- a/x.py +++ b/x.py @@ -114,7 +114,7 @@ def prepare() -> None: print(f"{hook.name} installed at {dst}.") def build(dir: str, jobs: Optional[int], ninja: bool, unittest: bool, compiler: str, cmake_path: str, D: List[str], - skip_build: bool) -> None: + skip_build: bool, toolchain: Optional[str] = None) -> None: basedir = Path(__file__).parent.absolute() find_command("autoconf", msg="autoconf is required to build jemalloc") @@ -129,6 +129,8 @@ def build(dir: str, jobs: Optional[int], ninja: bool, unittest: bool, compiler: os.makedirs(dir, exist_ok=True) cmake_options = ["-DCMAKE_BUILD_TYPE=RelWithDebInfo"] + if toolchain: + cmake_options.append(f"-DCMAKE_TOOLCHAIN_FILE={toolchain}") if ninja: cmake_options.append("-G Ninja") if compiler == 'gcc': @@ -389,6 +391,7 @@ def test_go(dir: str, cli_path: str, rest: List[str]) -> None: parser_build.add_argument('--unittest', default=False, action='store_true', help='build unittest target') parser_build.add_argument('--compiler', default='auto', choices=('auto', 'gcc', 'clang'), help="compiler used to build kvrocks") + parser_build.add_argument('--toolchain', metavar='FILE', help="path to CMake toolchain file for cross-compiling") parser_build.add_argument('--cmake-path', default='cmake', help="path of cmake binary used to build kvrocks") parser_build.add_argument('-D', action='append', metavar='key=value', help='extra CMake definitions') parser_build.add_argument('--skip-build', default=False, action='store_true',