/
githubmirror
/
nvme-cli
Обзор
Документация
Войти
/
githubmirror
/
nvme-cli
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
scripts/build.sh
615 строк
18 KB
Daniel Wagner
tests/e2e: make test configuration flexible
10 авг 2026, 17:30
10 авг 2026, 17:30
10c5590
Код
Авторство
О чём код?
#!/bin/bash # SPDX-License-Identifier: GPL-2.0-or-later # # This file is part of nvme. # Copyright (c) 2026 SUSE LLC # # Authors: Daniel Wagner <dwagner@suse.de> set -e usage() { echo "Usage: build.sh [-b [release|debug]] " echo " [-c [gcc|clang]]" echo " [-m [meson|muon]" echo " [--e2e-controller /dev/nvme0]" echo " [--e2e-ns1 /dev/nvme0n1]" echo " [--e2e-log-dir dir]" echo " [--e2e-log-level level]" echo " [--e2e-nvme-bin path]" echo " [--plugin-tests plugin1,plugin2]" echo " [config]" echo "" echo "CI build script." echo "" echo " -a run static analysis with clang analyzer" echo " -b [release]|debug build type" echo " -c [gcc]|clang compiler to use" echo " -m [meson]|muon use meson or muon" echo " -p enable coverage report" echo " -s run tests with ASan+UBSan (asanubsan setup)" echo " -t [arm]|ppc64le|s390x cross compile target" echo " -x run tests with valgrind (valgrind setup)" echo "" echo "options for the 'tests' config (mirror the e2e-* meson options):" echo " --e2e-controller dev controller device for e2e tests, e.g. /dev/nvme0" echo " (required when running the 'tests' config)" echo " --e2e-ns1 dev namespace device for e2e tests, e.g. /dev/nvme0n1" echo " (required when running the 'tests' config)" echo " --e2e-log-dir dir log directory for e2e tests" echo " --e2e-log-level level log verbosity for e2e tests" echo " --e2e-nvme-bin path nvme binary to exercise in e2e tests" echo " --plugin-tests list comma-separated list of plugin test suites to" echo " run against real hardware, e.g. micron,ocp" echo "" echo "configs with meson:" echo " [default] default settings" echo " libdbus build with libdbus" echo " liburing build with liburing" echo " fallback download all dependencies" echo " and build them as shared libraries" echo " cross use cross toolchain to build" echo " distro build libnvme and nvme-cli separately" echo " docs build all documentation" echo " man_docs build man documentation only" echo " html_docs build html documentation only" echo " rst_docs build rst documentation only" echo " static build a static binary" echo " minimal_static build a static binary without fabrics support" echo " nofabrics build without fabrics support, run unit tests" echo " libnvme build only libnvme" echo " tests build for nightly build" echo "" echo "configs with muon:" echo " [default] minimal static build" } BUILDTOOL=meson MESON=meson BUILDTYPE=release CROSS_TARGET=arm CC=${CC:-"gcc"} SCAN_BUILD="" use_coverage=0 use_valgrind=0 use_asan=0 use_analyzer=0 E2E_CONTROLLER="" E2E_NS1="" E2E_LOG_DIR="" E2E_LOG_LEVEL="" E2E_NVME_BIN="" PLUGIN_TESTS="" ARGS=() while [[ $# -gt 0 ]]; do case "$1" in -a) if ! command -v clang > /dev/null 2>&1; then echo "Error: clang is not found; please install clang." exit 1 fi if ! command -v scan-build >/dev/null 2>&1; then echo "Error: scan-build is not found; please install clang-analyzer." exit 1 fi use_analyzer=1 CC=clang SCAN_BUILD=scan-build shift ;; -b) BUILDTYPE="$2" shift 2 ;; -c) CC="$2" shift 2 ;; -m) BUILDTOOL="$2" shift 2 ;; -p) use_coverage=1 shift ;; -s) use_asan=1 shift ;; -t) CROSS_TARGET="$2" shift 2 ;; -x) use_valgrind=1 shift ;; --e2e-controller) E2E_CONTROLLER="$2" shift 2 ;; --e2e-ns1) E2E_NS1="$2" shift 2 ;; --e2e-log-dir) E2E_LOG_DIR="$2" shift 2 ;; --e2e-log-level) E2E_LOG_LEVEL="$2" shift 2 ;; --e2e-nvme-bin) E2E_NVME_BIN="$2" shift 2 ;; --plugin-tests) PLUGIN_TESTS="$2" shift 2 ;; -h|--help) usage exit 0 ;; -*) usage exit 1 ;; *) ARGS+=("$1") shift ;; esac done set -- "${ARGS[@]}" CONFIG=${1:-"default"} if [[ "${CONFIG}" != "tests" ]]; then if [[ -n "${E2E_CONTROLLER}" || -n "${E2E_NS1}" || -n "${E2E_LOG_DIR}" || \ -n "${E2E_LOG_LEVEL}" || -n "${E2E_NVME_BIN}" || -n "${PLUGIN_TESTS}" ]]; then echo "error: --e2e-* and --plugin-tests are only valid with the 'tests' config" >&2 exit 1 fi fi cd "$(git rev-parse --show-toplevel)" || exit 1 BUILDDIR="$(pwd)/.build-ci" TOOLDIR="$(pwd)/.build-tools" fn_exists() { declare -F "$1" > /dev/null; } config_meson_default() { local extra_args=() if [ "${use_asan:-0}" -eq 1 ]; then extra_args+=(-Db_sanitize=address,undefined) fi CC="${CC}" ${SCAN_BUILD} "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ "${extra_args[@]}" \ "${BUILDDIR}" } config_meson_musl() { local cflags=( -U_GNU_SOURCE -idirafter /usr/include -idirafter /usr/include/x86_64-linux-gnu ) local cflags_str="${cflags[*]}" CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ -Dc_args="${cflags_str}" \ -Ddefault_library=static \ -Djson-c=disabled \ -Dopenssl=disabled \ -Dkeyutils=disabled \ -Dpython=disabled \ "${BUILDDIR}" } config_meson_libdbus() { CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ -Ddeprecated-cmds=enabled \ -Dlibdbus=enabled \ --prefix="${BUILDDIR}/usr" \ "${BUILDDIR}" } config_meson_liburing() { CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ -Dliburing=enabled \ --prefix="${BUILDDIR}/usr" \ "${BUILDDIR}" } config_meson_fallback() { CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ --wrap-mode=forcefallback \ --default-library=both \ -Dlibdbus=enabled \ -Ddbus:werror=false \ -Dopenssl:werror=false \ "${BUILDDIR}" } config_meson_cross() { CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ --cross-file=.github/cross/ubuntu-cross-${CROSS_TARGET}.txt \ -Dpython=disabled \ -Dopenssl=disabled \ "${BUILDDIR}" } config_meson_docs() { CC="${CC}" "${MESON}" setup \ -Ddocs=all \ -Ddocs-build=true \ -Ddeprecated-cmds=enabled \ --prefix=/tmp/usr \ "${BUILDDIR}" } config_meson_man_docs() { CC="${CC}" "${MESON}" setup \ -Ddocs=man \ -Ddocs-build=true \ -Ddeprecated-cmds=enabled \ --prefix=/tmp/usr \ "${BUILDDIR}" } config_meson_html_docs() { CC="${CC}" "${MESON}" setup \ -Ddocs=html \ -Ddocs-build=true \ -Ddeprecated-cmds=enabled \ --prefix=/tmp/usr \ "${BUILDDIR}" } config_meson_rst_docs() { CC="${CC}" "${MESON}" setup \ -Ddocs=rst \ -Ddocs-build=true \ -Ddeprecated-cmds=enabled \ --prefix=/tmp/usr \ "${BUILDDIR}" } config_meson_static() { CC="${CC}" "${MESON}" setup \ --werror \ --buildtype=release \ --default-library=static \ --wrap-mode=forcefallback \ --prefix=/usr \ -Dc_link_args="-static" \ -Dkeyutils=disabled \ -Dliburing=disabled \ -Dpython=disabled \ -Dopenssl=disabled \ -Dtests=false \ -Dexamples=false \ "${BUILDDIR}" } config_meson_minimal_static() { local cflags=( -U_GNU_SOURCE -idirafter /usr/include -idirafter /usr/include/x86_64-linux-gnu -Oz -flto -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-protector ) local ldflags=( -flto -Wl,--gc-sections -s -Wl,--build-id=none -static ) local cflags_str="${cflags[*]}" local ldflags_str="${ldflags[*]}" CC=musl-gcc CC="${CC}" "${MESON}" setup \ --werror \ --buildtype=release \ --default-library=static \ --prefix=/usr \ -Dplugins="sed,lm,feat,zns,fdp" \ -Dc_args="${cflags_str}" \ -Dc_link_args="${ldflags_str}" \ -Dfabrics=disabled \ -Dmi=disabled \ -Djson-c=disabled \ -Dopenssl=disabled \ -Dtests=false \ -Dexamples=false \ "${BUILDDIR}" } config_meson_nofabrics() { CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ -Dfabrics=disabled \ -Dmi=disabled \ -Dpython=disabled \ -Djson-c=disabled \ -Dlibkmod=disabled \ -Dopenssl=disabled \ -Dkeyutils=disabled \ "${BUILDDIR}" } config_meson_tests() { # e2e tests are destructive and refuse to guess a target device, so # --e2e-controller/--e2e-ns1 must be passed on the command line (meson # setup errors out on its own if they're left unset). The remaining # options are optional and mirror the other e2e-*/plugin-tests meson # options. local extra_args=() [ -n "${E2E_CONTROLLER}" ] && extra_args+=(-De2e-controller="${E2E_CONTROLLER}") [ -n "${E2E_NS1}" ] && extra_args+=(-De2e-ns1="${E2E_NS1}") [ -n "${E2E_LOG_DIR}" ] && extra_args+=(-De2e-log-dir="${E2E_LOG_DIR}") [ -n "${E2E_LOG_LEVEL}" ] && extra_args+=(-De2e-log-level="${E2E_LOG_LEVEL}") [ -n "${E2E_NVME_BIN}" ] && extra_args+=(-De2e-nvme-bin="${E2E_NVME_BIN}") [ -n "${PLUGIN_TESTS}" ] && extra_args+=(-Dplugin-tests="${PLUGIN_TESTS}") CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ -De2e-tests=true \ "${extra_args[@]}" \ "${BUILDDIR}" } config_meson_libnvme() { CC="${CC}" "${MESON}" setup \ --werror \ --buildtype="${BUILDTYPE}" \ -Dnvme=disabled \ -Dlibnvme=enabled \ "${BUILDDIR}" } build_meson() { if [ "${use_analyzer:-0}" -eq 1 ]; then "${SCAN_BUILD}" -o "${BUILDDIR}/scan-results" \ -analyze-headers \ --force-analyze-debug-code \ --status-bugs \ "${MESON}" compile -C "${BUILDDIR}" else "${MESON}" compile \ -C "${BUILDDIR}" fi } build_meson_docs() { "${MESON}" compile \ -C "${BUILDDIR}" \ docs } build_meson_man_docs() { "${MESON}" compile \ -C "${BUILDDIR}" \ docs } build_meson_html_docs() { "${MESON}" compile \ -C "${BUILDDIR}" \ docs } build_meson_rst_docs() { "${MESON}" compile \ -C "${BUILDDIR}" \ docs } test_meson() { local args=(-C "${BUILDDIR}") if [ "${use_valgrind:-0}" -eq 1 ]; then if command -v valgrind >/dev/null 2>&1; then args+=(--setup valgrind) else echo "Warning: valgrind requested but not found; running without it." >&2 fi elif [ "${use_asan:-0}" -eq 1 ]; then args+=(--setup asanubsan) fi "${MESON}" test "${args[@]}" } test_meson_docs() { true } test_meson_man_docs() { true } test_meson_html_docs() { true } test_meson_rst_docs() { true } install_meson_docs() { "${MESON}" install \ -C "${BUILDDIR}" } tools_build_samurai() { if [ ! -d "${TOOLDIR}"/samurai ]; then git clone --depth 1 https://github.com/michaelforney/samurai.git \ "${TOOLDIR}/samurai" fi if [[ -f "${TOOLDIR}/samurai/samu" ]]; then return fi pushd "${TOOLDIR}/samurai" || exit 1 CC="${CC}" make popd || exit 1 } tools_build_muon() { if [ ! -d "${TOOLDIR}/muon" ]; then git clone --depth 1 https://git.sr.ht/~lattis/muon \ "${TOOLDIR}/muon" fi if [[ -f "${TOOLDIR}/build-muon/muon" ]]; then return fi pushd "${TOOLDIR}/muon" || exit 1 CC="${CC}" CFLAGS="${CFLAGS} -std=c99" ninja="${SAMU}" ./bootstrap.sh stage1 CC="${CC}" ninja="${SAMU}" stage1/muon-bootstrap setup \ -Dprefix="${TOOLDIR}" \ -Dsamurai=disabled \ "${TOOLDIR}/build-muon" "${SAMU}" -C "${TOOLDIR}/build-muon" MUON="${BUILDDIR}/build-tools/.build-muon/muon" # "${TOOLDIR}/build-muon/muon" \ # -C "${TOOLDIR}/build-muon" test popd || exit 1 } config_muon_default() { # wrap_mode=forcefallback depends on git being available CC="${CC}" CFLAGS="${CFLAGS}" ninja="${SAMU}" \ "${MUON}" setup \ -Ddefault_library=static \ -Dc_link_args="-static" \ -Dwrap_mode=forcefallback \ -Djson-c=disabled \ -Dpython=disabled \ -Dopenssl=disabled \ -Dkeyutils=disabled \ -Djson-c=disabled \ "${BUILDDIR}" } build_muon() { "${SAMU}" -C "${BUILDDIR}" } test_muon() { ninja="${SAMU}" "${MUON}" -C "${BUILDDIR}" test ldd "${BUILDDIR}/nvme" 2>&1 | grep 'not a dynamic executable' || exit 1 } _install_libnvme() { local LBUILDDIR="${BUILDDIR}/.build-libnvme" CC="${CC}" "${MESON}" setup \ --prefix="${BUILDDIR}/usr" \ --buildtype="${BUILDTYPE}" \ -Dnvme=disabled \ "${LBUILDDIR}" "${MESON}" compile \ -C "${LBUILDDIR}" "${MESON}" install \ -C "${LBUILDDIR}" } config_meson_distro() { _install_libnvme PKG_CONFIG_PATH="${BUILDDIR}/usr/lib64/pkgconfig" \ CC="${CC}" ${MESON} setup \ --prefix="${BUILDDIR}/usr" \ --werror \ --buildtype="${BUILDTYPE}" \ --force-fallback-for= \ -Dlibnvme=disabled \ "${BUILDDIR}" } build_meson_distro() { build_meson } test_meson_distro() { test_meson } if [[ "${use_coverage}" -eq 1 && "${BUILDTOOL}" != "meson" ]]; then echo "error: coverage reporting (-p) is only supported with the meson build tool" >&2 exit 1 fi if [[ "${BUILDTOOL}" == "muon" ]]; then SAMU="$(which samu 2> /dev/null)" || true if [[ -z "${SAMU}" ]]; then tools_build_samurai SAMU="${TOOLDIR}/samurai/samu" fi MUON="$(which muon 2> /dev/null)" || true if [[ -z "${MUON}" ]]; then tools_build_muon MUON="${TOOLDIR}/build-muon/muon" fi fi echo "samu: ${SAMU}" echo "muon: ${MUON}" rm -rf "${BUILDDIR}" config_"${BUILDTOOL}"_"${CONFIG}" if [[ "${use_coverage}" -eq 1 ]]; then "${MESON}" setup --reconfigure "${BUILDDIR}" -Db_coverage=true fi fn_exists "build_${BUILDTOOL}_${CONFIG}" && "build_${BUILDTOOL}_${CONFIG}" || build_"${BUILDTOOL}" fn_exists "test_${BUILDTOOL}_${CONFIG}" && "test_${BUILDTOOL}_${CONFIG}" || test_"${BUILDTOOL}" if [[ "${use_coverage}" -eq 1 ]]; then gcovr -r . "${BUILDDIR}" --xml-pretty -o coverage.xml fi fn_exists "install_${BUILDTOOL}_${CONFIG}" && "install_${BUILDTOOL}_${CONFIG}" || true;