From e39e2843be3b6956bf21c1295502a7abf673f60d Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Thu, 2 Jul 2026 19:15:28 +0800 Subject: [PATCH 1/7] test: cover toolchain wrapper failure propagation --- .../tests/test_wrapper_failure_propagation.sh | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 toolchain/tests/test_wrapper_failure_propagation.sh diff --git a/toolchain/tests/test_wrapper_failure_propagation.sh b/toolchain/tests/test_wrapper_failure_propagation.sh new file mode 100755 index 0000000000..5e33ebb243 --- /dev/null +++ b/toolchain/tests/test_wrapper_failure_propagation.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +set -u + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" +TOOLCHAIN_DIR="${REPO_ROOT}/toolchain" +FAILURES=0 + +fail() { + printf 'FAIL: %s\n' "$*" >&2 + FAILURES=$((FAILURES + 1)) +} + +assert_file_contains() { + local file="$1" + local text="$2" + if ! grep -Fq "$text" "$file"; then + fail "${file} does not contain expected text: ${text}" + fi +} + +test_runner_preserves_command_failure() { + # shellcheck source=/dev/null + source "${TOOLCHAIN_DIR}/scripts/lib/wrapper_runner.sh" + + local tmpdir log status + tmpdir="$(mktemp -d)" + log="${tmpdir}/compile.log" + + run_toolchain_with_log "$log" bash -c 'printf "installer stdout\n"; exit 37' + status=$? + + if [[ "$status" -ne 37 ]]; then + fail "run_toolchain_with_log returned ${status}; expected 37" + fi + assert_file_contains "$log" "installer stdout" + + rm -rf "$tmpdir" +} + +test_wrappers_use_runner() { + local wrappers=( + "${TOOLCHAIN_DIR}/toolchain_gnu.sh" + "${TOOLCHAIN_DIR}/toolchain_intel.sh" + "${TOOLCHAIN_DIR}/toolchain_gcc-mkl.sh" + "${TOOLCHAIN_DIR}/toolchain_gcc-aocl.sh" + "${TOOLCHAIN_DIR}/toolchain_aocc-aocl.sh" + ) + + local wrapper + for wrapper in "${wrappers[@]}"; do + assert_file_contains "$wrapper" 'source "${SCRIPT_DIR}/scripts/lib/wrapper_runner.sh"' + assert_file_contains "$wrapper" 'run_toolchain_with_log compile.log ./install_abacus_toolchain_new.sh' + + if grep -Eq '\|\s*tee[[:space:]]+compile\.log' "$wrapper"; then + fail "${wrapper} still contains a raw pipe to tee compile.log" + fi + + if grep -Eq '^exec[[:space:]]+\./install_abacus_toolchain_new\.sh' "$wrapper"; then + fail "${wrapper} still execs the installer directly" + fi + done +} + +test_runner_preserves_command_failure +test_wrappers_use_runner + +if [[ "$FAILURES" -ne 0 ]]; then + printf '%s wrapper failure propagation test(s) failed\n' "$FAILURES" >&2 + exit 1 +fi + +printf 'wrapper failure propagation tests passed\n' From 934515fd646e5e5a8020239d72a8ae0548f39d04 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Thu, 2 Jul 2026 19:37:20 +0800 Subject: [PATCH 2/7] fix: preserve toolchain wrapper installer failures --- toolchain/scripts/lib/wrapper_runner.sh | 11 +++++++++++ toolchain/toolchain_aocc-aocl.sh | 8 +++++--- toolchain/toolchain_gcc-aocl.sh | 8 +++++--- toolchain/toolchain_gcc-mkl.sh | 8 +++++--- toolchain/toolchain_gnu.sh | 9 ++++++--- toolchain/toolchain_intel.sh | 8 +++++--- 6 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 toolchain/scripts/lib/wrapper_runner.sh diff --git a/toolchain/scripts/lib/wrapper_runner.sh b/toolchain/scripts/lib/wrapper_runner.sh new file mode 100644 index 0000000000..81adb56c1a --- /dev/null +++ b/toolchain/scripts/lib/wrapper_runner.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +run_toolchain_with_log() { + local log_file="$1" + shift + + "$@" | tee "$log_file" + local installer_status=${PIPESTATUS[0]} + + return "$installer_status" +} diff --git a/toolchain/toolchain_aocc-aocl.sh b/toolchain/toolchain_aocc-aocl.sh index bfc4b4bc1a..83ad0a1c84 100755 --- a/toolchain/toolchain_aocc-aocl.sh +++ b/toolchain/toolchain_aocc-aocl.sh @@ -5,6 +5,9 @@ #SBATCH -o compile.log #SBATCH -e compile.err +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +source "${SCRIPT_DIR}/scripts/lib/wrapper_runner.sh" + # Users can easily modify these parameters to customize the build # Before running this script, ensure you have loaded your system packages @@ -84,7 +87,7 @@ LIBTORCH_VERSION="main" # main=2.1.2, alt=1.12.1 (use alt for older GLIBC) # ============================================================================ # Call the main installation script with configured parameters -exec ./install_abacus_toolchain_new.sh \ +run_toolchain_with_log compile.log ./install_abacus_toolchain_new.sh \ --with-amd="$WITH_AMD" \ --with-gcc="$WITH_GCC" \ --math-mode="$MATH_MODE" \ @@ -115,5 +118,4 @@ exec ./install_abacus_toolchain_new.sh \ ${PACK_RUN_MODE:+$([ "$PACK_RUN_MODE" = "yes" ] && echo "--pack-run")} \ ${ENABLE_CUDA:+--enable-cuda} \ ${GPU_VERSION:+--gpu-ver="$GPU_VERSION"} \ - "$@" \ - | tee compile.log + "$@" diff --git a/toolchain/toolchain_gcc-aocl.sh b/toolchain/toolchain_gcc-aocl.sh index f77b533989..1238defd36 100755 --- a/toolchain/toolchain_gcc-aocl.sh +++ b/toolchain/toolchain_gcc-aocl.sh @@ -5,6 +5,9 @@ #SBATCH -o compile.log #SBATCH -e compile.err +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +source "${SCRIPT_DIR}/scripts/lib/wrapper_runner.sh" + # Users can easily modify these parameters to customize the build # Before running this script, ensure you have loaded your system packages @@ -81,7 +84,7 @@ LIBTORCH_VERSION="main" # main=2.1.2, alt=1.12.1 (use alt for older GLIBC) # ============================================================================ # Call the main installation script with configured parameters -exec ./install_abacus_toolchain_new.sh \ +run_toolchain_with_log compile.log ./install_abacus_toolchain_new.sh \ --with-gcc="$WITH_GCC" \ --with-amd="$WITH_AMD" \ --math-mode="$MATH_MODE" \ @@ -111,5 +114,4 @@ exec ./install_abacus_toolchain_new.sh \ ${PACK_RUN_MODE:+$([ "$PACK_RUN_MODE" = "yes" ] && echo "--pack-run")} \ ${ENABLE_CUDA:+--enable-cuda} \ ${GPU_VERSION:+--gpu-ver="$GPU_VERSION"} \ - "$@" \ - | tee compile.log + "$@" diff --git a/toolchain/toolchain_gcc-mkl.sh b/toolchain/toolchain_gcc-mkl.sh index bac479c38f..df0fc04d10 100755 --- a/toolchain/toolchain_gcc-mkl.sh +++ b/toolchain/toolchain_gcc-mkl.sh @@ -5,6 +5,9 @@ #SBATCH -o compile.log #SBATCH -e compile.err +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +source "${SCRIPT_DIR}/scripts/lib/wrapper_runner.sh" + # Users can easily modify these parameters to customize the build # Before running this script, ensure you have loaded your system packages @@ -84,7 +87,7 @@ LIBTORCH_VERSION="main" # main=2.1.2, alt=1.12.1 (use alt for older GLIBC) # ============================================================================ # Call the main installation script with configured parameters -exec ./install_abacus_toolchain_new.sh \ +run_toolchain_with_log compile.log ./install_abacus_toolchain_new.sh \ --with-gcc="$WITH_GCC" \ --math-mode="$MATH_MODE" \ --mpi-mode="$MPI_MODE" \ @@ -114,5 +117,4 @@ exec ./install_abacus_toolchain_new.sh \ ${PACK_RUN_MODE:+$([ "$PACK_RUN_MODE" = "yes" ] && echo "--pack-run")} \ ${ENABLE_CUDA:+--enable-cuda} \ ${GPU_VERSION:+--gpu-ver="$GPU_VERSION"} \ - "$@" \ - | tee compile.log + "$@" diff --git a/toolchain/toolchain_gnu.sh b/toolchain/toolchain_gnu.sh index a934fed018..e297c0e453 100755 --- a/toolchain/toolchain_gnu.sh +++ b/toolchain/toolchain_gnu.sh @@ -4,6 +4,10 @@ #SBATCH -n 16 #SBATCH -o compile.log #SBATCH -e compile.err + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +source "${SCRIPT_DIR}/scripts/lib/wrapper_runner.sh" + # Users can easily modify these parameters to customize the build # Before running this script, ensure you have loaded your system packages @@ -84,7 +88,7 @@ LIBTORCH_VERSION="main" # main=2.1.2, alt=1.12.1 (use alt for older GLIBC) # ============================================================================ # Call the main installation script with configured parameters -exec ./install_abacus_toolchain_new.sh \ +run_toolchain_with_log compile.log ./install_abacus_toolchain_new.sh \ --with-gcc="$WITH_GCC" \ --with-intel="$WITH_INTEL" \ --with-amd="$WITH_AMD" \ @@ -119,5 +123,4 @@ exec ./install_abacus_toolchain_new.sh \ ${PACK_RUN_MODE:+$([ "$PACK_RUN_MODE" = "yes" ] && echo "--pack-run")} \ ${ENABLE_CUDA:+--enable-cuda} \ ${GPU_VERSION:+--gpu-ver="$GPU_VERSION"} \ - "$@" \ - | tee compile.log + "$@" diff --git a/toolchain/toolchain_intel.sh b/toolchain/toolchain_intel.sh index ab40cf55b2..9f854a0b4a 100755 --- a/toolchain/toolchain_intel.sh +++ b/toolchain/toolchain_intel.sh @@ -5,6 +5,9 @@ #SBATCH -o compile.log #SBATCH -e compile.err +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +source "${SCRIPT_DIR}/scripts/lib/wrapper_runner.sh" + # Users can easily modify these parameters to customize the build # Before running this script, ensure you have loaded your system packages @@ -103,7 +106,7 @@ LIBTORCH_VERSION="main" # main=2.1.2, alt=1.12.1 (use alt for older GLIBC) # ============================================================================ # Call the main installation script with configured parameters -exec ./install_abacus_toolchain_new.sh \ +run_toolchain_with_log compile.log ./install_abacus_toolchain_new.sh \ --with-intel="$WITH_INTEL" \ --with-gcc="$WITH_GCC" \ --math-mode="$MATH_MODE" \ @@ -136,5 +139,4 @@ exec ./install_abacus_toolchain_new.sh \ ${PACK_RUN_MODE:+$([ "$PACK_RUN_MODE" = "yes" ] && echo "--pack-run")} \ ${ENABLE_CUDA:+--enable-cuda} \ ${GPU_VERSION:+--gpu-ver="$GPU_VERSION"} \ - "$@" \ - | tee compile.log + "$@" From b65c3180e5f00fa35046e87d593da904e1e90f89 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Thu, 2 Jul 2026 19:59:39 +0800 Subject: [PATCH 3/7] test: cover toolchain argument failure exits --- .../tests/test_installer_argument_failures.sh | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100755 toolchain/tests/test_installer_argument_failures.sh diff --git a/toolchain/tests/test_installer_argument_failures.sh b/toolchain/tests/test_installer_argument_failures.sh new file mode 100755 index 0000000000..2ffd89e016 --- /dev/null +++ b/toolchain/tests/test_installer_argument_failures.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +set -u + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" +TOOLCHAIN_DIR="${REPO_ROOT}/toolchain" +FAILURES=0 + +fail() { + printf 'FAIL: %s\n' "$*" >&2 + FAILURES=$((FAILURES + 1)) +} + +copy_toolchain() { + local tmpdir="$1" + local entry name + mkdir -p "${tmpdir}/toolchain" + while IFS= read -r -d '' entry; do + name="${entry##*/}" + case "$name" in + build|install) continue ;; + esac + cp -a "$entry" "${tmpdir}/toolchain/" + done < <(find "${TOOLCHAIN_DIR}" -mindepth 1 -maxdepth 1 -print0) +} + +run_installer_in_copy() { + local tmpdir="$1" + shift + (cd "${tmpdir}/toolchain" && ./install_abacus_toolchain_new.sh "$@") >"${tmpdir}/output.log" 2>&1 +} + +assert_invalid_input_fails() { + local name="$1" + local expected_text="$2" + shift 2 + + local tmpdir status + tmpdir="$(mktemp -d)" + copy_toolchain "$tmpdir" + + run_installer_in_copy "$tmpdir" "$@" + status=$? + + if [[ "$status" -eq 0 ]]; then + cat "${tmpdir}/output.log" >&2 + fail "${name} exited 0; expected nonzero" + fi + + if ! grep -Fq -- "$expected_text" "${tmpdir}/output.log"; then + cat "${tmpdir}/output.log" >&2 + fail "${name} did not report expected error: ${expected_text}" + fi + + if [[ -e "${tmpdir}/toolchain/install/setup" ]]; then + fail "${name} wrote install/setup even though argument parsing failed" + fi + + rm -rf "$tmpdir" +} + +assert_valid_help_succeeds() { + local tmpdir status + tmpdir="$(mktemp -d)" + copy_toolchain "$tmpdir" + + run_installer_in_copy "$tmpdir" --help + status=$? + + if [[ "$status" -ne 0 ]]; then + cat "${tmpdir}/output.log" >&2 + fail "--help exited ${status}; expected 0" + fi + + if ! grep -Fq "install_abacus_toolchain_new.sh [OPTIONS]" "${tmpdir}/output.log"; then + cat "${tmpdir}/output.log" >&2 + fail "--help output did not contain usage text" + fi + + rm -rf "$tmpdir" +} + +assert_invalid_input_fails "invalid package version" "Invalid package version format" --dry-run --package-version bad:wrong +assert_invalid_input_fails "missing package version value" "--package-version requires at least one package:version argument" --dry-run --package-version +assert_invalid_input_fails "invalid mpi mode" "Invalid MPI mode: invalid" --dry-run --mpi-mode invalid +assert_valid_help_succeeds + +if [[ "$FAILURES" -ne 0 ]]; then + printf '%s installer argument failure test(s) failed\n' "$FAILURES" >&2 + exit 1 +fi + +printf 'installer argument failure tests passed\n' From 53d1f77ea0728a43ea5229252b1680172ab22bc1 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Thu, 2 Jul 2026 20:49:15 +0800 Subject: [PATCH 4/7] fix: propagate toolchain argument parsing failures --- toolchain/install_abacus_toolchain_new.sh | 2 +- toolchain/scripts/lib/config_manager.sh | 42 ++++++++++++------- .../tests/test_installer_argument_failures.sh | 36 ++++++++++++++++ 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/toolchain/install_abacus_toolchain_new.sh b/toolchain/install_abacus_toolchain_new.sh index 0f0d85d42e..cbcd438558 100755 --- a/toolchain/install_abacus_toolchain_new.sh +++ b/toolchain/install_abacus_toolchain_new.sh @@ -50,7 +50,7 @@ main() { # Initialize configuration with command line arguments if ! config_init "${args[@]}"; then show_help - exit 0 + exit 1 fi # Handle special version-related requests diff --git a/toolchain/scripts/lib/config_manager.sh b/toolchain/scripts/lib/config_manager.sh index fc7ca30683..249e651556 100644 --- a/toolchain/scripts/lib/config_manager.sh +++ b/toolchain/scripts/lib/config_manager.sh @@ -456,13 +456,13 @@ config_validate() { if [[ -n "${CONFIG_CACHE[NPROCS_OVERWRITE]}" ]]; then if ! [[ "${CONFIG_CACHE[NPROCS_OVERWRITE]}" =~ ^[0-9]+$ ]]; then report_error ${LINENO} "Invalid number of processes: ${CONFIG_CACHE[NPROCS_OVERWRITE]}" - exit 1 + return 1 fi fi if ! [[ "${CONFIG_CACHE[LOG_LINES]}" =~ ^[0-9]+$ ]]; then report_error ${LINENO} "Invalid log lines value: ${CONFIG_CACHE[LOG_LINES]}" - exit 1 + return 1 fi # Validate GPU version - support only numeric formats @@ -476,7 +476,7 @@ config_validate() { CONFIG_CACHE["ARCH_NUM"]="$arch_num" else report_error ${LINENO} "Invalid GPU version: $gpu_ver. Supported formats: numeric with decimal (6.0, 7.0, 8.0, 8.9, etc.) or numeric without decimal (60, 70, 80, 89, etc.)" - exit 1 + return 1 fi else CONFIG_CACHE["ARCH_NUM"]="no" @@ -1166,27 +1166,37 @@ config_parse_arguments() { config_init() { # Set defaults first config_set_defaults - + # Initialize version helper to ensure VERSION_STRATEGY defaults are set if command -v version_helper_init > /dev/null 2>&1; then version_helper_init fi - + # Load configuration from file (if available) - this will override defaults - config_load_from_file - + if ! config_load_from_file; then + return 1 + fi + # Apply mode-based configurations from file - this will override defaults - config_apply_modes_from_file - + if ! config_apply_modes_from_file; then + return 1 + fi + # Parse command line arguments - this will override file settings - config_parse_arguments "$@" - + if ! config_parse_arguments "$@"; then + return 1 + fi + # Apply mode-based configurations from command line - config_apply_modes - + if ! config_apply_modes; then + return 1 + fi + # Validate configuration - config_validate - + if ! config_validate; then + return 1 + fi + return 0 } @@ -1262,4 +1272,6 @@ config_apply_modes() { ;; esac fi + + return 0 } diff --git a/toolchain/tests/test_installer_argument_failures.sh b/toolchain/tests/test_installer_argument_failures.sh index 2ffd89e016..48c153dad8 100755 --- a/toolchain/tests/test_installer_argument_failures.sh +++ b/toolchain/tests/test_installer_argument_failures.sh @@ -51,6 +51,11 @@ assert_invalid_input_fails() { fail "${name} did not report expected error: ${expected_text}" fi + if ! grep -Fq "install_abacus_toolchain_new.sh [OPTIONS]" "${tmpdir}/output.log"; then + cat "${tmpdir}/output.log" >&2 + fail "${name} output did not contain usage text" + fi + if [[ -e "${tmpdir}/toolchain/install/setup" ]]; then fail "${name} wrote install/setup even though argument parsing failed" fi @@ -58,6 +63,35 @@ assert_invalid_input_fails() { rm -rf "$tmpdir" } +assert_valid_dry_run_succeeds() { + local name="$1" + shift + + local tmpdir status + tmpdir="$(mktemp -d)" + copy_toolchain "$tmpdir" + + run_installer_in_copy "$tmpdir" "$@" + status=$? + + if [[ "$status" -ne 0 ]]; then + cat "${tmpdir}/output.log" >&2 + fail "${name} exited ${status}; expected 0" + fi + + if ! grep -Fq "Configuration files generated successfully (dry-run mode)" "${tmpdir}/output.log"; then + cat "${tmpdir}/output.log" >&2 + fail "${name} output did not contain dry-run success text" + fi + + if grep -Fq "Attempting secure download" "${tmpdir}/output.log"; then + cat "${tmpdir}/output.log" >&2 + fail "${name} attempted a package download during dry-run" + fi + + rm -rf "$tmpdir" +} + assert_valid_help_succeeds() { local tmpdir status tmpdir="$(mktemp -d)" @@ -82,6 +116,8 @@ assert_valid_help_succeeds() { assert_invalid_input_fails "invalid package version" "Invalid package version format" --dry-run --package-version bad:wrong assert_invalid_input_fails "missing package version value" "--package-version requires at least one package:version argument" --dry-run --package-version assert_invalid_input_fails "invalid mpi mode" "Invalid MPI mode: invalid" --dry-run --mpi-mode invalid +assert_invalid_input_fails "invalid gpu version" "Invalid GPU version" --dry-run --gpu-ver bad +assert_valid_dry_run_succeeds "explicit system openblas dry-run" --dry-run --with-openblas=system assert_valid_help_succeeds if [[ "$FAILURES" -ne 0 ]]; then From 077ed5be4ec04f55dffe4e3c4d08b14c3e2fbd18 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Thu, 2 Jul 2026 21:48:46 +0800 Subject: [PATCH 5/7] test: cover RapidJSON CMake package compatibility --- toolchain/tests/test_rapidjson_cmake.sh | 165 ++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100755 toolchain/tests/test_rapidjson_cmake.sh diff --git a/toolchain/tests/test_rapidjson_cmake.sh b/toolchain/tests/test_rapidjson_cmake.sh new file mode 100755 index 0000000000..0c68fa38c2 --- /dev/null +++ b/toolchain/tests/test_rapidjson_cmake.sh @@ -0,0 +1,165 @@ +#!/usr/bin/env bash +set -u + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" +FAILURES=0 + +fail() { + printf 'FAIL: %s\n' "$*" >&2 + FAILURES=$((FAILURES + 1)) +} + +write_lowercase_target_package() { + local prefix="$1" + mkdir -p "${prefix}/include/rapidjson" "${prefix}/lib/cmake/RapidJSON" + printf '#pragma once\n' >"${prefix}/include/rapidjson/document.h" + cat >"${prefix}/lib/cmake/RapidJSON/RapidJSONConfig.cmake" <<'EOF' +get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_rapidjson_prefix "${RapidJSON_CMAKE_DIR}/../../.." ABSOLUTE) +set(RapidJSON_INCLUDE_DIR "${_rapidjson_prefix}/include") +set(RapidJSON_INCLUDE_DIRS "${RapidJSON_INCLUDE_DIR}") +if(NOT TARGET rapidjson) + add_library(rapidjson INTERFACE IMPORTED) + set_property(TARGET rapidjson PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${RapidJSON_INCLUDE_DIRS}") +endif() +EOF +} + +write_variable_only_package() { + local prefix="$1" + mkdir -p "${prefix}/include/rapidjson" "${prefix}/lib/cmake/RapidJSON" + printf '#pragma once\n' >"${prefix}/include/rapidjson/document.h" + cat >"${prefix}/lib/cmake/RapidJSON/RapidJSONConfig.cmake" <<'EOF' +get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_rapidjson_prefix "${RapidJSON_CMAKE_DIR}/../../.." ABSOLUTE) +set(RapidJSON_INCLUDE_DIR "${_rapidjson_prefix}/include") +set(RapidJSON_INCLUDE_DIRS "${RapidJSON_INCLUDE_DIR}") +EOF +} + +write_target_test_project() { + local project_dir="$1" + mkdir -p "$project_dir" + cat >"${project_dir}/CMakeLists.txt" <<'EOF' +cmake_minimum_required(VERSION 3.16) +project(check_rapidjson_target LANGUAGES CXX) + +function(abacus_add_feature_definitions) + set_property(GLOBAL APPEND PROPERTY ABACUS_FEATURE_DEFINITIONS ${ARGN}) +endfunction() + +include("${ABACUS_SOURCE_DIR}/cmake/AbacusRapidJSON.cmake") + +add_library(deps INTERFACE) +abacus_configure_rapidjson(deps) + +get_target_property(_links deps INTERFACE_LINK_LIBRARIES) +if(NOT _links MATCHES "(^|;)rapidjson($|;)") + message(FATAL_ERROR "Expected deps to link to rapidjson target, got '${_links}'") +endif() + +get_property(_defs GLOBAL PROPERTY ABACUS_FEATURE_DEFINITIONS) +if(NOT "__RAPIDJSON" IN_LIST _defs) + message(FATAL_ERROR "Expected __RAPIDJSON feature definition") +endif() +EOF +} + +write_variable_test_project() { + local project_dir="$1" + mkdir -p "$project_dir" + cat >"${project_dir}/CMakeLists.txt" <<'EOF' +cmake_minimum_required(VERSION 3.16) +project(check_rapidjson_variables LANGUAGES CXX) + +function(abacus_add_feature_definitions) + set_property(GLOBAL APPEND PROPERTY ABACUS_FEATURE_DEFINITIONS ${ARGN}) +endfunction() + +include("${ABACUS_SOURCE_DIR}/cmake/AbacusRapidJSON.cmake") + +add_library(deps INTERFACE) +abacus_configure_rapidjson(deps) + +get_target_property(_includes deps INTERFACE_INCLUDE_DIRECTORIES) +if(NOT _includes STREQUAL "${EXPECTED_RAPIDJSON_INCLUDE}") + message(FATAL_ERROR "Expected include '${EXPECTED_RAPIDJSON_INCLUDE}', got '${_includes}'") +endif() + +get_property(_defs GLOBAL PROPERTY ABACUS_FEATURE_DEFINITIONS) +if(NOT "__RAPIDJSON" IN_LIST _defs) + message(FATAL_ERROR "Expected __RAPIDJSON feature definition") +endif() +EOF +} + +run_cmake_configure() { + local source_dir="$1" + local build_dir="$2" + local prefix="$3" + local expected_include="$4" + + cmake -S "$source_dir" -B "$build_dir" \ + -DABACUS_SOURCE_DIR="${REPO_ROOT}" \ + -DCMAKE_PREFIX_PATH="$prefix" \ + -DEXPECTED_RAPIDJSON_INCLUDE="$expected_include" \ + >"${build_dir}.log" 2>&1 +} + +test_lowercase_target_package() { + local tmpdir prefix source_dir build_dir status + tmpdir="$(mktemp -d)" + prefix="${tmpdir}/prefix" + source_dir="${tmpdir}/target-project" + build_dir="${tmpdir}/target-build" + + write_lowercase_target_package "$prefix" + write_target_test_project "$source_dir" + run_cmake_configure "$source_dir" "$build_dir" "$prefix" "${prefix}/include" + status=$? + + if [[ "$status" -ne 0 ]]; then + cat "${build_dir}.log" >&2 + fail "lowercase RapidJSON target package did not configure" + fi + + rm -rf "$tmpdir" +} + +test_variable_only_package() { + local tmpdir prefix source_dir build_dir status + tmpdir="$(mktemp -d)" + prefix="${tmpdir}/prefix" + source_dir="${tmpdir}/variable-project" + build_dir="${tmpdir}/variable-build" + + write_variable_only_package "$prefix" + write_variable_test_project "$source_dir" + run_cmake_configure "$source_dir" "$build_dir" "$prefix" "${prefix}/include" + status=$? + + if [[ "$status" -ne 0 ]]; then + cat "${build_dir}.log" >&2 + fail "variable-only RapidJSON package did not configure" + fi + + rm -rf "$tmpdir" +} + +test_aocc_build_script_does_not_override_rapidjson_dir() { + local script="${REPO_ROOT}/toolchain/build_abacus_aocc-aocl.sh" + if grep -Fq -- '-DRapidJSON_DIR=$RAPIDJSON' "$script"; then + fail "${script} still passes RapidJSON_DIR as the package prefix" + fi +} + +test_lowercase_target_package +test_variable_only_package +test_aocc_build_script_does_not_override_rapidjson_dir + +if [[ "$FAILURES" -ne 0 ]]; then + printf '%s RapidJSON CMake test(s) failed\n' "$FAILURES" >&2 + exit 1 +fi + +printf 'RapidJSON CMake tests passed\n' From 583c5dc668a7216e70393b99f881c57a63fd7772 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Thu, 2 Jul 2026 22:16:00 +0800 Subject: [PATCH 6/7] fix: support installed RapidJSON CMake packages --- CMakeLists.txt | 5 ++--- cmake/AbacusRapidJSON.cmake | 23 +++++++++++++++++++++++ toolchain/build_abacus_aocc-aocl.sh | 2 -- 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 cmake/AbacusRapidJSON.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 23583375bb..7a0fa3f081 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,9 +160,8 @@ endfunction() # enable json support if(ENABLE_RAPIDJSON) - find_package(RapidJSON CONFIG REQUIRED) - abacus_add_feature_definitions(__RAPIDJSON) - target_link_libraries(abacus_external_deps INTERFACE RapidJSON) + include(cmake/AbacusRapidJSON.cmake) + abacus_configure_rapidjson(abacus_external_deps) endif() # get commit info diff --git a/cmake/AbacusRapidJSON.cmake b/cmake/AbacusRapidJSON.cmake new file mode 100644 index 0000000000..0c8e9c4af9 --- /dev/null +++ b/cmake/AbacusRapidJSON.cmake @@ -0,0 +1,23 @@ +function(abacus_configure_rapidjson target_name) + find_package(RapidJSON CONFIG REQUIRED) + + if(TARGET RapidJSON::RapidJSON) + target_link_libraries("${target_name}" INTERFACE RapidJSON::RapidJSON) + elseif(TARGET rapidjson) + target_link_libraries("${target_name}" INTERFACE rapidjson) + elseif(TARGET RapidJSON) + target_link_libraries("${target_name}" INTERFACE RapidJSON) + elseif(DEFINED RapidJSON_INCLUDE_DIRS AND NOT "${RapidJSON_INCLUDE_DIRS}" STREQUAL "") + target_include_directories("${target_name}" INTERFACE ${RapidJSON_INCLUDE_DIRS}) + elseif(DEFINED RapidJSON_INCLUDE_DIR AND NOT "${RapidJSON_INCLUDE_DIR}" STREQUAL "") + target_include_directories("${target_name}" INTERFACE "${RapidJSON_INCLUDE_DIR}") + else() + message( + FATAL_ERROR + "RapidJSON was found, but it did not provide a usable target or include directory. " + "Expected one of RapidJSON::RapidJSON, rapidjson, RapidJSON, RapidJSON_INCLUDE_DIRS, or RapidJSON_INCLUDE_DIR." + ) + endif() + + abacus_add_feature_definitions(__RAPIDJSON) +endfunction() diff --git a/toolchain/build_abacus_aocc-aocl.sh b/toolchain/build_abacus_aocc-aocl.sh index b32295bf11..c8a991f17d 100755 --- a/toolchain/build_abacus_aocc-aocl.sh +++ b/toolchain/build_abacus_aocc-aocl.sh @@ -24,7 +24,6 @@ rm -rf $BUILD_DIR PREFIX=$ABACUS_DIR ELPA=${ELPA_ROOT} CEREAL=${CEREAL_ROOT}/include -RAPIDJSON=${RAPIDJSON_ROOT} LAPACK=$AOCLhome/lib SCALAPACK=$AOCLhome/lib FFTW3=$AOCLhome @@ -75,7 +74,6 @@ cmake -B $BUILD_DIR -DCMAKE_INSTALL_PREFIX=$PREFIX \ -DUSE_OPENMP=ON \ -DUSE_ELPA=ON \ -DENABLE_RAPIDJSON=ON \ - -DRapidJSON_DIR=$RAPIDJSON \ -DENABLE_LIBRI=ON \ -DLIBRI_DIR=$LIBRI \ -DLIBCOMM_DIR=$LIBCOMM \ From 1a1763596b11d67ce78de1fd28a594189da7b236 Mon Sep 17 00:00:00 2001 From: QuantumMisaka Date: Fri, 3 Jul 2026 23:23:12 +0800 Subject: [PATCH 7/7] fix: require RapidJSON exported CMake target --- CMakeLists.txt | 8 +- cmake/AbacusRapidJSON.cmake | 23 ---- toolchain/tests/test_rapidjson_cmake.sh | 135 ++++++++++++++---------- 3 files changed, 87 insertions(+), 79 deletions(-) delete mode 100644 cmake/AbacusRapidJSON.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a0fa3f081..871f913a8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,8 +160,12 @@ endfunction() # enable json support if(ENABLE_RAPIDJSON) - include(cmake/AbacusRapidJSON.cmake) - abacus_configure_rapidjson(abacus_external_deps) + find_package(RapidJSON CONFIG REQUIRED) + if(NOT TARGET RapidJSON) + message(FATAL_ERROR "RapidJSON package configuration did not define the RapidJSON target") + endif() + abacus_add_feature_definitions(__RAPIDJSON) + target_link_libraries(abacus_external_deps INTERFACE RapidJSON) endif() # get commit info diff --git a/cmake/AbacusRapidJSON.cmake b/cmake/AbacusRapidJSON.cmake deleted file mode 100644 index 0c8e9c4af9..0000000000 --- a/cmake/AbacusRapidJSON.cmake +++ /dev/null @@ -1,23 +0,0 @@ -function(abacus_configure_rapidjson target_name) - find_package(RapidJSON CONFIG REQUIRED) - - if(TARGET RapidJSON::RapidJSON) - target_link_libraries("${target_name}" INTERFACE RapidJSON::RapidJSON) - elseif(TARGET rapidjson) - target_link_libraries("${target_name}" INTERFACE rapidjson) - elseif(TARGET RapidJSON) - target_link_libraries("${target_name}" INTERFACE RapidJSON) - elseif(DEFINED RapidJSON_INCLUDE_DIRS AND NOT "${RapidJSON_INCLUDE_DIRS}" STREQUAL "") - target_include_directories("${target_name}" INTERFACE ${RapidJSON_INCLUDE_DIRS}) - elseif(DEFINED RapidJSON_INCLUDE_DIR AND NOT "${RapidJSON_INCLUDE_DIR}" STREQUAL "") - target_include_directories("${target_name}" INTERFACE "${RapidJSON_INCLUDE_DIR}") - else() - message( - FATAL_ERROR - "RapidJSON was found, but it did not provide a usable target or include directory. " - "Expected one of RapidJSON::RapidJSON, rapidjson, RapidJSON, RapidJSON_INCLUDE_DIRS, or RapidJSON_INCLUDE_DIR." - ) - endif() - - abacus_add_feature_definitions(__RAPIDJSON) -endfunction() diff --git a/toolchain/tests/test_rapidjson_cmake.sh b/toolchain/tests/test_rapidjson_cmake.sh index 0c68fa38c2..bd3089d99c 100755 --- a/toolchain/tests/test_rapidjson_cmake.sh +++ b/toolchain/tests/test_rapidjson_cmake.sh @@ -9,18 +9,16 @@ fail() { FAILURES=$((FAILURES + 1)) } -write_lowercase_target_package() { +write_target_package() { local prefix="$1" mkdir -p "${prefix}/include/rapidjson" "${prefix}/lib/cmake/RapidJSON" printf '#pragma once\n' >"${prefix}/include/rapidjson/document.h" cat >"${prefix}/lib/cmake/RapidJSON/RapidJSONConfig.cmake" <<'EOF' get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) get_filename_component(_rapidjson_prefix "${RapidJSON_CMAKE_DIR}/../../.." ABSOLUTE) -set(RapidJSON_INCLUDE_DIR "${_rapidjson_prefix}/include") -set(RapidJSON_INCLUDE_DIRS "${RapidJSON_INCLUDE_DIR}") -if(NOT TARGET rapidjson) - add_library(rapidjson INTERFACE IMPORTED) - set_property(TARGET rapidjson PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${RapidJSON_INCLUDE_DIRS}") +if(NOT TARGET RapidJSON) + add_library(RapidJSON INTERFACE IMPORTED) + set_property(TARGET RapidJSON PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${_rapidjson_prefix}/include") endif() EOF } @@ -37,7 +35,7 @@ set(RapidJSON_INCLUDE_DIRS "${RapidJSON_INCLUDE_DIR}") EOF } -write_target_test_project() { +write_test_project() { local project_dir="$1" mkdir -p "$project_dir" cat >"${project_dir}/CMakeLists.txt" <<'EOF' @@ -48,42 +46,18 @@ function(abacus_add_feature_definitions) set_property(GLOBAL APPEND PROPERTY ABACUS_FEATURE_DEFINITIONS ${ARGN}) endfunction() -include("${ABACUS_SOURCE_DIR}/cmake/AbacusRapidJSON.cmake") - -add_library(deps INTERFACE) -abacus_configure_rapidjson(deps) - -get_target_property(_links deps INTERFACE_LINK_LIBRARIES) -if(NOT _links MATCHES "(^|;)rapidjson($|;)") - message(FATAL_ERROR "Expected deps to link to rapidjson target, got '${_links}'") -endif() - -get_property(_defs GLOBAL PROPERTY ABACUS_FEATURE_DEFINITIONS) -if(NOT "__RAPIDJSON" IN_LIST _defs) - message(FATAL_ERROR "Expected __RAPIDJSON feature definition") +find_package(RapidJSON CONFIG REQUIRED) +if(NOT TARGET RapidJSON) + message(FATAL_ERROR "RapidJSON package configuration did not define the RapidJSON target") endif() -EOF -} - -write_variable_test_project() { - local project_dir="$1" - mkdir -p "$project_dir" - cat >"${project_dir}/CMakeLists.txt" <<'EOF' -cmake_minimum_required(VERSION 3.16) -project(check_rapidjson_variables LANGUAGES CXX) - -function(abacus_add_feature_definitions) - set_property(GLOBAL APPEND PROPERTY ABACUS_FEATURE_DEFINITIONS ${ARGN}) -endfunction() - -include("${ABACUS_SOURCE_DIR}/cmake/AbacusRapidJSON.cmake") add_library(deps INTERFACE) -abacus_configure_rapidjson(deps) +target_link_libraries(deps INTERFACE RapidJSON) +abacus_add_feature_definitions(__RAPIDJSON) -get_target_property(_includes deps INTERFACE_INCLUDE_DIRECTORIES) -if(NOT _includes STREQUAL "${EXPECTED_RAPIDJSON_INCLUDE}") - message(FATAL_ERROR "Expected include '${EXPECTED_RAPIDJSON_INCLUDE}', got '${_includes}'") +get_target_property(_links deps INTERFACE_LINK_LIBRARIES) +if(NOT "RapidJSON" IN_LIST _links) + message(FATAL_ERROR "Expected deps to link to RapidJSON target, got '${_links}'") endif() get_property(_defs GLOBAL PROPERTY ABACUS_FEATURE_DEFINITIONS) @@ -97,36 +71,43 @@ run_cmake_configure() { local source_dir="$1" local build_dir="$2" local prefix="$3" - local expected_include="$4" cmake -S "$source_dir" -B "$build_dir" \ - -DABACUS_SOURCE_DIR="${REPO_ROOT}" \ -DCMAKE_PREFIX_PATH="$prefix" \ - -DEXPECTED_RAPIDJSON_INCLUDE="$expected_include" \ >"${build_dir}.log" 2>&1 } -test_lowercase_target_package() { +run_top_level_configure() { + local build_dir="$1" + local prefix="$2" + + cmake -S "$REPO_ROOT" -B "$build_dir" \ + -DENABLE_RAPIDJSON=ON \ + -DCMAKE_PREFIX_PATH="$prefix" \ + >"${build_dir}.log" 2>&1 +} + +test_rapidjson_target_package_configures() { local tmpdir prefix source_dir build_dir status tmpdir="$(mktemp -d)" prefix="${tmpdir}/prefix" source_dir="${tmpdir}/target-project" build_dir="${tmpdir}/target-build" - write_lowercase_target_package "$prefix" - write_target_test_project "$source_dir" - run_cmake_configure "$source_dir" "$build_dir" "$prefix" "${prefix}/include" + write_target_package "$prefix" + write_test_project "$source_dir" + run_cmake_configure "$source_dir" "$build_dir" "$prefix" status=$? if [[ "$status" -ne 0 ]]; then cat "${build_dir}.log" >&2 - fail "lowercase RapidJSON target package did not configure" + fail "RapidJSON target package did not configure" fi rm -rf "$tmpdir" } -test_variable_only_package() { +test_variable_only_package_fails() { local tmpdir prefix source_dir build_dir status tmpdir="$(mktemp -d)" prefix="${tmpdir}/prefix" @@ -134,18 +115,62 @@ test_variable_only_package() { build_dir="${tmpdir}/variable-build" write_variable_only_package "$prefix" - write_variable_test_project "$source_dir" - run_cmake_configure "$source_dir" "$build_dir" "$prefix" "${prefix}/include" + write_test_project "$source_dir" + run_cmake_configure "$source_dir" "$build_dir" "$prefix" status=$? - if [[ "$status" -ne 0 ]]; then + if [[ "$status" -eq 0 ]]; then + cat "${build_dir}.log" >&2 + fail "variable-only RapidJSON package configured; expected target-missing failure" + elif ! grep -Fq "RapidJSON package configuration did not define the RapidJSON target" "${build_dir}.log"; then cat "${build_dir}.log" >&2 - fail "variable-only RapidJSON package did not configure" + fail "variable-only RapidJSON package failed for the wrong reason" fi rm -rf "$tmpdir" } +test_top_level_rejects_variable_only_package() { + local tmpdir prefix build_dir status + tmpdir="$(mktemp -d)" + prefix="${tmpdir}/prefix" + build_dir="${tmpdir}/top-level-build" + + write_variable_only_package "$prefix" + run_top_level_configure "$build_dir" "$prefix" + status=$? + + if [[ "$status" -eq 0 ]]; then + cat "${build_dir}.log" >&2 + fail "top-level CMake configured with variable-only RapidJSON package; expected target-missing failure" + elif ! grep -Fq "RapidJSON package configuration did not define the RapidJSON target" "${build_dir}.log"; then + cat "${build_dir}.log" >&2 + fail "top-level CMake failed for the wrong reason with variable-only RapidJSON package" + fi + + rm -rf "$tmpdir" +} + +test_top_level_uses_rapidjson_target_directly() { + local cmakelists="${REPO_ROOT}/CMakeLists.txt" + + if [[ -e "${REPO_ROOT}/cmake/AbacusRapidJSON.cmake" ]]; then + fail "cmake/AbacusRapidJSON.cmake still exists; RapidJSON config should provide the target" + fi + + if ! grep -Fq "find_package(RapidJSON CONFIG REQUIRED)" "$cmakelists"; then + fail "top-level CMakeLists.txt does not call find_package(RapidJSON CONFIG REQUIRED)" + fi + + if ! grep -Fq "target_link_libraries(abacus_external_deps INTERFACE RapidJSON)" "$cmakelists"; then + fail "top-level CMakeLists.txt does not link abacus_external_deps to RapidJSON target" + fi + + if grep -Fq "include(cmake/AbacusRapidJSON.cmake)" "$cmakelists"; then + fail "top-level CMakeLists.txt still includes the RapidJSON compatibility helper" + fi +} + test_aocc_build_script_does_not_override_rapidjson_dir() { local script="${REPO_ROOT}/toolchain/build_abacus_aocc-aocl.sh" if grep -Fq -- '-DRapidJSON_DIR=$RAPIDJSON' "$script"; then @@ -153,8 +178,10 @@ test_aocc_build_script_does_not_override_rapidjson_dir() { fi } -test_lowercase_target_package -test_variable_only_package +test_rapidjson_target_package_configures +test_variable_only_package_fails +test_top_level_rejects_variable_only_package +test_top_level_uses_rapidjson_target_directly test_aocc_build_script_does_not_override_rapidjson_dir if [[ "$FAILURES" -ne 0 ]]; then