summaryrefslogtreecommitdiff
path: root/test/posix/cmake/run.sh
blob: 76536cf73a6333f97450f4cd178db9e62068d678 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/bin/bash
##############################################################################
# Copyright (c) 2026 Eclipse ThreadX contributors
#
# This program and the accompanying materials are made available under the
# terms of the MIT License which is available at
# https://opensource.org/licenses/MIT.
#
# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5).
# The AI-generated portions may be considered public domain (CC0-1.0)
# and not subject to the project's licence. The human contributor has
# reviewed and verified that the code is correct.
#
# SPDX-License-Identifier: MIT and CC0-1.0
##############################################################################


set -e

# POSIX compatibility layer regression test build/test runner.
# Usage: run.sh <arch> <build|test> [all|<config> ...]
#   arch: riscv32
#
# Only riscv32 is available: the layer cannot carry a 64-bit message pointer
# without TX_64_BIT, and TX_64_BIT needs a port that declares
# tx_thread_extension_ptr. See the comment in ../CMakeLists.txt.

function help() {
    echo "Usage: $0 <arch> <command> [all|<build_configuration> ...]"
    echo ""
    echo "  arch:    riscv32"
    echo "  command: build | test"
    echo ""
    echo "Available build configurations:"
    for build in ${build_configurations[*]}; do
        echo "  $build"
    done
    exit 1
}

function validate() {
    for build in ${build_configurations[*]}; do
        if [ "$1" == "$build" ]; then
            return
        fi
    done
    help
}

function generate() {
    local arch=$1
    local build=$2
    local toolchain_file
    local build_dir

    toolchain_file="${REPO_ROOT}/cmake/riscv32_gnu.cmake"

    build_dir="build/${arch}_${build}"
    cmake -B"$build_dir" -GNinja \
        -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \
        -DCMAKE_BUILD_TYPE="$build" \
        .
}

function build() {
    local arch=$1
    local build=$2
    # -k 0 keeps Ninja going after a target fails, so one broken target no
    # longer decides whether the targets after it exist. ctest reports a
    # missing binary as a failing test, which turned a single link error into
    # a failure count that varied with build scheduling order.
    cmake --build "build/${arch}_${build}" -- -k 0
}

function run_test() {
    local arch=$1
    local build=$2
    local parallel_jobs=$3

    # Guard the pushd: with the caller capturing this function's status, set -e
    # no longer aborts here, so a missing build directory would otherwise let
    # ctest run in the source tree and report "no tests" as success.
    pushd "build/${arch}_${build}" || return 1
    [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j${parallel_jobs}"
    if [ -z "${CTEST_REPEAT_FAIL}" ]; then
        repeat_fail=2
    else
        repeat_fail=${CTEST_REPEAT_FAIL}
    fi
    # ctest's status is captured and returned past the popd and the summary
    # steps, which all succeed. Without this the function would return 0 and a
    # failing configuration would be reported as a pass.
    local status=0
    ctest $parallel --timeout 1000 \
        -O "${arch}_${build}.txt" \
        -T test --no-compress-output \
        --test-output-size-passed 4194304 \
        --test-output-size-failed 4194304 \
        --output-on-failure \
        --repeat until-pass:${repeat_fail} \
        --output-junit "${arch}_${build}.xml" || status=$?
    popd
    return $status
}

# Determine repo root and script directory
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
cd "$SCRIPT_DIR"

# Parse build configurations from CMakeLists.txt
result=$(sed -n "/(BUILD_CONFIGURATIONS/,/)/p" CMakeLists.txt | sed ':label;N;s/\n/ /;b label' | grep -Pzo "[a-zA-Z0-9_]*build[a-zA-Z0-9_]*\s*" | tr -d '\0')
IFS=' '
read -ra build_configurations <<< "$result"

if [ $# -lt 2 ]; then
    help
fi

arch=$1
shift

if [ "$arch" != "riscv32" ]; then
    echo "Error: arch must be 'riscv32'"
    help
fi

command=$1
shift

if [ "$#" == "0" ]; then
    builds=${build_configurations[0]}
elif [ "$*" == "all" ]; then
    builds=${build_configurations[@]}
else
    for item in $*; do
        validate "$item"
    done
    builds=$*
fi

if [ "$command" == "build" ]; then
    for item in $builds; do
        generate "$arch" "$item"
        echo ""
    done

    # A failing configuration must not stop the ones after it: under set -e
    # the loop would abort and leave them unbuilt, which then reads as a wall
    # of missing-binary test failures. The status is accumulated and returned.
    build_status=0
    for item in $builds; do
        echo "Building ${arch} ${item}"
        build "$arch" "$item" || build_status=$?
        echo ""
    done
    [ $build_status -eq 0 ] || exit $build_status
elif [ "$command" == "test" ]; then
    cores=$(nproc)
    if [ -z "${CTEST_PARALLEL_LEVEL}" ]; then
        build_counts=$(echo $builds | wc -w)
        parallel_jobs=$(($cores / $build_counts))
        parallel_jobs=$(($parallel_jobs + 2))
        pids=""
        for item in $builds; do
            echo "Testing ${arch} ${item}"
            run_test "$arch" "$item" "$parallel_jobs" &
            pids+=" $!"
        done
        exit_code=0
        for p in $pids; do
            wait $p || exit_code=$?
        done
        exit $exit_code
    else
        # ctest's status is accumulated rather than allowed to abort the loop.
        # set -e would otherwise stop at the first failing configuration and
        # leave every configuration after it untested. This mirrors what the
        # parallel branch above already does with wait.
        exit_code=0
        for item in $builds; do
            echo "Testing ${arch} ${item}"
            run_test "$arch" "$item" "$parallel_jobs" || exit_code=$?
        done
        exit $exit_code
    fi
else
    help
fi