xref: /aosp_15_r20/external/openthread/script/check-size (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1#!/bin/bash
2#
3#  Copyright (c) 2019, The OpenThread Authors.
4#  All rights reserved.
5#
6#  Redistribution and use in source and binary forms, with or without
7#  modification, are permitted provided that the following conditions are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions and the following disclaimer.
10#  2. Redistributions in binary form must reproduce the above copyright
11#     notice, this list of conditions and the following disclaimer in the
12#     documentation and/or other materials provided with the distribution.
13#  3. Neither the name of the copyright holder nor the
14#     names of its contributors may be used to endorse or promote products
15#     derived from this software without specific prior written permission.
16#
17#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27#  POSSIBILITY OF SUCH DAMAGE.
28#
29
30set -euo pipefail
31
32OT_TMP_DIR=/tmp/ot-size-report
33readonly OT_TMP_DIR
34
35OT_SHA_NEW=${GITHUB_SHA:-$(git rev-parse HEAD)}
36readonly OT_SHA_NEW
37
38OT_SHA_OLD="$(git cat-file -p "${OT_SHA_NEW}" | grep 'parent ' | head -n1 | cut -d' ' -f2)"
39readonly OT_SHA_OLD
40
41OT_REPORT_FILE_TABLE="${OT_TMP_DIR}/report_table"
42readonly OT_REPORT_FILE_TABLE
43
44OT_REPORT_FILE_PR="${OT_TMP_DIR}/report_pr"
45readonly OT_REPORT_FILE_TABLE
46
47OT_REPORTER="${OT_SIZE_REPORTER-}"
48readonly OT_REPORTER
49
50setup_arm_gcc_7()
51{
52    if arm-none-eabi-gcc --version | grep -q 'Arm Embedded Processors 7'; then
53        return 0
54    fi
55
56    (cd /tmp/ \
57        && wget --tries 4 --no-check-certificate --quiet https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2 \
58        && tar xjf gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2)
59    export PATH=/tmp/gcc-arm-none-eabi-7-2018-q2-update/bin:$PATH
60
61    arm-none-eabi-gcc --version
62}
63
64setup_ninja_build()
65{
66    sudo apt-get --no-install-recommends install -y ninja-build
67}
68
69setup()
70{
71    setup_arm_gcc_7
72    setup_ninja_build
73}
74
75nm_size()
76{
77    arm-none-eabi-nm --print-size --defined-only -C "$1" | cut -d' ' -f2- >nmsize_old
78    arm-none-eabi-nm --print-size --defined-only -C "$2" | cut -d' ' -f2- >nmsize_new
79    diff -Nuar nmsize_old nmsize_new || true
80}
81
82build_nrf52840()
83{
84    case "$1" in
85        ftd)
86            local ot_ftd=ON
87            local ot_mtd=OFF
88            local ot_rcp=ON
89            ;;
90        mtd)
91            local ot_ftd=OFF
92            local ot_mtd=ON
93            local ot_rcp=ON
94            ;;
95        br)
96            local ot_ftd=ON
97            local ot_mtd=OFF
98            local ot_rcp=OFF
99            ;;
100        *)
101            exit 128
102            ;;
103    esac
104
105    case "$2" in
106        new)
107            local sha=${OT_SHA_NEW}
108            local clone_options=("clone")
109            ;;
110        old)
111            local sha=${OT_SHA_OLD}
112            local clone_options=("clone" "no-depend")
113            ;;
114        *)
115            exit 128
116            ;;
117    esac
118
119    local folder="$1_$2"
120    local config_name="ot-core-config-check-size-$1.h"
121    local config_file="../examples/config/${config_name}"
122
123    mkdir -p "${OT_TMP_DIR}/${folder}"
124    script/git-tool "${clone_options[@]}" https://github.com/openthread/ot-nrf528xx.git "${OT_TMP_DIR}/${folder}"
125    rm -rf "${OT_TMP_DIR}/${folder}/openthread/*" # replace openthread submodule with latest commit
126    git archive "${sha}" | tar x -C "${OT_TMP_DIR}/${folder}/openthread"
127
128    if [ ! -e "${OT_TMP_DIR}/${folder}/openthread/examples/config/${config_name}" ]; then
129        # Check if the the config headers are not present, copy from
130        # the main sha.
131        case "$1" in
132            br)
133                rm -rf "${OT_TMP_DIR}/${folder}/openthread/*"
134                git archive "${OT_SHA_NEW}" | tar x -C "${OT_TMP_DIR}/${folder}/openthread"
135                ;;
136            *)
137                mkdir -p "${OT_TMP_DIR}/${folder}/openthread/examples/config"
138                cp "./examples/config/${config_name}" "${OT_TMP_DIR}/${folder}/openthread/examples/config"
139                ;;
140        esac
141    fi
142
143    local cur_dir
144
145    cur_dir=$(pwd)
146
147    cd "${OT_TMP_DIR}/${folder}"
148    OT_CMAKE_BUILD_DIR=build script/build nrf52840 UART_trans \
149        -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=${ot_rcp} \
150        -DOT_FTD=${ot_ftd} -DOT_MTD=${ot_mtd} -DOT_RCP=${ot_rcp} \
151        -DBUILD_TESTING=OFF \
152        -DOT_PROJECT_CONFIG="${config_file}"
153
154    if [[ $1 == "br" ]]; then
155        mv ./build/bin/ot-cli-ftd ./build/bin/ot-cli-ftd-br
156        mv ./build/lib/libopenthread-ftd.a ./build/lib/libopenthread-ftd-br.a
157        mv ./build/lib/libopenthread-cli-ftd.a ./build/lib/libopenthread-cli-ftd-br.a
158    fi
159
160    cd "${cur_dir}"
161}
162
163generate_table_header()
164{
165    {
166        printf "+----------------------------+----------+----------+----------+----------+----------+\n"
167        printf "| name                       | branch   | text     | data     | bss      | total    |\n"
168        printf "+============================+==========+==========+==========+==========+==========+\n"
169    } >>"${OT_REPORT_FILE_TABLE}"
170
171    {
172        printf "# Size Report of **OpenThread**\n"
173        printf "Merging PR into main\n\n"
174        printf "|  name  |  branch  |  text  | data  | bss  | total |\n"
175        printf "| :----: | :------: | -----: | ----: | ---: | ----: |\n"
176    } >>"${OT_REPORT_FILE_PR}"
177
178    {
179        printf "\n<details><summary>Library files</summary>\n\n\n"
180        printf "|  name  |  branch  |  text  | data  | bss  | total |\n"
181        printf "| :----: | :------: | -----: | ----: | ---: | ----: |\n"
182    } >>"${OT_REPORT_FILE_PR}_libs"
183
184    if [ -n "${OT_REPORTER}" ]; then
185        "${OT_REPORTER}" init OpenThread
186    fi
187
188}
189
190generate_size_diff()
191{
192    local name
193    local old_file
194    local new_file
195
196    old_file="$1"
197    new_file="$2"
198
199    name=$(basename "${old_file}")
200
201    case "${name}" in
202        lib*)
203            table_report_file="${OT_REPORT_FILE_TABLE}_libs"
204            pr_report_file="${OT_REPORT_FILE_PR}"_libs
205            ;;
206        *)
207            table_report_file="${OT_REPORT_FILE_TABLE}"
208            pr_report_file="${OT_REPORT_FILE_PR}"
209            ;;
210    esac
211
212    read -r -a size_old <<<"$(size "${old_file}" | awk '{text+=$1} {bss+=$2} {data+=$3} {total+=$4} END {printf "%d %d %d %d", text, bss, data, total}')"
213    read -r -a size_new <<<"$(size "${new_file}" | awk '{text+=$1} {bss+=$2} {data+=$3} {total+=$4} END {printf "%d %d %d %d", text, bss, data, total}')"
214
215    local -a size_diff
216
217    for i in 0 1 2 3; do
218        size_diff[$i]="$((size_new["$i"] - size_old["$i"]))"
219        if [[ ${size_diff["$i"]} != 0 ]]; then
220            size_diff["$i"]=$(printf '%+d' "${size_diff["$i"]}")
221        fi
222    done
223
224    # Generate table format report
225
226    {
227        printf "| %-26s | %-8s " "${name}" "${OT_SHA_OLD:0:8}"
228        printf "| %8u | %8u | %8u | %8u |" "${size_old[0]}" "${size_old[1]}" "${size_old[2]}" "${size_old[3]}"
229        printf "\n"
230
231        printf "| %-26s | %-8s " "" "${OT_SHA_NEW:0:8}"
232        printf "| %8u | %8u | %8u | %8u |" "${size_new[0]}" "${size_new[1]}" "${size_new[2]}" "${size_new[3]}"
233        printf "\n"
234
235        printf "| %-26s | %-8s " "" "+/-"
236        printf "| %+8d | %+8d | %+8d | %+8d |" "${size_diff[0]}" "${size_diff[1]}" "${size_diff[2]}" "${size_diff[3]}"
237        printf "\n" >>"${table_report_file}"
238
239        printf "+----------------------------+----------+----------+----------+----------+----------+\n"
240    } >>"${table_report_file}"
241
242    # Generate PR post format report
243
244    {
245        printf "| %s | %s " "${name}" "${OT_SHA_OLD:0:8}"
246        printf "| %u | %u | %u | %u |" "${size_old[0]}" "${size_old[1]}" "${size_old[2]}" "${size_old[3]}"
247        printf "\n"
248
249        printf "|  | %s " "${OT_SHA_NEW:0:8}"
250        printf "| %u | %u | %u | %u |" "${size_new[0]}" "${size_new[1]}" "${size_new[2]}" "${size_new[3]}"
251        printf "\n"
252
253        printf "|  | %s " "+/-"
254        printf "| %+d | %+d | %+d | %+d |" "${size_diff[0]}" "${size_diff[1]}" "${size_diff[2]}" "${size_diff[3]}"
255        printf "\n"
256    } >>"${pr_report_file}"
257
258    if [ -n "${OT_REPORTER}" ]; then
259        "${OT_REPORTER}" size "${old_file}" "${new_file}"
260    fi
261}
262
263generate_report()
264{
265    local type="${1}"
266    shift
267
268    local old_file
269    local new_file
270
271    for file in "$@"; do
272        case "${file}" in
273            lib*)
274                old_file="${OT_TMP_DIR}"/${type}_old/build/lib/"${file}"
275                new_file="${OT_TMP_DIR}"/${type}_new/build/lib/"${file}"
276                ;;
277            *)
278                old_file="${OT_TMP_DIR}"/${type}_old/build/bin/"${file}"
279                new_file="${OT_TMP_DIR}"/${type}_new/build/bin/"${file}"
280                ;;
281        esac
282
283        generate_size_diff "${old_file}" "${new_file}"
284
285        echo "nm_size ${old_file} ${new_file}"
286        nm_size "${old_file}" "${new_file}"
287    done
288}
289
290finalize_report()
291{
292    cat "${OT_REPORT_FILE_TABLE}"
293    cat "${OT_REPORT_FILE_TABLE}_libs"
294
295    printf "</details>" >>${OT_REPORT_FILE_PR}_libs
296    cat "${OT_REPORT_FILE_PR}_libs" >>${OT_REPORT_FILE_PR}
297
298    if [ -n "${OT_REPORTER}" ]; then
299        "${OT_REPORTER}" post
300    fi
301}
302
303size_nrf52840()
304{
305    export OT_SHA_NEW OT_SHA_OLD
306
307    rm -rf "${OT_TMP_DIR}"
308    mkdir -p "${OT_TMP_DIR}"
309
310    if [[ "${GITHUB_ACTIONS+x}" ]]; then
311        git fetch --depth 1 --no-recurse-submodules origin "${OT_SHA_OLD}"
312    fi
313
314    generate_table_header
315
316    build_nrf52840 ftd new
317    build_nrf52840 mtd new
318    build_nrf52840 br new
319
320    build_nrf52840 ftd old
321    build_nrf52840 mtd old
322    build_nrf52840 br old
323
324    local ftd_files=(
325        "ot-cli-ftd"
326        "ot-ncp-ftd"
327        "libopenthread-ftd.a"
328        "libopenthread-cli-ftd.a"
329        "libopenthread-ncp-ftd.a"
330    )
331
332    local mtd_files=(
333        "ot-cli-mtd"
334        "ot-ncp-mtd"
335        "libopenthread-mtd.a"
336        "libopenthread-cli-mtd.a"
337        "libopenthread-ncp-mtd.a"
338    )
339
340    local br_files=(
341        "ot-cli-ftd-br"
342        "libopenthread-ftd-br.a"
343        "libopenthread-cli-ftd-br.a"
344    )
345
346    # `rcp`` is using same config as `ftd`.
347    local rcp_files=(
348        "ot-rcp"
349        "libopenthread-rcp.a"
350        "libopenthread-radio.a"
351    )
352
353    generate_report ftd "${ftd_files[@]}"
354    generate_report mtd "${mtd_files[@]}"
355    generate_report br "${br_files[@]}"
356    generate_report ftd "${rcp_files[@]}"
357
358    finalize_report
359}
360
361main()
362{
363    if [[ $# == 0 ]]; then
364        setup
365        size_nrf52840
366        cd
367    elif [[ $1 == setup ]]; then
368        setup
369    elif [[ $1 == nrf52840 ]]; then
370        size_nrf52840
371    else
372        echo "USAGE: $0 [setup|nrf52840]"
373        exit 128
374    fi
375}
376
377main "$@"
378