blob: d23b038eab32977e1dc98dfb87f945bad2285863 [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 Greene62f9bb2019-02-21 13:09:26 +000012The results of the comparison are either formatted as HTML and stored at
Darryl Green4cde8a02019-03-05 15:21:32 +000013a configurable location, or are given as a brief list of problems.
Darryl Greene62f9bb2019-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 Green9f357d62019-02-25 11:35:05 +000026import fnmatch
Darryl Green7c2dd582018-03-01 14:53:49 +000027
Darryl Greene62f9bb2019-02-21 13:09:26 +000028import xml.etree.ElementTree as ET
29
Darryl Green7c2dd582018-03-01 14:53:49 +000030
Darryl Green7c1a7332019-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 Peskine712afa72019-02-25 20:36:52 +010053 """API and ABI checker."""
Darryl Green7c2dd582018-03-01 14:53:49 +000054
Darryl Green7c1a7332019-03-05 16:25:38 +000055 def __init__(self, old_version, new_version, report_dir,
56 keep_all_reports, brief, skip_file=None):
Gilles Peskine712afa72019-02-25 20:36:52 +010057 """Instantiate the API/ABI checker.
58
Darryl Green7c1a7332019-03-05 16:25:38 +000059 old_version: RepoVersion containing details to compare against
60 new_version: RepoVersion containing details to check
Gilles Peskine712afa72019-02-25 20:36:52 +010061 report_dir: directory for output files
Gilles Peskine712afa72019-02-25 20:36:52 +010062 keep_all_reports: if false, delete old reports
Darryl Greene62f9bb2019-02-21 13:09:26 +000063 brief: if true, output shorter report to stdout
Darryl Greenc2883a22019-02-20 15:01:56 +000064 skip_file: path to file containing symbols and types to skip
Gilles Peskine712afa72019-02-25 20:36:52 +010065 """
Darryl Green7c2dd582018-03-01 14:53:49 +000066 self.repo_path = "."
67 self.log = None
Darryl Green3a5f6c82019-03-05 16:30:39 +000068 self._setup_logger()
Darryl Green7c2dd582018-03-01 14:53:49 +000069 self.report_dir = os.path.abspath(report_dir)
70 self.keep_all_reports = keep_all_reports
Darryl Green3d3d5522019-02-25 17:01:55 +000071 self.can_remove_report_dir = not (os.path.isdir(self.report_dir) or
72 keep_all_reports)
Darryl Green7c1a7332019-03-05 16:25:38 +000073 self.old_version = old_version
74 self.new_version = new_version
Darryl Greenc2883a22019-02-20 15:01:56 +000075 self.skip_file = skip_file
Darryl Greene62f9bb2019-02-21 13:09:26 +000076 self.brief = brief
Darryl Green7c2dd582018-03-01 14:53:49 +000077 self.git_command = "git"
78 self.make_command = "make"
79
Gilles Peskine712afa72019-02-25 20:36:52 +010080 @staticmethod
81 def check_repo_path():
Darryl Greena6f430f2018-03-15 10:12:06 +000082 current_dir = os.path.realpath('.')
83 root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
84 if current_dir != root_dir:
Darryl Green7c2dd582018-03-01 14:53:49 +000085 raise Exception("Must be run from Mbed TLS root")
86
Darryl Green3a5f6c82019-03-05 16:30:39 +000087 def _setup_logger(self):
Darryl Green7c2dd582018-03-01 14:53:49 +000088 self.log = logging.getLogger()
89 self.log.setLevel(logging.INFO)
90 self.log.addHandler(logging.StreamHandler())
91
Gilles Peskine712afa72019-02-25 20:36:52 +010092 @staticmethod
93 def check_abi_tools_are_installed():
Darryl Green7c2dd582018-03-01 14:53:49 +000094 for command in ["abi-dumper", "abi-compliance-checker"]:
95 if not shutil.which(command):
96 raise Exception("{} not installed, aborting".format(command))
97
Darryl Green3a5f6c82019-03-05 16:30:39 +000098 def _get_clean_worktree_for_git_revision(self, version):
Darryl Green7c1a7332019-03-05 16:25:38 +000099 """Make a separate worktree with version.revision checked out.
Gilles Peskine712afa72019-02-25 20:36:52 +0100100 Do not modify the current worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000101 git_worktree_path = tempfile.mkdtemp()
Darryl Green7c1a7332019-03-05 16:25:38 +0000102 if version.repository:
Darryl Greenda84e322019-02-19 16:59:33 +0000103 self.log.info(
104 "Checking out git worktree for revision {} from {}".format(
Darryl Green7c1a7332019-03-05 16:25:38 +0000105 version.revision, version.repository
Darryl Greenda84e322019-02-19 16:59:33 +0000106 )
107 )
108 fetch_process = subprocess.Popen(
Darryl Green7c1a7332019-03-05 16:25:38 +0000109 [self.git_command, "fetch",
110 version.repository, version.revision],
Darryl Greenda84e322019-02-19 16:59:33 +0000111 cwd=self.repo_path,
112 stdout=subprocess.PIPE,
113 stderr=subprocess.STDOUT
114 )
115 fetch_output, _ = fetch_process.communicate()
116 self.log.info(fetch_output.decode("utf-8"))
117 if fetch_process.returncode != 0:
118 raise Exception("Fetching revision failed, aborting")
119 worktree_rev = "FETCH_HEAD"
120 else:
Darryl Green7c1a7332019-03-05 16:25:38 +0000121 self.log.info("Checking out git worktree for revision {}".format(
122 version.revision
123 ))
124 worktree_rev = version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000125 worktree_process = subprocess.Popen(
Darryl Greenda84e322019-02-19 16:59:33 +0000126 [self.git_command, "worktree", "add", "--detach",
127 git_worktree_path, worktree_rev],
Darryl Green7c2dd582018-03-01 14:53:49 +0000128 cwd=self.repo_path,
129 stdout=subprocess.PIPE,
130 stderr=subprocess.STDOUT
131 )
132 worktree_output, _ = worktree_process.communicate()
133 self.log.info(worktree_output.decode("utf-8"))
134 if worktree_process.returncode != 0:
135 raise Exception("Checking out worktree failed, aborting")
136 return git_worktree_path
137
Darryl Green3a5f6c82019-03-05 16:30:39 +0000138 def _update_git_submodules(self, git_worktree_path, version):
Jaeden Ameroffeb1b82018-11-02 16:35:09 +0000139 process = subprocess.Popen(
140 [self.git_command, "submodule", "update", "--init", '--recursive'],
141 cwd=git_worktree_path,
142 stdout=subprocess.PIPE,
143 stderr=subprocess.STDOUT
144 )
145 output, _ = process.communicate()
146 self.log.info(output.decode("utf-8"))
147 if process.returncode != 0:
148 raise Exception("git submodule update failed, aborting")
Darryl Greene29ce702019-03-05 15:23:25 +0000149 if not (os.path.exists(os.path.join(git_worktree_path, "crypto"))
Darryl Green7c1a7332019-03-05 16:25:38 +0000150 and version.crypto_revision):
Darryl Greene29ce702019-03-05 15:23:25 +0000151 return
152
Darryl Green7c1a7332019-03-05 16:25:38 +0000153 if version.crypto_repository:
Darryl Green1d95c532019-03-08 11:12:19 +0000154 fetch_process = subprocess.Popen(
155 [self.git_command, "fetch", version.crypto_repository,
156 version.crypto_revision],
Darryl Greene29ce702019-03-05 15:23:25 +0000157 cwd=os.path.join(git_worktree_path, "crypto"),
158 stdout=subprocess.PIPE,
159 stderr=subprocess.STDOUT
160 )
Darryl Green1d95c532019-03-08 11:12:19 +0000161 fetch_output, _ = fetch_process.communicate()
162 self.log.info(fetch_output.decode("utf-8"))
163 if fetch_process.returncode != 0:
164 raise Exception("git fetch failed, aborting")
165 crypto_rev = "FETCH_HEAD"
166 else:
167 crypto_rev = version.crypto_revision
168
169 checkout_process = subprocess.Popen(
170 [self.git_command, "checkout", crypto_rev],
171 cwd=os.path.join(git_worktree_path, "crypto"),
172 stdout=subprocess.PIPE,
173 stderr=subprocess.STDOUT
174 )
175 checkout_output, _ = checkout_process.communicate()
176 self.log.info(checkout_output.decode("utf-8"))
177 if checkout_process.returncode != 0:
178 raise Exception("git checkout failed, aborting")
Jaeden Ameroffeb1b82018-11-02 16:35:09 +0000179
Darryl Green3a5f6c82019-03-05 16:30:39 +0000180 def _build_shared_libraries(self, git_worktree_path, version):
Gilles Peskine712afa72019-02-25 20:36:52 +0100181 """Build the shared libraries in the specified worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000182 my_environment = os.environ.copy()
183 my_environment["CFLAGS"] = "-g -Og"
184 my_environment["SHARED"] = "1"
Darryl Green9f357d62019-02-25 11:35:05 +0000185 my_environment["USE_CRYPTO_SUBMODULE"] = "1"
Darryl Green7c2dd582018-03-01 14:53:49 +0000186 make_process = subprocess.Popen(
Darryl Greenddf25a62019-02-28 11:52:39 +0000187 [self.make_command, "lib"],
Darryl Green7c2dd582018-03-01 14:53:49 +0000188 env=my_environment,
189 cwd=git_worktree_path,
190 stdout=subprocess.PIPE,
191 stderr=subprocess.STDOUT
192 )
193 make_output, _ = make_process.communicate()
194 self.log.info(make_output.decode("utf-8"))
Darryl Green9f357d62019-02-25 11:35:05 +0000195 for root, dirs, files in os.walk(git_worktree_path):
196 for file in fnmatch.filter(files, "*.so"):
Darryl Green7c1a7332019-03-05 16:25:38 +0000197 version.modules[os.path.splitext(file)[0]] = (
Darryl Green3e7a9802019-02-27 16:53:40 +0000198 os.path.join(root, file)
Darryl Green9f357d62019-02-25 11:35:05 +0000199 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000200 if make_process.returncode != 0:
201 raise Exception("make failed, aborting")
202
Darryl Green3a5f6c82019-03-05 16:30:39 +0000203 def _get_abi_dumps_from_shared_libraries(self, git_worktree_path,
204 version):
Gilles Peskine712afa72019-02-25 20:36:52 +0100205 """Generate the ABI dumps for the specified git revision.
206 It must be checked out in git_worktree_path and the shared libraries
207 must have been built."""
Darryl Green7c1a7332019-03-05 16:25:38 +0000208 for mbed_module, module_path in version.modules.items():
Darryl Green7c2dd582018-03-01 14:53:49 +0000209 output_path = os.path.join(
Darryl Green7c1a7332019-03-05 16:25:38 +0000210 self.report_dir, version.version, "{}-{}.dump".format(
211 mbed_module, version.revision
Darryl Green3e7a9802019-02-27 16:53:40 +0000212 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000213 )
214 abi_dump_command = [
215 "abi-dumper",
Darryl Green9f357d62019-02-25 11:35:05 +0000216 module_path,
Darryl Green7c2dd582018-03-01 14:53:49 +0000217 "-o", output_path,
Darryl Green7c1a7332019-03-05 16:25:38 +0000218 "-lver", version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000219 ]
220 abi_dump_process = subprocess.Popen(
221 abi_dump_command,
222 stdout=subprocess.PIPE,
223 stderr=subprocess.STDOUT
224 )
225 abi_dump_output, _ = abi_dump_process.communicate()
226 self.log.info(abi_dump_output.decode("utf-8"))
227 if abi_dump_process.returncode != 0:
228 raise Exception("abi-dumper failed, aborting")
Darryl Green7c1a7332019-03-05 16:25:38 +0000229 version.abi_dumps[mbed_module] = output_path
Darryl Green7c2dd582018-03-01 14:53:49 +0000230
Darryl Green3a5f6c82019-03-05 16:30:39 +0000231 def _cleanup_worktree(self, git_worktree_path):
Gilles Peskine712afa72019-02-25 20:36:52 +0100232 """Remove the specified git worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000233 shutil.rmtree(git_worktree_path)
234 worktree_process = subprocess.Popen(
235 [self.git_command, "worktree", "prune"],
236 cwd=self.repo_path,
237 stdout=subprocess.PIPE,
238 stderr=subprocess.STDOUT
239 )
240 worktree_output, _ = worktree_process.communicate()
241 self.log.info(worktree_output.decode("utf-8"))
242 if worktree_process.returncode != 0:
243 raise Exception("Worktree cleanup failed, aborting")
244
Darryl Green3a5f6c82019-03-05 16:30:39 +0000245 def _get_abi_dump_for_ref(self, version):
Gilles Peskine712afa72019-02-25 20:36:52 +0100246 """Generate the ABI dumps for the specified git revision."""
Darryl Green3a5f6c82019-03-05 16:30:39 +0000247 git_worktree_path = self._get_clean_worktree_for_git_revision(version)
248 self._update_git_submodules(git_worktree_path, version)
249 self._build_shared_libraries(git_worktree_path, version)
250 self._get_abi_dumps_from_shared_libraries(git_worktree_path, version)
251 self._cleanup_worktree(git_worktree_path)
Darryl Green7c2dd582018-03-01 14:53:49 +0000252
Darryl Green3a5f6c82019-03-05 16:30:39 +0000253 def _remove_children_with_tag(self, parent, tag):
Darryl Greene62f9bb2019-02-21 13:09:26 +0000254 children = parent.getchildren()
255 for child in children:
256 if child.tag == tag:
257 parent.remove(child)
258 else:
Darryl Green3a5f6c82019-03-05 16:30:39 +0000259 self._remove_children_with_tag(child, tag)
Darryl Greene62f9bb2019-02-21 13:09:26 +0000260
Darryl Green3a5f6c82019-03-05 16:30:39 +0000261 def _remove_extra_detail_from_report(self, report_root):
Darryl Greene62f9bb2019-02-21 13:09:26 +0000262 for tag in ['test_info', 'test_results', 'problem_summary',
263 'added_symbols', 'removed_symbols', 'affected']:
Darryl Green3a5f6c82019-03-05 16:30:39 +0000264 self._remove_children_with_tag(report_root, tag)
Darryl Greene62f9bb2019-02-21 13:09:26 +0000265
266 for report in report_root:
267 for problems in report.getchildren()[:]:
268 if not problems.getchildren():
269 report.remove(problems)
270
Darryl Green7c2dd582018-03-01 14:53:49 +0000271 def get_abi_compatibility_report(self):
Gilles Peskine712afa72019-02-25 20:36:52 +0100272 """Generate a report of the differences between the reference ABI
273 and the new ABI. ABI dumps from self.old_rev and self.new_rev must
274 be available."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000275 compatibility_report = ""
276 compliance_return_code = 0
Darryl Green7c1a7332019-03-05 16:25:38 +0000277 shared_modules = list(set(self.old_version.modules.keys()) &
278 set(self.new_version.modules.keys()))
Darryl Green3e7a9802019-02-27 16:53:40 +0000279 for mbed_module in shared_modules:
Darryl Green7c2dd582018-03-01 14:53:49 +0000280 output_path = os.path.join(
281 self.report_dir, "{}-{}-{}.html".format(
Darryl Green7c1a7332019-03-05 16:25:38 +0000282 mbed_module, self.old_version.revision,
283 self.new_version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000284 )
285 )
286 abi_compliance_command = [
287 "abi-compliance-checker",
288 "-l", mbed_module,
Darryl Green7c1a7332019-03-05 16:25:38 +0000289 "-old", self.old_version.abi_dumps[mbed_module],
290 "-new", self.new_version.abi_dumps[mbed_module],
Darryl Green7c2dd582018-03-01 14:53:49 +0000291 "-strict",
Darryl Greene62f9bb2019-02-21 13:09:26 +0000292 "-report-path", output_path,
Darryl Green7c2dd582018-03-01 14:53:49 +0000293 ]
Darryl Greenc2883a22019-02-20 15:01:56 +0000294 if self.skip_file:
295 abi_compliance_command += ["-skip-symbols", self.skip_file,
296 "-skip-types", self.skip_file]
Darryl Greene62f9bb2019-02-21 13:09:26 +0000297 if self.brief:
298 abi_compliance_command += ["-report-format", "xml",
299 "-stdout"]
Darryl Green7c2dd582018-03-01 14:53:49 +0000300 abi_compliance_process = subprocess.Popen(
301 abi_compliance_command,
302 stdout=subprocess.PIPE,
303 stderr=subprocess.STDOUT
304 )
305 abi_compliance_output, _ = abi_compliance_process.communicate()
Darryl Green7c2dd582018-03-01 14:53:49 +0000306 if abi_compliance_process.returncode == 0:
307 compatibility_report += (
308 "No compatibility issues for {}\n".format(mbed_module)
309 )
Darryl Greene62f9bb2019-02-21 13:09:26 +0000310 if not (self.keep_all_reports or self.brief):
Darryl Green7c2dd582018-03-01 14:53:49 +0000311 os.remove(output_path)
312 elif abi_compliance_process.returncode == 1:
Darryl Greene62f9bb2019-02-21 13:09:26 +0000313 if self.brief:
314 self.log.info(
315 "Compatibility issues found for {}".format(mbed_module)
316 )
317 report_root = ET.fromstring(abi_compliance_output.decode("utf-8"))
Darryl Green3a5f6c82019-03-05 16:30:39 +0000318 self._remove_extra_detail_from_report(report_root)
Darryl Greene62f9bb2019-02-21 13:09:26 +0000319 self.log.info(ET.tostring(report_root).decode("utf-8"))
320 else:
321 compliance_return_code = 1
322 self.can_remove_report_dir = False
323 compatibility_report += (
324 "Compatibility issues found for {}, "
325 "for details see {}\n".format(mbed_module, output_path)
326 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000327 else:
328 raise Exception(
329 "abi-compliance-checker failed with a return code of {},"
330 " aborting".format(abi_compliance_process.returncode)
331 )
Darryl Green7c1a7332019-03-05 16:25:38 +0000332 os.remove(self.old_version.abi_dumps[mbed_module])
333 os.remove(self.new_version.abi_dumps[mbed_module])
Darryl Green3d3d5522019-02-25 17:01:55 +0000334 if self.can_remove_report_dir:
Darryl Green7c2dd582018-03-01 14:53:49 +0000335 os.rmdir(self.report_dir)
336 self.log.info(compatibility_report)
337 return compliance_return_code
338
339 def check_for_abi_changes(self):
Gilles Peskine712afa72019-02-25 20:36:52 +0100340 """Generate a report of ABI differences
341 between self.old_rev and self.new_rev."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000342 self.check_repo_path()
343 self.check_abi_tools_are_installed()
Darryl Green3a5f6c82019-03-05 16:30:39 +0000344 self._get_abi_dump_for_ref(self.old_version)
345 self._get_abi_dump_for_ref(self.new_version)
Darryl Green7c2dd582018-03-01 14:53:49 +0000346 return self.get_abi_compatibility_report()
347
348
349def run_main():
350 try:
351 parser = argparse.ArgumentParser(
352 description=(
Darryl Green418527b2018-04-16 12:02:29 +0100353 """This script is a small wrapper around the
354 abi-compliance-checker and abi-dumper tools, applying them
355 to compare the ABI and API of the library files from two
356 different Git revisions within an Mbed TLS repository.
Darryl Greene62f9bb2019-02-21 13:09:26 +0000357 The results of the comparison are either formatted as HTML and
Darryl Green4cde8a02019-03-05 15:21:32 +0000358 stored at a configurable location, or are given as a brief list
359 of problems. Returns 0 on success, 1 on ABI/API non-compliance,
360 and 2 if there is an error while running the script.
361 Note: must be run from Mbed TLS root."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000362 )
363 )
364 parser.add_argument(
Darryl Green418527b2018-04-16 12:02:29 +0100365 "-r", "--report-dir", type=str, default="reports",
Darryl Green7c2dd582018-03-01 14:53:49 +0000366 help="directory where reports are stored, default is reports",
367 )
368 parser.add_argument(
Darryl Green418527b2018-04-16 12:02:29 +0100369 "-k", "--keep-all-reports", action="store_true",
Darryl Green7c2dd582018-03-01 14:53:49 +0000370 help="keep all reports, even if there are no compatibility issues",
371 )
372 parser.add_argument(
Darryl Greenc5132ff2019-03-01 09:54:44 +0000373 "-o", "--old-rev", type=str, help="revision for old version.",
374 required=True,
Darryl Green7c2dd582018-03-01 14:53:49 +0000375 )
376 parser.add_argument(
Darryl Greenc5132ff2019-03-01 09:54:44 +0000377 "-or", "--old-repo", type=str, help="repository for old version."
Darryl Green9f357d62019-02-25 11:35:05 +0000378 )
379 parser.add_argument(
Darryl Greenc5132ff2019-03-01 09:54:44 +0000380 "-oc", "--old-crypto-rev", type=str,
381 help="revision for old crypto submodule."
Darryl Green7c2dd582018-03-01 14:53:49 +0000382 )
Darryl Greenc2883a22019-02-20 15:01:56 +0000383 parser.add_argument(
Darryl Greenc5132ff2019-03-01 09:54:44 +0000384 "-ocr", "--old-crypto-repo", type=str,
385 help="repository for old crypto submodule."
386 )
387 parser.add_argument(
388 "-n", "--new-rev", type=str, help="revision for new version",
389 required=True,
390 )
391 parser.add_argument(
392 "-nr", "--new-repo", type=str, help="repository for new version."
393 )
394 parser.add_argument(
395 "-nc", "--new-crypto-rev", type=str,
396 help="revision for new crypto version"
397 )
398 parser.add_argument(
399 "-ncr", "--new-crypto-repo", type=str,
400 help="repository for new crypto submodule."
Darryl Green9f357d62019-02-25 11:35:05 +0000401 )
402 parser.add_argument(
Darryl Greenc2883a22019-02-20 15:01:56 +0000403 "-s", "--skip-file", type=str,
404 help="path to file containing symbols and types to skip"
405 )
Darryl Greene62f9bb2019-02-21 13:09:26 +0000406 parser.add_argument(
407 "-b", "--brief", action="store_true",
408 help="output only the list of issues to stdout, instead of a full report",
409 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000410 abi_args = parser.parse_args()
Darryl Green7c1a7332019-03-05 16:25:38 +0000411 old_version = RepoVersion("old", abi_args.old_repo, abi_args.old_rev,
412 abi_args.old_crypto_repo, abi_args.old_crypto_rev)
413 new_version = RepoVersion("new", abi_args.new_repo, abi_args.new_rev,
414 abi_args.new_crypto_repo, abi_args.new_crypto_rev)
Darryl Green7c2dd582018-03-01 14:53:49 +0000415 abi_check = AbiChecker(
Darryl Green7c1a7332019-03-05 16:25:38 +0000416 old_version, new_version, abi_args.report_dir,
417 abi_args.keep_all_reports, abi_args.brief, abi_args.skip_file
Darryl Green7c2dd582018-03-01 14:53:49 +0000418 )
419 return_code = abi_check.check_for_abi_changes()
420 sys.exit(return_code)
Gilles Peskinee915d532019-02-25 21:39:42 +0100421 except Exception: # pylint: disable=broad-except
422 # Print the backtrace and exit explicitly so as to exit with
423 # status 2, not 1.
Darryl Greena6f430f2018-03-15 10:12:06 +0000424 traceback.print_exc()
Darryl Green7c2dd582018-03-01 14:53:49 +0000425 sys.exit(2)
426
427
428if __name__ == "__main__":
429 run_main()