diff --git a/.github/workflows/kvrocks.yaml b/.github/workflows/kvrocks.yaml index 84ad4f7b8db..35fe1eb8d80 100644 --- a/.github/workflows/kvrocks.yaml +++ b/.github/workflows/kvrocks.yaml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: apache/skywalking-eyes/header@501a28d2fb4a9b962661987e50cf0219631b32ff + - uses: apache/skywalking-eyes/header@v0.4.0 with: config: tools/ci/licenserc.yml @@ -42,19 +42,20 @@ jobs: steps: - name: Checkout Code Base uses: actions/checkout@v3 - - name: Install Check Tools run: | - sudo pip install --upgrade pip - sudo pip install --upgrade setuptools sudo apt update sudo apt install -y cppcheck - sudo pip install cpplint==1.5.0 - + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: 3.x + - name: Setup dependencies + run: pip install cpplint==1.5.0 - name: Lint and check code run: | - ./cpplint.sh - ./cppcheck.sh + ./x.py check cpplint + ./x.py check cppcheck build-and-test: name: Build and test @@ -65,42 +66,50 @@ jobs: include: - name: Darwin Clang os: macos-latest + compiler: auto - name: Darwin Clang without Jemalloc os: macos-latest + compiler: auto without_jemalloc: -DDISABLE_JEMALLOC=ON - name: Ubuntu GCC os: ubuntu-18.04 + compiler: gcc - name: Ubuntu Clang os: ubuntu-18.04 - clang: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + compiler: clang - name: Ubuntu GCC ASan os: ubuntu-18.04 with_sanitizer: -DENABLE_ASAN=ON + compiler: gcc # - name: Ubuntu GCC TSan # os: ubuntu-18.04 # with_sanitizer: -DENABLE_TSAN=ON + # compiler: gcc - name: Ubuntu GCC without Jemalloc os: ubuntu-18.04 without_jemalloc: -DDISABLE_JEMALLOC=ON + compiler: gcc - name: Ubuntu Clang ASan os: ubuntu-18.04 with_sanitizer: -DENABLE_ASAN=ON - clang: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + compiler: clang # - name: Ubuntu Clang TSan # os: ubuntu-18.04 # with_sanitizer: -DENABLE_TSAN=ON - # clang: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + # compiler: clang - name: Ubuntu Clang without Jemalloc os: ubuntu-18.04 without_jemalloc: -DDISABLE_JEMALLOC=ON - clang: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + compiler: clang - name: Ubuntu GCC Ninja os: ubuntu-18.04 with_ninja: --ninja + compiler: gcc - name: Ubuntu GCC Ninja without Jemalloc os: ubuntu-18.04 with_ninja: --ninja without_jemalloc: -DDISABLE_JEMALLOC=ON + compiler: gcc runs-on: ${{ matrix.os }} steps: @@ -117,7 +126,7 @@ jobs: run: | brew install cmake gcc autoconf automake libtool echo "NPROC=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV - + - name: Setup Linux if: ${{ startsWith(matrix.os, 'ubuntu') }} run: | @@ -136,8 +145,13 @@ jobs: - name: Checkout Code Base uses: actions/checkout@v3 + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: 3.x + - name: Build Kvrocks - run: ./build.sh build -j$NPROC --unittest ${{ matrix.clang }} ${{ matrix.with_ninja }} ${{ matrix.with_sanitizer }} ${{ matrix.without_jemalloc }} + run: ./x.py build -j$NPROC --unittest --compiler ${{ matrix.compiler }} ${{ matrix.with_ninja }} ${{ matrix.with_sanitizer }} ${{ matrix.without_jemalloc }} - name: Run Unit Test run: ./build/unittest diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 112654461f2..a033ee677c7 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -47,7 +47,7 @@ jobs: - name: Build run: | - ./build.sh build + ./x.py build cd build cp kvrocks release/bin/ cp kvrocks2redis release/bin/ @@ -113,7 +113,7 @@ jobs: - name: Build run: | mkdir -p build/release - ./build.sh build + ./x.py build cd build mkdir -p release/bin release/conf cp kvrocks release/bin/ diff --git a/Dockerfile b/Dockerfile index f8a88495275..778f3956179 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,11 +22,11 @@ ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN apt update -RUN apt install -y cmake make git autoconf libtool g++ +RUN apt install -y cmake make git autoconf libtool g++ python3 WORKDIR /kvrocks COPY . . -RUN ./build.sh build +RUN ./x.py build FROM ubuntu:focal diff --git a/README.md b/README.md index 7a05cc1e129..4c9a9392508 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,18 @@ --- -- [Google Group](https://groups.google.com/g/kvrocks) -- [Slack Channel](https://join.slack.com/t/kvrockscommunity/shared_invite/zt-p5928e3r-OUAK8SUgC8GOceGM6dAz6w) +* [Google Group](https://groups.google.com/g/kvrocks) +* [Slack Channel](https://join.slack.com/t/kvrockscommunity/shared_invite/zt-p5928e3r-OUAK8SUgC8GOceGM6dAz6w) **Apache Kvrocks(Incubating)** is a distributed key value NoSQL database that uses RocksDB as storage engine and is compatible with Redis protocol. Kvrocks intends to decrease the cost of memory and increase the capacity while compared to Redis. The design of replication and storage was inspired by `rocksplicator` and `blackwidow`. Kvrocks has the following key features: -- Redis protocol, user can use redis client to visit the kvrocks -- Namespace, similar to redis db but use token per namespace -- Replication, async replication using binlog like MySQL -- High Available, supports redis sentinel to failover when master or slave was failed -- Cluster mode, centralized management but compatible with Redis cluster client access +* Redis protocol, user can use redis client to visit the kvrocks +* Namespace, similar to redis db but use token per namespace +* Replication, async replication using binlog like MySQL +* High Available, supports redis sentinel to failover when master or slave was failed +* Cluster mode, centralized management but compatible with Redis cluster client access > Thanks for designers @[田凌宇](https://github.com/tianlingyu1997) and @范世丽 contribute the kvrocks logo for us. @@ -41,35 +41,34 @@ Kvrocks has the following key features: -***Tickets a pull reqeust to let us known that you're using kvrocks and add your logo to README*** +***Tickets a pull request to let us known that you're using kvrocks and add your logo to README*** -## Building kvrocks +## Build and Run kvrocks -#### requirements -* g++ (required by c++11, version >= 4.8) -* autoconf automake libtool cmake - -#### Build +### Prerequisite ```shell -# Centos/Redhat -sudo yum install -y epel-release && sudo yum install -y git gcc gcc-c++ make cmake autoconf automake libtool which +# CentOS / RedHat +sudo yum install -y epel-release +sudo yum install -y git gcc gcc-c++ make cmake autoconf automake libtool which -# Ubuntu/Debian +# Ubuntu / Debian sudo apt update -sudo apt-get install gcc g++ make cmake autoconf automake libtool +sudo apt install -y gcc g++ make cmake autoconf automake libtool # macOS brew install autoconf automake libtool cmake ``` +### Build + It is as simple as: ```shell $ git clone https://github.com/apache/incubator-kvrocks.git $ cd incubator-kvrocks -$ ./build.sh build # `./build.sh -h` to check more options; - # especially, `./build.sh build --ghproxy` will fetch dependencies via ghproxy.com. +$ ./x.py build # `./x.py build -h` to check more options; + # especially, `./x.py build --ghproxy` will fetch dependencies via ghproxy.com. ``` ### Running kvrocks @@ -111,7 +110,7 @@ $ ./unittest ## Namespace -namespace was used to isolate data between users. unlike all the redis databases can be visited by `requirepass`, we use one token per namespace. `requirepass` was regraded as admin token, only admin token allows to access the namespace command, as well as some commands like `config`, `slaveof`, `bgsave`, etc… +Namespace is used to isolate data between users. Unlike all the Redis databases can be visited by `requirepass`, we use one token per namespace. `requirepass` is regraded as admin token, and only admin token allows to access the namespace command, as well as some commands like `config`, `slaveof`, `bgsave`, etc.. ``` # add token @@ -136,24 +135,25 @@ OK ## Cluster -Kvrocks implements a proxyless centralized cluster solution but its accessing method is completely compatible with the Redis cluster client. You can use Redis cluster SDKs to access the kvrocks cluster. More details, please see: [Kvrocks Cluster Introduction](https://github.com/apache/incubator-kvrocks/wiki/Kvrocks-Cluster-Introduction) +Kvrocks implements a proxyless centralized cluster solution but its accessing method is completely compatible with the Redis cluster client. You can use Redis cluster SDKs to access the kvrocks cluster. More details, please see: [Kvrocks Cluster Introduction](https://kvrocks.apache.org/docs/Cluster/kvrocks-cluster-introduction) -## DOCs +## Documents -* [supported commands](https://github.com/apache/incubator-kvrocks/wiki/Support-Commands) -* [design complex kv on rocksdb](https://github.com/apache/incubator-kvrocks/blob/master/docs/metadata-design.md) -* [replication design](https://github.com/apache/incubator-kvrocks/blob/master/docs/replication-design.md) +Documents are hosted at the [official website](https://kvrocks.apache.org/docs/supported-commands). -For more informations, can see: [Kvrocks Wiki](https://github.com/apache/incubator-kvrocks/wiki) +* [Supported Commands](https://kvrocks.apache.org/docs/supported-commands) +* [Design Complex Structure on RocksDB](https://kvrocks.apache.org/docs/Design/design-structure-on-rocksdb) +* [Replication Design](https://kvrocks.apache.org/docs/Design/replication) ## Tools + * Export the Kvrocks monitor metrics, please use [kvrocks_exporter](https://github.com/KvrocksLabs/kvrocks_exporter) -* Migrate from redis to kvrocks, use [redis-migrate-tool](https://github.com/vipshop/redis-migrate-tool) which was developed by vipshop +* Migrate from redis to kvrocks, use [redis-migrate-tool](https://github.com/vipshop/redis-migrate-tool) which was developed by @vipshop * Migrate from kvrocks to redis. use `kvrocks2redis` in build dir ## Performance -#### Hardware +### Hardware * CPU: 48 cores Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz * Memory: 32 GiB @@ -162,21 +162,21 @@ For more informations, can see: [Kvrocks Wiki](https://github.com/apache/incubat > Benchmark Client: multi-thread redis-benchmark(unstable branch) - #### 1. Commands QPS +### 1. Commands QPS > kvrocks: workers = 16, benchmark: 8 threads/ 512 conns / 128 payload latency: 99.9% < 10ms -![image](https://raw.githubusercontent.com/apache/incubator-kvrocks/master/docs/images/chart-commands.png) +![image](docs/images/chart-commands.png) -#### 2. QPS on different payloads +### 2. QPS on different payloads > kvrocks: workers = 16, benchmark: 8 threads/ 512 conns latency: 99.9% < 10ms -![image](https://raw.githubusercontent.com/apache/incubator-kvrocks/master/docs/images/chart-values.png) +![image](docs/images/chart-values.png) #### 3. QPS on different workers @@ -184,12 +184,12 @@ latency: 99.9% < 10ms latency: 99.9% < 10ms -![image](https://raw.githubusercontent.com/apache/incubator-kvrocks/master/docs/images/chart-threads.png) +![image](docs/images/chart-threads.png) ## License -Kvrocks is under the Apache License Version 2.0. See the LICENSE file for details. +Kvrocks is under the Apache License Version 2.0. See the [LICENSE](LICENSE) file for details. ## WeChat Official Account (微信公众号) -WeChat offical account +![WeChat official account](docs/images/wechat_account.jpg) diff --git a/build.sh b/build.sh deleted file mode 100755 index de3026d8e90..00000000000 --- a/build.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env bash -# 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 -e - -function usage() { - echo "Usage: $0 BUILD_DIR [-Dvar=value ...] [--unittest] [-jN] [-h|--help]" >&2 - echo >&2 - echo "BUILD_DIR : directory to store cmake-generated and build files" >&2 - echo "-Dvar=value : extra cmake definitions" >&2 - echo "-jN : execute N build jobs concurrently, default N = 4" >&2 - echo "--unittest : build unittest target" >&2 - echo "--ninja : use ninja to build kvrocks" >&2 - echo "--gcc : use gcc/g++ to build kvrocks" >&2 - echo "--clang : use clang/clang++ to build kvrocks" >&2 - echo "--ghproxy : use ghproxy.com to fetch dependencies" >&2 - echo "-h, --help : print this help messages" >&2 - exit 1 -} - -until [ $# -eq 0 ]; do - case $1 in - -D*) CMAKE_DEFS="$CMAKE_DEFS $1";; - --unittest) BUILD_UNITTEST=1;; - --ninja) USE_NINJA="-G Ninja";; - --gcc) COMPILER="-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++";; - --clang) COMPILER="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++";; - --ghproxy) USE_GHPROXY="-DDEPS_FETCH_PROXY=https://ghproxy.com/";; - -j*) JOB_CMD=$1;; - -*) usage;; - *) BUILD_DIR=$1;; - esac - shift -done - -if [ -z "$BUILD_DIR" ]; then - usage -fi - -if [ -z "$JOB_CMD" ]; then - JOB_CMD="-j4" -fi - -WORKING_DIR=$(pwd) -CMAKE_INSTALL_DIR=$WORKING_DIR/$BUILD_DIR/cmake -CMAKE_REQUIRE_VERSION="3.13.0" - -RED='\033[0;31m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -if [ ! -x "$(command -v autoconf)" ]; then - printf ${RED}"The autoconf was required to build jemalloc\n"${NC} - printf ${YELLOW}"Please use 'yum install -y autoconf automake libtool' in centos/redhat, or use 'apt-get install autoconf automake libtool' in debian/ubuntu"${NC}"\n" - exit 1 -fi - -if [ -x "$(command -v cmake)" ]; then - CMAKE_BIN=$(command -v cmake) -fi - -if [ -x "$CMAKE_INSTALL_DIR/bin/cmake" ]; then - CMAKE_BIN=$CMAKE_INSTALL_DIR/bin/cmake -fi - -if [ -f "$CMAKE_BIN" ]; then - CMAKE_VERSION=`$CMAKE_BIN -version | head -n 1 | sed 's/[^0-9.]*//g'` -else - CMAKE_VERSION=0 -fi - -if [ "$(printf '%s\n' "$CMAKE_REQUIRE_VERSION" "$CMAKE_VERSION" | sort -V | head -n1)" != "$CMAKE_REQUIRE_VERSION" ]; then - printf ${YELLOW}"CMake $CMAKE_REQUIRE_VERSION or higher is required. Trying to install CMake $CMAKE_REQUIRE_VERSION ..."${NC}"\n" - if [ ! -x "$(command -v curl)" ]; then - printf ${RED}"Please install the curl first to download the cmake"${NC}"\n" - exit 1 - fi - mkdir -p $BUILD_DIR/cmake - cd $BUILD_DIR - CMAKE_DOWNLOAD_VERSION=3.23.1 - curl -O -L https://github.com/Kitware/CMake/releases/download/v$CMAKE_DOWNLOAD_VERSION/cmake-$CMAKE_DOWNLOAD_VERSION.tar.gz - tar -zxf cmake-$CMAKE_DOWNLOAD_VERSION.tar.gz && cd cmake-$CMAKE_DOWNLOAD_VERSION - ./bootstrap --prefix=$CMAKE_INSTALL_DIR -- -DCMAKE_USE_OPENSSL=OFF && make && make install && cd ../.. - CMAKE_BIN=$CMAKE_INSTALL_DIR/bin/cmake -fi - -mkdir -p $BUILD_DIR -cd $BUILD_DIR - -set -x -$CMAKE_BIN $WORKING_DIR -DCMAKE_BUILD_TYPE=RelWithDebInfo $CMAKE_DEFS $USE_NINJA $COMPILER $USE_GHPROXY -$CMAKE_BIN --build . $JOB_CMD -t kvrocks kvrocks2redis - -if [ -n "$BUILD_UNITTEST" ]; then - $CMAKE_BIN --build . $JOB_CMD -t unittest -fi diff --git a/cppcheck.sh b/cppcheck.sh deleted file mode 100755 index e48bc57910b..00000000000 --- a/cppcheck.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -# 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. - -# we should run cmake configuration to fetch deps if we want to enable missingInclude -CHECK_TYPES="warning,portability,information" -STANDARD=c++11 -ERROR_EXITCODE=1 -LANG=c++ - -set -ex -cppcheck --version -cppcheck \ - --force --enable=${CHECK_TYPES} -U__GNUC__ -x ${LANG} src --std=${STANDARD} --error-exitcode=${ERROR_EXITCODE} \ - --inline-suppr -j$(nproc) diff --git a/cpplint.sh b/cpplint.sh deleted file mode 100755 index 39d675b3c79..00000000000 --- a/cpplint.sh +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - -cpplint --linelength=120 --filter=-build/include_subdir,-legal/copyright,-build/c++11 src/*.h src/*.cc diff --git a/x.py b/x.py new file mode 100755 index 00000000000..1ea89b77ed5 --- /dev/null +++ b/x.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 + +# 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. + +import argparse +import glob +import os +import pathlib +import re +import subprocess +import sys + +CMAKE_REQUIRE_VERSION = (3, 13, 0) +SEMVER_REGEX = re.compile( + r""" + ^ + (?P0|[1-9]\d*) + \. + (?P0|[1-9]\d*) + \. + (?P0|[1-9]\d*) + (?:-(?P + (?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*) + (?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))* + ))? + (?:\+(?P + [0-9a-zA-Z-]+ + (?:\.[0-9a-zA-Z-]+)* + ))? + $ + """, + re.VERBOSE, +) + +def run(args, msg=None, **kwargs): + sys.stdout.flush() + p = subprocess.Popen(args, **kwargs) + code = p.wait() + if code != 0: + err = f""" +failed to run: {args} +exit with code: {code} +error message: {msg} +""" + raise RuntimeError(err) + else: + return p.stdout + +def find_command(command, msg=None): + output = run(["bash", "-c", f"command -v {command}"], stdout=subprocess.PIPE) + path = output.read().decode().strip() + run(["test", "-x", path], msg=msg) + return path + +def build(args): + (dir, jobs, ghproxy, ninja, unittest, compiler, d) = (args.dir, args.jobs, args.ghproxy, args.ninja, args.unittest, args.compiler, args.D) + + basedir = pathlib.Path(__file__).parent.absolute() + + find_command("autoconf", msg="autoconf is required to build jemalloc") + cmake = find_command("cmake", msg="CMake is required") + + output = run([cmake, "-version"], stdout=subprocess.PIPE) + output = run(["head", "-n", "1"], stdin=output, stdout=subprocess.PIPE) + output = run(["sed", "s/[^0-9.]*//g"], stdin=output, stdout=subprocess.PIPE) + cmake_version = output.read().decode().strip() + cmake_require_version = '.'.join(map(str, CMAKE_REQUIRE_VERSION)) + cmake_semver = SEMVER_REGEX.match(cmake_version) + if cmake_semver is None: + raise RuntimeError(f"CMake {cmake_require_version} or higher is required, got: {cmake_version}") + cmake_semver = cmake_semver.groupdict() + cmake_semver = (int(cmake_semver["major"]), int(cmake_semver["minor"]), int(cmake_semver["patch"])) + if cmake_semver < CMAKE_REQUIRE_VERSION: + raise RuntimeError(f"CMake {cmake_require_version} or higher is required, got: {cmake_version}") + + os.makedirs(dir, exist_ok=True) + os.chdir(dir) + + cmake_options = ["-DCMAKE_BUILD_TYPE=RelWithDebInfo"] + if ghproxy: + cmake_options.append("-DDEPS_FETCH_PROXY=https://ghproxy.com/") + if ninja: + cmake_options.append("-G Ninja") + if compiler == 'gcc': + cmake_options += ["-DCMAKE_C_COMPILER=gcc", "-DCMAKE_CXX_COMPILER=g++"] + elif compiler == 'clang': + cmake_options += ["-DCMAKE_C_COMPILER=clang", "-DCMAKE_CXX_COMPILER=clang++"] + if d: + cmake_options += [f"-D{o}" for o in d] + run([cmake, basedir, *cmake_options]) + + target = ["kvrocks", "kvrocks2redis"] + if unittest: + target.append("unittest") + run([cmake, "--build", ".", f"-j{jobs}", "-t", *target]) + +def cpplint(args): + command = find_command("cpplint", msg="cpplint is required") + options = ["--linelength=120", "--filter=-build/include_subdir,-legal/copyright,-build/c++11"] + sources = [*glob.glob("src/*.h"), *glob.glob("src/*.cc")] + run([command, *options, *sources]) + +def cppcheck(args): + command = find_command("cppcheck", msg="cppcheck is required") + + options = ["-x", "c++"] + options.append("-U__GNUC__") + options.append("--force") + options.append("--std=c++11") + # we should run cmake configuration to fetch deps if we want to enable missingInclude + options.append("--enable=warning,portability,information") + options.append("--error-exitcode=1") + options.append("--inline-suppr") + + sources = ["src"] + + run([command, *options, *sources]) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.set_defaults(func=lambda _: parser.print_help()) + + subparsers = parser.add_subparsers() + + parser_check = subparsers.add_parser( + 'check', + description="Check code with cpplint or cppcheck", + help="Check code with cpplint or cppcheck") + parser_check.set_defaults(func=lambda _: parser_check.print_help()) + parser_check_subparsers = parser_check.add_subparsers() + parser_check_cpplint = parser_check_subparsers.add_parser( + 'cpplint', + description="Lint code with cpplint (https://github.com/cpplint/cpplint)", + help="Lint code with cpplint (https://github.com/cpplint/cpplint)") + parser_check_cpplint.set_defaults(func=cpplint) + parser_check_cppcheck = parser_check_subparsers.add_parser( + 'cppcheck', + description="Check code with cppcheck (https://github.com/danmar/cppcheck)", + help="Check code with cppcheck (https://github.com/danmar/cppcheck)", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser_check_cppcheck.set_defaults(func=cppcheck) + + parser_build = subparsers.add_parser( + 'build', + description="Build executables to BUILD_DIR [default: build]", + help="Build executables to BUILD_DIR [default: build]", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser_build.add_argument('dir', metavar='BUILD_DIR', nargs='?', default='build', help="directory to store cmake-generated and build files") + parser_build.add_argument('-j', '--jobs', default=4, metavar='N', help='execute N build jobs concurrently') + parser_build.add_argument('--ghproxy', default=False, action='store_true', help='use https://ghproxy.com to fetch dependencies') + parser_build.add_argument('--ninja', default=False, action='store_true', help='use Ninja to build kvrocks') + 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('-D', nargs='*', metavar='key=value', help='extra CMake definitions') + parser_build.set_defaults(func=build) + + args = parser.parse_args() + args.func(args)