blob: a5ef7e6482116cbc4f1b033760322daa4deb7ff4 [file] [log] [blame]
Darryl Green7c2dd582018-03-01 14:53:49 +00001#!/usr/bin/env python3
Darryl Green78696802018-04-06 11:23:22 +01002"""
3This file is part of Mbed TLS (https://tls.mbed.org)
4
5Copyright (c) 2018, Arm Limited, All Rights Reserved
6
7Purpose
8
9This script is a small wrapper around the abi-compliance-checker and
10abi-dumper tools, applying them to compare the ABI and API of the library
11files from two different Git revisions within an Mbed TLS repository.
Darryl Green0da45782019-02-21 13:09:26 +000012The results of the comparison are either formatted as HTML and stored at
Darryl Green7c0e0522019-03-05 15:21:32 +000013a configurable location, or are given as a brief list of problems.
Darryl Green0da45782019-02-21 13:09:26 +000014Returns 0 on success, 1 on ABI/API non-compliance, and 2 if there is an error
15while running the script. Note: must be run from Mbed TLS root.
Darryl Green78696802018-04-06 11:23:22 +010016"""
Darryl Green7c2dd582018-03-01 14:53:49 +000017
18import os
19import sys
20import traceback
21import shutil
22import subprocess
23import argparse
24import logging
25import tempfile
Darryl Greenae5d66c2019-02-25 11:35:05 +000026import fnmatch
Darryl Green7c2dd582018-03-01 14:53:49 +000027
Darryl Green0da45782019-02-21 13:09:26 +000028import xml.etree.ElementTree as ET
29
Darryl Green7c2dd582018-03-01 14:53:49 +000030
Darryl Green7381bea2019-03-05 16:25:38 +000031class RepoVersion(object):
32
33 def __init__(self, version, repository, revision,
34 crypto_repository, crypto_revision):
35 """Class containing details for a particular revision.
36
37 version: either 'old' or 'new'
38 repository: repository for git revision
39 revision: git revision for comparison
40 crypto_repository: repository for git revision of crypto submodule
41 crypto_revision: git revision of crypto submodule
42 """
43 self.version = version
44 self.repository = repository
45 self.revision = revision
46 self.crypto_repository = crypto_repository
47 self.crypto_revision = crypto_revision
48 self.abi_dumps = {}
49 self.modules = {}
50
51
Darryl Green7c2dd582018-03-01 14:53:49 +000052class AbiChecker(object):
Gilles Peskine9df17632019-02-25 20:36:52 +010053 """API and ABI checker."""
Darryl Green7c2dd582018-03-01 14:53:49 +000054
Darryl Green66025382019-03-08 11:30:04 +000055 def __init__(self, verbose, old_version, new_version, report_dir,
Darryl Green7381bea2019-03-05 16:25:38 +000056 keep_all_reports, brief, skip_file=None):
Gilles Peskine9df17632019-02-25 20:36:52 +010057 """Instantiate the API/ABI checker.
58
Darryl Green7381bea2019-03-05 16:25:38 +000059 old_version: RepoVersion containing details to compare against
60 new_version: RepoVersion containing details to check
Gilles Peskine9df17632019-02-25 20:36:52 +010061 report_dir: directory for output files
Gilles Peskine9df17632019-02-25 20:36:52 +010062 keep_all_reports: if false, delete old reports
Darryl Green0da45782019-02-21 13:09:26 +000063 brief: if true, output shorter report to stdout
Darryl Green668063b2019-02-20 15:01:56 +000064 skip_file: path to file containing symbols and types to skip
Gilles Peskine9df17632019-02-25 20:36:52 +010065 """
Darryl Green7c2dd582018-03-01 14:53:49 +000066 self.repo_path = "."
67 self.log = None
Darryl Green66025382019-03-08 11:30:04 +000068 self.verbose = verbose
Darryl Green88bfbc22019-03-05 16:30:39 +000069 self._setup_logger()
Darryl Green7c2dd582018-03-01 14:53:49 +000070 self.report_dir = os.path.abspath(report_dir)
71 self.keep_all_reports = keep_all_reports
Darryl Green131e24b2019-02-25 17:01:55 +000072 self.can_remove_report_dir = not (os.path.isdir(self.report_dir) or
73 keep_all_reports)
Darryl Green7381bea2019-03-05 16:25:38 +000074 self.old_version = old_version
75 self.new_version = new_version
Darryl Green668063b2019-02-20 15:01:56 +000076 self.skip_file = skip_file
Darryl Green0da45782019-02-21 13:09:26 +000077 self.brief = brief
Darryl Green7c2dd582018-03-01 14:53:49 +000078 self.git_command = "git"
79 self.make_command = "make"
80
Gilles Peskine9df17632019-02-25 20:36:52 +010081 @staticmethod
82 def check_repo_path():
Darryl Greena6f430f2018-03-15 10:12:06 +000083 current_dir = os.path.realpath('.')
84 root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
85 if current_dir != root_dir:
Darryl Green7c2dd582018-03-01 14:53:49 +000086 raise Exception("Must be run from Mbed TLS root")
87
Darryl Green88bfbc22019-03-05 16:30:39 +000088 def _setup_logger(self):
Darryl Green7c2dd582018-03-01 14:53:49 +000089 self.log = logging.getLogger()
Darryl Green66025382019-03-08 11:30:04 +000090 if self.verbose:
91 self.log.setLevel(logging.DEBUG)
92 else:
93 self.log.setLevel(logging.INFO)
Darryl Green7c2dd582018-03-01 14:53:49 +000094 self.log.addHandler(logging.StreamHandler())
95
Gilles Peskine9df17632019-02-25 20:36:52 +010096 @staticmethod
97 def check_abi_tools_are_installed():
Darryl Green7c2dd582018-03-01 14:53:49 +000098 for command in ["abi-dumper", "abi-compliance-checker"]:
99 if not shutil.which(command):
100 raise Exception("{} not installed, aborting".format(command))
101
Darryl Green88bfbc22019-03-05 16:30:39 +0000102 def _get_clean_worktree_for_git_revision(self, version):
Darryl Green7381bea2019-03-05 16:25:38 +0000103 """Make a separate worktree with version.revision checked out.
Gilles Peskine9df17632019-02-25 20:36:52 +0100104 Do not modify the current worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000105 git_worktree_path = tempfile.mkdtemp()
Darryl Green7381bea2019-03-05 16:25:38 +0000106 if version.repository:
Darryl Green66025382019-03-08 11:30:04 +0000107 self.log.debug(
Darryl Green5a301f02019-02-19 16:59:33 +0000108 "Checking out git worktree for revision {} from {}".format(
Darryl Green7381bea2019-03-05 16:25:38 +0000109 version.revision, version.repository
Darryl Green5a301f02019-02-19 16:59:33 +0000110 )
111 )
112 fetch_process = subprocess.Popen(
Darryl Green7381bea2019-03-05 16:25:38 +0000113 [self.git_command, "fetch",
114 version.repository, version.revision],
Darryl Green5a301f02019-02-19 16:59:33 +0000115 cwd=self.repo_path,
116 stdout=subprocess.PIPE,
117 stderr=subprocess.STDOUT
118 )
119 fetch_output, _ = fetch_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000120 self.log.debug(fetch_output.decode("utf-8"))
Darryl Green5a301f02019-02-19 16:59:33 +0000121 if fetch_process.returncode != 0:
122 raise Exception("Fetching revision failed, aborting")
123 worktree_rev = "FETCH_HEAD"
124 else:
Darryl Green66025382019-03-08 11:30:04 +0000125 self.log.debug("Checking out git worktree for revision {}".format(
Darryl Green7381bea2019-03-05 16:25:38 +0000126 version.revision
127 ))
128 worktree_rev = version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000129 worktree_process = subprocess.Popen(
Darryl Green5a301f02019-02-19 16:59:33 +0000130 [self.git_command, "worktree", "add", "--detach",
131 git_worktree_path, worktree_rev],
Darryl Green7c2dd582018-03-01 14:53:49 +0000132 cwd=self.repo_path,
133 stdout=subprocess.PIPE,
134 stderr=subprocess.STDOUT
135 )
136 worktree_output, _ = worktree_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000137 self.log.debug(worktree_output.decode("utf-8"))
Darryl Green7c2dd582018-03-01 14:53:49 +0000138 if worktree_process.returncode != 0:
139 raise Exception("Checking out worktree failed, aborting")
140 return git_worktree_path
141
Darryl Green88bfbc22019-03-05 16:30:39 +0000142 def _update_git_submodules(self, git_worktree_path, version):
Jaeden Amero4cd4b4b2018-11-02 16:35:09 +0000143 process = subprocess.Popen(
144 [self.git_command, "submodule", "update", "--init", '--recursive'],
145 cwd=git_worktree_path,
146 stdout=subprocess.PIPE,
147 stderr=subprocess.STDOUT
148 )
149 output, _ = process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000150 self.log.debug(output.decode("utf-8"))
Jaeden Amero4cd4b4b2018-11-02 16:35:09 +0000151 if process.returncode != 0:
152 raise Exception("git submodule update failed, aborting")
Darryl Green0478a322019-03-05 15:23:25 +0000153 if not (os.path.exists(os.path.join(git_worktree_path, "crypto"))
Darryl Green7381bea2019-03-05 16:25:38 +0000154 and version.crypto_revision):
Darryl Green0478a322019-03-05 15:23:25 +0000155 return
156
Darryl Green7381bea2019-03-05 16:25:38 +0000157 if version.crypto_repository:
Darryl Green3f742982019-03-08 11:12:19 +0000158 fetch_process = subprocess.Popen(
159 [self.git_command, "fetch", version.crypto_repository,
160 version.crypto_revision],
Darryl Green0478a322019-03-05 15:23:25 +0000161 cwd=os.path.join(git_worktree_path, "crypto"),
162 stdout=subprocess.PIPE,
163 stderr=subprocess.STDOUT
164 )
Darryl Green3f742982019-03-08 11:12:19 +0000165 fetch_output, _ = fetch_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000166 self.log.debug(fetch_output.decode("utf-8"))
Darryl Green3f742982019-03-08 11:12:19 +0000167 if fetch_process.returncode != 0:
168 raise Exception("git fetch failed, aborting")
169 crypto_rev = "FETCH_HEAD"
170 else:
171 crypto_rev = version.crypto_revision
172
173 checkout_process = subprocess.Popen(
174 [self.git_command, "checkout", crypto_rev],
175 cwd=os.path.join(git_worktree_path, "crypto"),
176 stdout=subprocess.PIPE,
177 stderr=subprocess.STDOUT
178 )
179 checkout_output, _ = checkout_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000180 self.log.debug(checkout_output.decode("utf-8"))
Darryl Green3f742982019-03-08 11:12:19 +0000181 if checkout_process.returncode != 0:
182 raise Exception("git checkout failed, aborting")
Jaeden Amero4cd4b4b2018-11-02 16:35:09 +0000183
Darryl Green88bfbc22019-03-05 16:30:39 +0000184 def _build_shared_libraries(self, git_worktree_path, version):
Gilles Peskine9df17632019-02-25 20:36:52 +0100185 """Build the shared libraries in the specified worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000186 my_environment = os.environ.copy()
187 my_environment["CFLAGS"] = "-g -Og"
188 my_environment["SHARED"] = "1"
Darryl Greenae5d66c2019-02-25 11:35:05 +0000189 my_environment["USE_CRYPTO_SUBMODULE"] = "1"
Darryl Green7c2dd582018-03-01 14:53:49 +0000190 make_process = subprocess.Popen(
Darryl Greenc8e6ad42019-02-28 11:52:39 +0000191 [self.make_command, "lib"],
Darryl Green7c2dd582018-03-01 14:53:49 +0000192 env=my_environment,
193 cwd=git_worktree_path,
194 stdout=subprocess.PIPE,
195 stderr=subprocess.STDOUT
196 )
197 make_output, _ = make_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000198 self.log.debug(make_output.decode("utf-8"))
Darryl Greenae5d66c2019-02-25 11:35:05 +0000199 for root, dirs, files in os.walk(git_worktree_path):
200 for file in fnmatch.filter(files, "*.so"):
Darryl Green7381bea2019-03-05 16:25:38 +0000201 version.modules[os.path.splitext(file)[0]] = (
Darryl Greende118092019-02-27 16:53:40 +0000202 os.path.join(root, file)
Darryl Greenae5d66c2019-02-25 11:35:05 +0000203 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000204 if make_process.returncode != 0:
205 raise Exception("make failed, aborting")
206
Darryl Green88bfbc22019-03-05 16:30:39 +0000207 def _get_abi_dumps_from_shared_libraries(self, git_worktree_path,
208 version):
Gilles Peskine9df17632019-02-25 20:36:52 +0100209 """Generate the ABI dumps for the specified git revision.
210 It must be checked out in git_worktree_path and the shared libraries
211 must have been built."""
Darryl Green7381bea2019-03-05 16:25:38 +0000212 for mbed_module, module_path in version.modules.items():
Darryl Green7c2dd582018-03-01 14:53:49 +0000213 output_path = os.path.join(
Darryl Green57838472019-04-04 14:39:33 +0100214 self.report_dir, "{}-{}-{}.dump".format(
215 mbed_module, version.revision, version.version
Darryl Greende118092019-02-27 16:53:40 +0000216 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000217 )
218 abi_dump_command = [
219 "abi-dumper",
Darryl Greenae5d66c2019-02-25 11:35:05 +0000220 module_path,
Darryl Green7c2dd582018-03-01 14:53:49 +0000221 "-o", output_path,
Darryl Green7381bea2019-03-05 16:25:38 +0000222 "-lver", version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000223 ]
224 abi_dump_process = subprocess.Popen(
225 abi_dump_command,
226 stdout=subprocess.PIPE,
227 stderr=subprocess.STDOUT
228 )
229 abi_dump_output, _ = abi_dump_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000230 self.log.debug(abi_dump_output.decode("utf-8"))
Darryl Green7c2dd582018-03-01 14:53:49 +0000231 if abi_dump_process.returncode != 0:
232 raise Exception("abi-dumper failed, aborting")
Darryl Green7381bea2019-03-05 16:25:38 +0000233 version.abi_dumps[mbed_module] = output_path
Darryl Green7c2dd582018-03-01 14:53:49 +0000234
Darryl Green88bfbc22019-03-05 16:30:39 +0000235 def _cleanup_worktree(self, git_worktree_path):
Gilles Peskine9df17632019-02-25 20:36:52 +0100236 """Remove the specified git worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000237 shutil.rmtree(git_worktree_path)
238 worktree_process = subprocess.Popen(
239 [self.git_command, "worktree", "prune"],
240 cwd=self.repo_path,
241 stdout=subprocess.PIPE,
242 stderr=subprocess.STDOUT
243 )
244 worktree_output, _ = worktree_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000245 self.log.debug(worktree_output.decode("utf-8"))
Darryl Green7c2dd582018-03-01 14:53:49 +0000246 if worktree_process.returncode != 0:
247 raise Exception("Worktree cleanup failed, aborting")
248
Darryl Green88bfbc22019-03-05 16:30:39 +0000249 def _get_abi_dump_for_ref(self, version):
Gilles Peskine9df17632019-02-25 20:36:52 +0100250 """Generate the ABI dumps for the specified git revision."""
Darryl Green88bfbc22019-03-05 16:30:39 +0000251 git_worktree_path = self._get_clean_worktree_for_git_revision(version)
252 self._update_git_submodules(git_worktree_path, version)
253 self._build_shared_libraries(git_worktree_path, version)
254 self._get_abi_dumps_from_shared_libraries(git_worktree_path, version)
255 self._cleanup_worktree(git_worktree_path)
Darryl Green7c2dd582018-03-01 14:53:49 +0000256
Darryl Green88bfbc22019-03-05 16:30:39 +0000257 def _remove_children_with_tag(self, parent, tag):
Darryl Green0da45782019-02-21 13:09:26 +0000258 children = parent.getchildren()
259 for child in children:
260 if child.tag == tag:
261 parent.remove(child)
262 else:
Darryl Green88bfbc22019-03-05 16:30:39 +0000263 self._remove_children_with_tag(child, tag)
Darryl Green0da45782019-02-21 13:09:26 +0000264
Darryl Green88bfbc22019-03-05 16:30:39 +0000265 def _remove_extra_detail_from_report(self, report_root):
Darryl Green0da45782019-02-21 13:09:26 +0000266 for tag in ['test_info', 'test_results', 'problem_summary',
267 'added_symbols', 'removed_symbols', 'affected']:
Darryl Green88bfbc22019-03-05 16:30:39 +0000268 self._remove_children_with_tag(report_root, tag)
Darryl Green0da45782019-02-21 13:09:26 +0000269
270 for report in report_root:
271 for problems in report.getchildren()[:]:
272 if not problems.getchildren():
273 report.remove(problems)
274
Darryl Green7c2dd582018-03-01 14:53:49 +0000275 def get_abi_compatibility_report(self):
Gilles Peskine9df17632019-02-25 20:36:52 +0100276 """Generate a report of the differences between the reference ABI
277 and the new ABI. ABI dumps from self.old_rev and self.new_rev must
278 be available."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000279 compatibility_report = ""
280 compliance_return_code = 0
Darryl Green7381bea2019-03-05 16:25:38 +0000281 shared_modules = list(set(self.old_version.modules.keys()) &
282 set(self.new_version.modules.keys()))
Darryl Greende118092019-02-27 16:53:40 +0000283 for mbed_module in shared_modules:
Darryl Green7c2dd582018-03-01 14:53:49 +0000284 output_path = os.path.join(
285 self.report_dir, "{}-{}-{}.html".format(
Darryl Green7381bea2019-03-05 16:25:38 +0000286 mbed_module, self.old_version.revision,
287 self.new_version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000288 )
289 )
290 abi_compliance_command = [
291 "abi-compliance-checker",
292 "-l", mbed_module,
Darryl Green7381bea2019-03-05 16:25:38 +0000293 "-old", self.old_version.abi_dumps[mbed_module],
294 "-new", self.new_version.abi_dumps[mbed_module],
Darryl Green7c2dd582018-03-01 14:53:49 +0000295 "-strict",
Darryl Green0da45782019-02-21 13:09:26 +0000296 "-report-path", output_path,
Darryl Green7c2dd582018-03-01 14:53:49 +0000297 ]
Darryl Green668063b2019-02-20 15:01:56 +0000298 if self.skip_file:
299 abi_compliance_command += ["-skip-symbols", self.skip_file,
300 "-skip-types", self.skip_file]
Darryl Green0da45782019-02-21 13:09:26 +0000301 if self.brief:
302 abi_compliance_command += ["-report-format", "xml",
303 "-stdout"]
Darryl Green7c2dd582018-03-01 14:53:49 +0000304 abi_compliance_process = subprocess.Popen(
305 abi_compliance_command,
306 stdout=subprocess.PIPE,
307 stderr=subprocess.STDOUT
308 )
309 abi_compliance_output, _ = abi_compliance_process.communicate()
Darryl Green7c2dd582018-03-01 14:53:49 +0000310 if abi_compliance_process.returncode == 0:
311 compatibility_report += (
312 "No compatibility issues for {}\n".format(mbed_module)
313 )
Darryl Green0da45782019-02-21 13:09:26 +0000314 if not (self.keep_all_reports or self.brief):
Darryl Green7c2dd582018-03-01 14:53:49 +0000315 os.remove(output_path)
316 elif abi_compliance_process.returncode == 1:
Darryl Green0da45782019-02-21 13:09:26 +0000317 if self.brief:
318 self.log.info(
319 "Compatibility issues found for {}".format(mbed_module)
320 )
321 report_root = ET.fromstring(abi_compliance_output.decode("utf-8"))
Darryl Green88bfbc22019-03-05 16:30:39 +0000322 self._remove_extra_detail_from_report(report_root)
Darryl Green0da45782019-02-21 13:09:26 +0000323 self.log.info(ET.tostring(report_root).decode("utf-8"))
324 else:
325 compliance_return_code = 1
326 self.can_remove_report_dir = False
327 compatibility_report += (
328 "Compatibility issues found for {}, "
329 "for details see {}\n".format(mbed_module, output_path)
330 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000331 else:
332 raise Exception(
333 "abi-compliance-checker failed with a return code of {},"
334 " aborting".format(abi_compliance_process.returncode)
335 )
Darryl Green7381bea2019-03-05 16:25:38 +0000336 os.remove(self.old_version.abi_dumps[mbed_module])
337 os.remove(self.new_version.abi_dumps[mbed_module])
Darryl Green131e24b2019-02-25 17:01:55 +0000338 if self.can_remove_report_dir:
Darryl Green7c2dd582018-03-01 14:53:49 +0000339 os.rmdir(self.report_dir)
340 self.log.info(compatibility_report)
341 return compliance_return_code
342
343 def check_for_abi_changes(self):
Gilles Peskine9df17632019-02-25 20:36:52 +0100344 """Generate a report of ABI differences
345 between self.old_rev and self.new_rev."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000346 self.check_repo_path()
347 self.check_abi_tools_are_installed()
Darryl Green88bfbc22019-03-05 16:30:39 +0000348 self._get_abi_dump_for_ref(self.old_version)
349 self._get_abi_dump_for_ref(self.new_version)
Darryl Green7c2dd582018-03-01 14:53:49 +0000350 return self.get_abi_compatibility_report()
351
352
353def run_main():
354 try:
355 parser = argparse.ArgumentParser(
356 description=(
Darryl Green418527b2018-04-16 12:02:29 +0100357 """This script is a small wrapper around the
358 abi-compliance-checker and abi-dumper tools, applying them
359 to compare the ABI and API of the library files from two
360 different Git revisions within an Mbed TLS repository.
Darryl Green0da45782019-02-21 13:09:26 +0000361 The results of the comparison are either formatted as HTML and
Darryl Green7c0e0522019-03-05 15:21:32 +0000362 stored at a configurable location, or are given as a brief list
363 of problems. Returns 0 on success, 1 on ABI/API non-compliance,
364 and 2 if there is an error while running the script.
365 Note: must be run from Mbed TLS root."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000366 )
367 )
368 parser.add_argument(
Darryl Green66025382019-03-08 11:30:04 +0000369 "-v", "--verbose", action="store_true",
370 help="set verbosity level",
371 )
372 parser.add_argument(
Darryl Green418527b2018-04-16 12:02:29 +0100373 "-r", "--report-dir", type=str, default="reports",
Darryl Green7c2dd582018-03-01 14:53:49 +0000374 help="directory where reports are stored, default is reports",
375 )
376 parser.add_argument(
Darryl Green418527b2018-04-16 12:02:29 +0100377 "-k", "--keep-all-reports", action="store_true",
Darryl Green7c2dd582018-03-01 14:53:49 +0000378 help="keep all reports, even if there are no compatibility issues",
379 )
380 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000381 "-o", "--old-rev", type=str, help="revision for old version.",
382 required=True,
Darryl Green7c2dd582018-03-01 14:53:49 +0000383 )
384 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000385 "-or", "--old-repo", type=str, help="repository for old version."
Darryl Greenae5d66c2019-02-25 11:35:05 +0000386 )
387 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000388 "-oc", "--old-crypto-rev", type=str,
389 help="revision for old crypto submodule."
Darryl Green7c2dd582018-03-01 14:53:49 +0000390 )
Darryl Green668063b2019-02-20 15:01:56 +0000391 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000392 "-ocr", "--old-crypto-repo", type=str,
393 help="repository for old crypto submodule."
394 )
395 parser.add_argument(
396 "-n", "--new-rev", type=str, help="revision for new version",
397 required=True,
398 )
399 parser.add_argument(
400 "-nr", "--new-repo", type=str, help="repository for new version."
401 )
402 parser.add_argument(
403 "-nc", "--new-crypto-rev", type=str,
404 help="revision for new crypto version"
405 )
406 parser.add_argument(
407 "-ncr", "--new-crypto-repo", type=str,
408 help="repository for new crypto submodule."
Darryl Greenae5d66c2019-02-25 11:35:05 +0000409 )
410 parser.add_argument(
Darryl Green668063b2019-02-20 15:01:56 +0000411 "-s", "--skip-file", type=str,
412 help="path to file containing symbols and types to skip"
413 )
Darryl Green0da45782019-02-21 13:09:26 +0000414 parser.add_argument(
415 "-b", "--brief", action="store_true",
416 help="output only the list of issues to stdout, instead of a full report",
417 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000418 abi_args = parser.parse_args()
Darryl Green7381bea2019-03-05 16:25:38 +0000419 old_version = RepoVersion("old", abi_args.old_repo, abi_args.old_rev,
420 abi_args.old_crypto_repo, abi_args.old_crypto_rev)
421 new_version = RepoVersion("new", abi_args.new_repo, abi_args.new_rev,
422 abi_args.new_crypto_repo, abi_args.new_crypto_rev)
Darryl Green7c2dd582018-03-01 14:53:49 +0000423 abi_check = AbiChecker(
Darryl Green66025382019-03-08 11:30:04 +0000424 abi_args.verbose, old_version, new_version, abi_args.report_dir,
Darryl Green7381bea2019-03-05 16:25:38 +0000425 abi_args.keep_all_reports, abi_args.brief, abi_args.skip_file
Darryl Green7c2dd582018-03-01 14:53:49 +0000426 )
427 return_code = abi_check.check_for_abi_changes()
428 sys.exit(return_code)
Gilles Peskineafd19dd2019-02-25 21:39:42 +0100429 except Exception: # pylint: disable=broad-except
430 # Print the backtrace and exit explicitly so as to exit with
431 # status 2, not 1.
Darryl Greena6f430f2018-03-15 10:12:06 +0000432 traceback.print_exc()
Darryl Green7c2dd582018-03-01 14:53:49 +0000433 sys.exit(2)
434
435
436if __name__ == "__main__":
437 run_main()