blob: 3c0f83d9a41e58ecd45cf27a4c011865fa273952 [file] [log] [blame]
Xiaofei Baibca03e52021-09-09 09:42:37 +00001#!/usr/bin/env python3
2
3"""
Xiaofei Baibca03e52021-09-09 09:42:37 +00004This script is for comparing the size of the library files from two
5different Git revisions within an Mbed TLS repository.
6The results of the comparison is formatted as csv and stored at a
7configurable location.
8Note: must be run from Mbed TLS root.
9"""
10
11# Copyright The Mbed TLS Contributors
12# SPDX-License-Identifier: Apache-2.0
13#
14# Licensed under the Apache License, Version 2.0 (the "License"); you may
15# not use this file except in compliance with the License.
16# You may obtain a copy of the License at
17#
18# http://www.apache.org/licenses/LICENSE-2.0
19#
20# Unless required by applicable law or agreed to in writing, software
21# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
22# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23# See the License for the specific language governing permissions and
24# limitations under the License.
25
26import argparse
27import os
Yanray Wang16ebc572023-05-30 18:10:20 +080028import re
Xiaofei Baibca03e52021-09-09 09:42:37 +000029import subprocess
30import sys
Yanray Wang16ebc572023-05-30 18:10:20 +080031import typing
Yanray Wang23bd5322023-05-24 11:03:59 +080032from enum import Enum
Xiaofei Baibca03e52021-09-09 09:42:37 +000033
Yanray Wang16ebc572023-05-30 18:10:20 +080034from mbedtls_dev import typing_util
Gilles Peskined9071e72022-09-18 21:17:09 +020035from mbedtls_dev import build_tree
36
Yanray Wang23bd5322023-05-24 11:03:59 +080037class SupportedArch(Enum):
38 """Supported architecture for code size measurement."""
39 AARCH64 = 'aarch64'
40 AARCH32 = 'aarch32'
Yanray Wangaba71582023-05-29 16:45:56 +080041 ARMV8_M = 'armv8-m'
Yanray Wang23bd5322023-05-24 11:03:59 +080042 X86_64 = 'x86_64'
43 X86 = 'x86'
44
Yanray Wang6a862582023-05-24 12:24:38 +080045CONFIG_TFM_MEDIUM_MBEDCRYPTO_H = "../configs/tfm_mbedcrypto_config_profile_medium.h"
46CONFIG_TFM_MEDIUM_PSA_CRYPTO_H = "../configs/crypto_config_profile_medium.h"
47class SupportedConfig(Enum):
48 """Supported configuration for code size measurement."""
49 DEFAULT = 'default'
50 TFM_MEDIUM = 'tfm-medium'
51
Yanray Wang16ebc572023-05-30 18:10:20 +080052# Static library
53MBEDTLS_STATIC_LIB = {
54 'CRYPTO': 'library/libmbedcrypto.a',
55 'X509': 'library/libmbedx509.a',
56 'TLS': 'library/libmbedtls.a',
57}
58
Yanray Wang23bd5322023-05-24 11:03:59 +080059DETECT_ARCH_CMD = "cc -dM -E - < /dev/null"
60def detect_arch() -> str:
61 """Auto-detect host architecture."""
62 cc_output = subprocess.check_output(DETECT_ARCH_CMD, shell=True).decode()
63 if "__aarch64__" in cc_output:
64 return SupportedArch.AARCH64.value
65 if "__arm__" in cc_output:
66 return SupportedArch.AARCH32.value
67 if "__x86_64__" in cc_output:
68 return SupportedArch.X86_64.value
69 if "__x86__" in cc_output:
70 return SupportedArch.X86.value
71 else:
72 print("Unknown host architecture, cannot auto-detect arch.")
73 sys.exit(1)
Gilles Peskined9071e72022-09-18 21:17:09 +020074
Yanray Wang6a862582023-05-24 12:24:38 +080075class CodeSizeInfo: # pylint: disable=too-few-public-methods
76 """Gather information used to measure code size.
77
78 It collects information about architecture, configuration in order to
79 infer build command for code size measurement.
80 """
81
Yanray Wangc18cd892023-05-31 11:08:04 +080082 SupportedArchConfig = [
83 "-a " + SupportedArch.AARCH64.value + " -c " + SupportedConfig.DEFAULT.value,
84 "-a " + SupportedArch.AARCH32.value + " -c " + SupportedConfig.DEFAULT.value,
85 "-a " + SupportedArch.X86_64.value + " -c " + SupportedConfig.DEFAULT.value,
86 "-a " + SupportedArch.X86.value + " -c " + SupportedConfig.DEFAULT.value,
87 "-a " + SupportedArch.ARMV8_M.value + " -c " + SupportedConfig.TFM_MEDIUM.value,
88 ]
89
Yanray Wang21f17442023-06-01 11:29:06 +080090 def __init__(self, arch: str, config: str, sys_arch: str) -> None:
Yanray Wang6a862582023-05-24 12:24:38 +080091 """
92 arch: architecture to measure code size on.
93 config: configuration type to measure code size with.
Yanray Wang699a6c82023-07-04 17:21:28 +080094 sys_arch: host architecture.
Yanray Wang6a862582023-05-24 12:24:38 +080095 make_command: command to build library (Inferred from arch and config).
96 """
97 self.arch = arch
98 self.config = config
Yanray Wang21f17442023-06-01 11:29:06 +080099 self.sys_arch = sys_arch
Yanray Wang6a862582023-05-24 12:24:38 +0800100 self.make_command = self.set_make_command()
101
102 def set_make_command(self) -> str:
103 """Infer build command based on architecture and configuration."""
104
Yanray Wang21f17442023-06-01 11:29:06 +0800105 if self.config == SupportedConfig.DEFAULT.value and \
106 self.arch == self.sys_arch:
Yanray Wang6a862582023-05-24 12:24:38 +0800107 return 'make -j lib CFLAGS=\'-Os \' '
Yanray Wangaba71582023-05-29 16:45:56 +0800108 elif self.arch == SupportedArch.ARMV8_M.value and \
Yanray Wang6a862582023-05-24 12:24:38 +0800109 self.config == SupportedConfig.TFM_MEDIUM.value:
110 return \
Yanray Wang60430bd2023-05-29 14:48:18 +0800111 'make -j lib CC=armclang \
Yanray Wang6a862582023-05-24 12:24:38 +0800112 CFLAGS=\'--target=arm-arm-none-eabi -mcpu=cortex-m33 -Os \
113 -DMBEDTLS_CONFIG_FILE=\\\"' + CONFIG_TFM_MEDIUM_MBEDCRYPTO_H + '\\\" \
114 -DMBEDTLS_PSA_CRYPTO_CONFIG_FILE=\\\"' + CONFIG_TFM_MEDIUM_PSA_CRYPTO_H + '\\\" \''
115 else:
Yanray Wang21f17442023-06-01 11:29:06 +0800116 print("Unsupported combination of architecture: {} and configuration: {}"
Yanray Wang6a862582023-05-24 12:24:38 +0800117 .format(self.arch, self.config))
Yanray Wangc18cd892023-05-31 11:08:04 +0800118 print("\nPlease use supported combination of architecture and configuration:")
119 for comb in CodeSizeInfo.SupportedArchConfig:
120 print(comb)
Yanray Wang21f17442023-06-01 11:29:06 +0800121 print("\nFor your system, please use:")
122 for comb in CodeSizeInfo.SupportedArchConfig:
123 if "default" in comb and self.sys_arch not in comb:
124 continue
125 print(comb)
Yanray Wang6a862582023-05-24 12:24:38 +0800126 sys.exit(1)
127
128
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800129class CodeSizeGeneratorWithSize:
Yanray Wang16ebc572023-05-30 18:10:20 +0800130 """Code Size Base Class for size record saving and writing."""
131
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800132 class SizeEntry: # pylint: disable=too-few-public-methods
133 """Data Structure to only store information of code size."""
134 def __init__(self, text, data, bss, dec):
135 self.text = text
136 self.data = data
137 self.bss = bss
138 self.total = dec # total <=> dec
139
Yanray Wang16ebc572023-05-30 18:10:20 +0800140 def __init__(self) -> None:
141 """ Variable code_size is used to store size info for any revisions.
142 code_size: (data format)
143 {revision: {module: {file_name: SizeEntry,
144 etc ...
145 },
146 etc ...
147 },
148 etc ...
149 }
150 """
151 self.code_size = {} #type: typing.Dict[str, typing.Dict]
152
153 def set_size_record(self, revision: str, mod: str, size_text: str) -> None:
154 """Store size information for target revision and high-level module.
155
156 size_text Format: text data bss dec hex filename
157 """
158 size_record = {}
159 for line in size_text.splitlines()[1:]:
160 data = line.split()
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800161 size_record[data[5]] = CodeSizeGeneratorWithSize.SizeEntry(\
162 data[0], data[1], data[2], data[3])
Yanray Wang16ebc572023-05-30 18:10:20 +0800163 if revision in self.code_size:
164 self.code_size[revision].update({mod: size_record})
165 else:
166 self.code_size[revision] = {mod: size_record}
167
168 def read_size_record(self, revision: str, fname: str) -> None:
169 """Read size information from csv file and write it into code_size.
170
171 fname Format: filename text data bss dec
172 """
173 mod = ""
174 size_record = {}
175 with open(fname, 'r') as csv_file:
176 for line in csv_file:
177 data = line.strip().split()
178 # check if we find the beginning of a module
179 if data and data[0] in MBEDTLS_STATIC_LIB:
180 mod = data[0]
181 continue
182
183 if mod:
184 size_record[data[0]] = \
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800185 CodeSizeGeneratorWithSize.SizeEntry(\
186 data[1], data[2], data[3], data[4])
Yanray Wang16ebc572023-05-30 18:10:20 +0800187
188 # check if we hit record for the end of a module
189 m = re.match(r'.?TOTALS', line)
190 if m:
191 if revision in self.code_size:
192 self.code_size[revision].update({mod: size_record})
193 else:
194 self.code_size[revision] = {mod: size_record}
195 mod = ""
196 size_record = {}
197
198 def _size_reader_helper(
199 self,
200 revision: str,
201 output: typing_util.Writable
202 ) -> typing.Iterator[tuple]:
203 """A helper function to peel code_size based on revision."""
204 for mod, file_size in self.code_size[revision].items():
205 output.write("\n" + mod + "\n")
206 for fname, size_entry in file_size.items():
207 yield mod, fname, size_entry
208
209 def write_size_record(
210 self,
211 revision: str,
212 output: typing_util.Writable
213 ) -> None:
214 """Write size information to a file.
215
216 Writing Format: file_name text data bss total(dec)
217 """
218 output.write("{:<30} {:>7} {:>7} {:>7} {:>7}\n"
219 .format("filename", "text", "data", "bss", "total"))
220 for _, fname, size_entry in self._size_reader_helper(revision, output):
221 output.write("{:<30} {:>7} {:>7} {:>7} {:>7}\n"
222 .format(fname, size_entry.text, size_entry.data,\
223 size_entry.bss, size_entry.total))
224
225 def write_comparison(
226 self,
227 old_rev: str,
228 new_rev: str,
229 output: typing_util.Writable
230 ) -> None:
231 """Write comparison result into a file.
232
233 Writing Format: file_name current(total) old(total) change(Byte) change_pct(%)
234 """
235 output.write("{:<30} {:>7} {:>7} {:>7} {:>7}\n"
236 .format("filename", "current", "old", "change", "change%"))
237 for mod, fname, size_entry in self._size_reader_helper(new_rev, output):
238 new_size = int(size_entry.total)
239 # check if we have the file in old revision
240 if fname in self.code_size[old_rev][mod]:
241 old_size = int(self.code_size[old_rev][mod][fname].total)
242 change = new_size - old_size
243 if old_size != 0:
244 change_pct = change / old_size
245 else:
246 change_pct = 0
247 output.write("{:<30} {:>7} {:>7} {:>7} {:>7.2%}\n"
248 .format(fname, new_size, old_size, change, change_pct))
249 else:
250 output.write("{} {}\n".format(fname, new_size))
251
252
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800253class CodeSizeComparison:
Xiaofei Bai2400b502021-10-21 12:22:58 +0000254 """Compare code size between two Git revisions."""
Xiaofei Baibca03e52021-09-09 09:42:37 +0000255
Yanray Wang72b105f2023-05-31 15:20:39 +0800256 def __init__(
257 self,
258 old_revision: str,
259 new_revision: str,
260 result_dir: str,
261 code_size_info: CodeSizeInfo
262 ) -> None:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000263 """
Yanray Wang6a862582023-05-24 12:24:38 +0800264 old_revision: revision to compare against.
Xiaofei Baibca03e52021-09-09 09:42:37 +0000265 new_revision:
Yanray Wang6a862582023-05-24 12:24:38 +0800266 result_dir: directory for comparison result.
267 code_size_info: an object containing information to build library.
Xiaofei Baibca03e52021-09-09 09:42:37 +0000268 """
Yanray Wang8804db92023-05-30 18:18:18 +0800269 super().__init__()
Xiaofei Baibca03e52021-09-09 09:42:37 +0000270 self.repo_path = "."
271 self.result_dir = os.path.abspath(result_dir)
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000272 os.makedirs(self.result_dir, exist_ok=True)
Xiaofei Baibca03e52021-09-09 09:42:37 +0000273
274 self.csv_dir = os.path.abspath("code_size_records/")
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000275 os.makedirs(self.csv_dir, exist_ok=True)
Xiaofei Baibca03e52021-09-09 09:42:37 +0000276
277 self.old_rev = old_revision
278 self.new_rev = new_revision
279 self.git_command = "git"
Yanray Wang4c26db02023-07-04 16:49:04 +0800280 self.make_clean = 'make clean'
Yanray Wang6a862582023-05-24 12:24:38 +0800281 self.make_command = code_size_info.make_command
Yanray Wang369cd962023-05-24 17:13:29 +0800282 self.fname_suffix = "-" + code_size_info.arch + "-" +\
283 code_size_info.config
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800284 self.code_size_generator = CodeSizeGeneratorWithSize()
Xiaofei Baibca03e52021-09-09 09:42:37 +0000285
286 @staticmethod
Yanray Wang72b105f2023-05-31 15:20:39 +0800287 def validate_revision(revision: str) -> bytes:
Xiaofei Baiccd738b2021-11-03 07:12:31 +0000288 result = subprocess.check_output(["git", "rev-parse", "--verify",
289 revision + "^{commit}"], shell=False)
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000290 return result
Xiaofei Bai2400b502021-10-21 12:22:58 +0000291
Yanray Wang72b105f2023-05-31 15:20:39 +0800292 def _create_git_worktree(self, revision: str) -> str:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000293 """Make a separate worktree for revision.
294 Do not modify the current worktree."""
295
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000296 if revision == "current":
Yanray Wangc7a2a6d2023-05-31 15:47:25 +0800297 print("Using current work directory")
Xiaofei Baibca03e52021-09-09 09:42:37 +0000298 git_worktree_path = self.repo_path
299 else:
300 print("Creating git worktree for", revision)
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000301 git_worktree_path = os.path.join(self.repo_path, "temp-" + revision)
Xiaofei Baibca03e52021-09-09 09:42:37 +0000302 subprocess.check_output(
303 [self.git_command, "worktree", "add", "--detach",
304 git_worktree_path, revision], cwd=self.repo_path,
305 stderr=subprocess.STDOUT
306 )
Aditya Deshpande41a0aad2023-04-13 16:32:21 +0100307
Xiaofei Baibca03e52021-09-09 09:42:37 +0000308 return git_worktree_path
309
Yanray Wang72b105f2023-05-31 15:20:39 +0800310 def _build_libraries(self, git_worktree_path: str) -> None:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000311 """Build libraries in the specified worktree."""
312
313 my_environment = os.environ.copy()
Aditya Deshpande41a0aad2023-04-13 16:32:21 +0100314 try:
315 subprocess.check_output(
Yanray Wang4c26db02023-07-04 16:49:04 +0800316 self.make_clean, env=my_environment, shell=True,
317 cwd=git_worktree_path, stderr=subprocess.STDOUT,
318 )
319 subprocess.check_output(
Aditya Deshpande41a0aad2023-04-13 16:32:21 +0100320 self.make_command, env=my_environment, shell=True,
321 cwd=git_worktree_path, stderr=subprocess.STDOUT,
322 )
323 except subprocess.CalledProcessError as e:
324 self._handle_called_process_error(e, git_worktree_path)
Xiaofei Baibca03e52021-09-09 09:42:37 +0000325
Yanray Wang72b105f2023-05-31 15:20:39 +0800326 def _gen_code_size_csv(self, revision: str, git_worktree_path: str) -> None:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000327 """Generate code size csv file."""
328
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000329 if revision == "current":
Yanray Wangc7a2a6d2023-05-31 15:47:25 +0800330 print("Measuring code size in current work directory")
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000331 else:
332 print("Measuring code size for", revision)
Yanray Wang8804db92023-05-30 18:18:18 +0800333
334 for mod, st_lib in MBEDTLS_STATIC_LIB.items():
335 try:
336 result = subprocess.check_output(
337 ["size", st_lib, "-t"], cwd=git_worktree_path
338 )
339 except subprocess.CalledProcessError as e:
340 self._handle_called_process_error(e, git_worktree_path)
341 size_text = result.decode("utf-8")
342
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800343 self.code_size_generator.set_size_record(revision, mod, size_text)
Yanray Wang8804db92023-05-30 18:18:18 +0800344
345 print("Generating code size csv for", revision)
346 csv_file = open(os.path.join(self.csv_dir, revision +
347 self.fname_suffix + ".csv"), "w")
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800348 self.code_size_generator.write_size_record(revision, csv_file)
Xiaofei Baibca03e52021-09-09 09:42:37 +0000349
Yanray Wang72b105f2023-05-31 15:20:39 +0800350 def _remove_worktree(self, git_worktree_path: str) -> None:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000351 """Remove temporary worktree."""
352 if git_worktree_path != self.repo_path:
353 print("Removing temporary worktree", git_worktree_path)
354 subprocess.check_output(
355 [self.git_command, "worktree", "remove", "--force",
356 git_worktree_path], cwd=self.repo_path,
357 stderr=subprocess.STDOUT
358 )
359
Yanray Wang72b105f2023-05-31 15:20:39 +0800360 def _get_code_size_for_rev(self, revision: str) -> None:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000361 """Generate code size csv file for the specified git revision."""
362
363 # Check if the corresponding record exists
Yanray Wang369cd962023-05-24 17:13:29 +0800364 csv_fname = revision + self.fname_suffix + ".csv"
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000365 if (revision != "current") and \
Xiaofei Baibca03e52021-09-09 09:42:37 +0000366 os.path.exists(os.path.join(self.csv_dir, csv_fname)):
367 print("Code size csv file for", revision, "already exists.")
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800368 self.code_size_generator.read_size_record(revision,\
369 os.path.join(self.csv_dir, csv_fname))
Xiaofei Baibca03e52021-09-09 09:42:37 +0000370 else:
371 git_worktree_path = self._create_git_worktree(revision)
372 self._build_libraries(git_worktree_path)
373 self._gen_code_size_csv(revision, git_worktree_path)
374 self._remove_worktree(git_worktree_path)
375
Yanray Wang72b105f2023-05-31 15:20:39 +0800376 def _gen_code_size_comparison(self) -> int:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000377 """Generate results of the size changes between two revisions,
378 old and new. Measured code size results of these two revisions
Xiaofei Bai2400b502021-10-21 12:22:58 +0000379 must be available."""
Xiaofei Baibca03e52021-09-09 09:42:37 +0000380
Yanray Wang369cd962023-05-24 17:13:29 +0800381 res_file = open(os.path.join(self.result_dir, "compare-" +
382 self.old_rev + "-" + self.new_rev +
383 self.fname_suffix +
384 ".csv"), "w")
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000385
Yanray Wangc7a2a6d2023-05-31 15:47:25 +0800386 print("\nGenerating comparison results between",\
387 self.old_rev, "and", self.new_rev)
Yanray Wangfc6ed4d2023-07-14 17:33:09 +0800388 self.code_size_generator.write_comparison(self.old_rev, self.new_rev, res_file)
Xiaofei Baibca03e52021-09-09 09:42:37 +0000389
Xiaofei Bai2400b502021-10-21 12:22:58 +0000390 return 0
Xiaofei Baibca03e52021-09-09 09:42:37 +0000391
Yanray Wang72b105f2023-05-31 15:20:39 +0800392 def get_comparision_results(self) -> int:
Xiaofei Baibca03e52021-09-09 09:42:37 +0000393 """Compare size of library/*.o between self.old_rev and self.new_rev,
394 and generate the result file."""
Gilles Peskined9071e72022-09-18 21:17:09 +0200395 build_tree.check_repo_path()
Xiaofei Baibca03e52021-09-09 09:42:37 +0000396 self._get_code_size_for_rev(self.old_rev)
397 self._get_code_size_for_rev(self.new_rev)
Yanray Wang8804db92023-05-30 18:18:18 +0800398 return self._gen_code_size_comparison()
Xiaofei Baibca03e52021-09-09 09:42:37 +0000399
Aditya Deshpande41a0aad2023-04-13 16:32:21 +0100400 def _handle_called_process_error(self, e: subprocess.CalledProcessError,
Yanray Wang72b105f2023-05-31 15:20:39 +0800401 git_worktree_path: str) -> None:
Aditya Deshpande41a0aad2023-04-13 16:32:21 +0100402 """Handle a CalledProcessError and quit the program gracefully.
403 Remove any extra worktrees so that the script may be called again."""
404
405 # Tell the user what went wrong
406 print("The following command: {} failed and exited with code {}"
407 .format(e.cmd, e.returncode))
408 print("Process output:\n {}".format(str(e.output, "utf-8")))
409
410 # Quit gracefully by removing the existing worktree
411 self._remove_worktree(git_worktree_path)
412 sys.exit(-1)
413
Xiaofei Bai2400b502021-10-21 12:22:58 +0000414def main():
Yanray Wang502c54f2023-05-31 11:41:36 +0800415 parser = argparse.ArgumentParser(description=(__doc__))
416 group_required = parser.add_argument_group(
417 'required arguments',
418 'required arguments to parse for running ' + os.path.basename(__file__))
419 group_required.add_argument(
420 "-o", "--old-rev", type=str, required=True,
421 help="old revision for comparison.")
422
423 group_optional = parser.add_argument_group(
424 'optional arguments',
425 'optional arguments to parse for running ' + os.path.basename(__file__))
426 group_optional.add_argument(
Xiaofei Baibca03e52021-09-09 09:42:37 +0000427 "-r", "--result-dir", type=str, default="comparison",
428 help="directory where comparison result is stored, \
Yanray Wang502c54f2023-05-31 11:41:36 +0800429 default is comparison")
430 group_optional.add_argument(
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000431 "-n", "--new-rev", type=str, default=None,
432 help="new revision for comparison, default is the current work \
Yanray Wang502c54f2023-05-31 11:41:36 +0800433 directory, including uncommitted changes.")
434 group_optional.add_argument(
Yanray Wang23bd5322023-05-24 11:03:59 +0800435 "-a", "--arch", type=str, default=detect_arch(),
436 choices=list(map(lambda s: s.value, SupportedArch)),
437 help="specify architecture for code size comparison, default is the\
Yanray Wang502c54f2023-05-31 11:41:36 +0800438 host architecture.")
439 group_optional.add_argument(
Yanray Wang6a862582023-05-24 12:24:38 +0800440 "-c", "--config", type=str, default=SupportedConfig.DEFAULT.value,
441 choices=list(map(lambda s: s.value, SupportedConfig)),
442 help="specify configuration type for code size comparison,\
Yanray Wang502c54f2023-05-31 11:41:36 +0800443 default is the current MbedTLS configuration.")
Xiaofei Baibca03e52021-09-09 09:42:37 +0000444 comp_args = parser.parse_args()
445
446 if os.path.isfile(comp_args.result_dir):
447 print("Error: {} is not a directory".format(comp_args.result_dir))
448 parser.exit()
449
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000450 validate_res = CodeSizeComparison.validate_revision(comp_args.old_rev)
Xiaofei Baiccd738b2021-11-03 07:12:31 +0000451 old_revision = validate_res.decode().replace("\n", "")
Xiaofei Bai2400b502021-10-21 12:22:58 +0000452
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000453 if comp_args.new_rev is not None:
454 validate_res = CodeSizeComparison.validate_revision(comp_args.new_rev)
Xiaofei Baiccd738b2021-11-03 07:12:31 +0000455 new_revision = validate_res.decode().replace("\n", "")
Xiaofei Bai184e8b62021-10-26 09:23:42 +0000456 else:
457 new_revision = "current"
Xiaofei Bai2400b502021-10-21 12:22:58 +0000458
Yanray Wang21f17442023-06-01 11:29:06 +0800459 code_size_info = CodeSizeInfo(comp_args.arch, comp_args.config,
460 detect_arch())
Yanray Wangc7a2a6d2023-05-31 15:47:25 +0800461 print("Measure code size for architecture: {}, configuration: {}\n"
Yanray Wangaba71582023-05-29 16:45:56 +0800462 .format(code_size_info.arch, code_size_info.config))
Xiaofei Baibca03e52021-09-09 09:42:37 +0000463 result_dir = comp_args.result_dir
Yanray Wang6a862582023-05-24 12:24:38 +0800464 size_compare = CodeSizeComparison(old_revision, new_revision, result_dir,
465 code_size_info)
Xiaofei Baibca03e52021-09-09 09:42:37 +0000466 return_code = size_compare.get_comparision_results()
467 sys.exit(return_code)
468
469
470if __name__ == "__main__":
Xiaofei Bai2400b502021-10-21 12:22:58 +0000471 main()