blob: 9f99309af43cc9d6642fd7399db6763d302f74d8 [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):
Darryl Green26dff8e2019-04-05 17:06:17 +0100143 """If the crypto submodule is present, initialize it.
144 if version.crypto_revision exists, update it to that revision,
145 otherwise update it to the default revision"""
Jaeden Amero4cd4b4b2018-11-02 16:35:09 +0000146 process = subprocess.Popen(
147 [self.git_command, "submodule", "update", "--init", '--recursive'],
148 cwd=git_worktree_path,
149 stdout=subprocess.PIPE,
150 stderr=subprocess.STDOUT
151 )
152 output, _ = process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000153 self.log.debug(output.decode("utf-8"))
Jaeden Amero4cd4b4b2018-11-02 16:35:09 +0000154 if process.returncode != 0:
155 raise Exception("git submodule update failed, aborting")
Darryl Green0478a322019-03-05 15:23:25 +0000156 if not (os.path.exists(os.path.join(git_worktree_path, "crypto"))
Darryl Green7381bea2019-03-05 16:25:38 +0000157 and version.crypto_revision):
Darryl Green0478a322019-03-05 15:23:25 +0000158 return
159
Darryl Green7381bea2019-03-05 16:25:38 +0000160 if version.crypto_repository:
Darryl Green3f742982019-03-08 11:12:19 +0000161 fetch_process = subprocess.Popen(
162 [self.git_command, "fetch", version.crypto_repository,
163 version.crypto_revision],
Darryl Green0478a322019-03-05 15:23:25 +0000164 cwd=os.path.join(git_worktree_path, "crypto"),
165 stdout=subprocess.PIPE,
166 stderr=subprocess.STDOUT
167 )
Darryl Green3f742982019-03-08 11:12:19 +0000168 fetch_output, _ = fetch_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000169 self.log.debug(fetch_output.decode("utf-8"))
Darryl Green3f742982019-03-08 11:12:19 +0000170 if fetch_process.returncode != 0:
171 raise Exception("git fetch failed, aborting")
172 crypto_rev = "FETCH_HEAD"
173 else:
174 crypto_rev = version.crypto_revision
175
176 checkout_process = subprocess.Popen(
177 [self.git_command, "checkout", crypto_rev],
178 cwd=os.path.join(git_worktree_path, "crypto"),
179 stdout=subprocess.PIPE,
180 stderr=subprocess.STDOUT
181 )
182 checkout_output, _ = checkout_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000183 self.log.debug(checkout_output.decode("utf-8"))
Darryl Green3f742982019-03-08 11:12:19 +0000184 if checkout_process.returncode != 0:
185 raise Exception("git checkout failed, aborting")
Jaeden Amero4cd4b4b2018-11-02 16:35:09 +0000186
Darryl Green88bfbc22019-03-05 16:30:39 +0000187 def _build_shared_libraries(self, git_worktree_path, version):
Gilles Peskine9df17632019-02-25 20:36:52 +0100188 """Build the shared libraries in the specified worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000189 my_environment = os.environ.copy()
190 my_environment["CFLAGS"] = "-g -Og"
191 my_environment["SHARED"] = "1"
Darryl Greenae5d66c2019-02-25 11:35:05 +0000192 my_environment["USE_CRYPTO_SUBMODULE"] = "1"
Darryl Green7c2dd582018-03-01 14:53:49 +0000193 make_process = subprocess.Popen(
Darryl Greenc8e6ad42019-02-28 11:52:39 +0000194 [self.make_command, "lib"],
Darryl Green7c2dd582018-03-01 14:53:49 +0000195 env=my_environment,
196 cwd=git_worktree_path,
197 stdout=subprocess.PIPE,
198 stderr=subprocess.STDOUT
199 )
200 make_output, _ = make_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000201 self.log.debug(make_output.decode("utf-8"))
Darryl Green26dff8e2019-04-05 17:06:17 +0100202 for root, dirs, files in os.walk(git_worktree_path): # pylint: disable=unused-variable
Darryl Greenae5d66c2019-02-25 11:35:05 +0000203 for file in fnmatch.filter(files, "*.so"):
Darryl Green7381bea2019-03-05 16:25:38 +0000204 version.modules[os.path.splitext(file)[0]] = (
Darryl Greende118092019-02-27 16:53:40 +0000205 os.path.join(root, file)
Darryl Greenae5d66c2019-02-25 11:35:05 +0000206 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000207 if make_process.returncode != 0:
208 raise Exception("make failed, aborting")
209
Darryl Green26dff8e2019-04-05 17:06:17 +0100210 def _get_abi_dumps_from_shared_libraries(self, version):
Gilles Peskine9df17632019-02-25 20:36:52 +0100211 """Generate the ABI dumps for the specified git revision.
Darryl Green26dff8e2019-04-05 17:06:17 +0100212 The shared libraries must have been built and the module paths
213 present in version.modules."""
Darryl Green7381bea2019-03-05 16:25:38 +0000214 for mbed_module, module_path in version.modules.items():
Darryl Green7c2dd582018-03-01 14:53:49 +0000215 output_path = os.path.join(
Darryl Green57838472019-04-04 14:39:33 +0100216 self.report_dir, "{}-{}-{}.dump".format(
217 mbed_module, version.revision, version.version
Darryl Greende118092019-02-27 16:53:40 +0000218 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000219 )
220 abi_dump_command = [
221 "abi-dumper",
Darryl Greenae5d66c2019-02-25 11:35:05 +0000222 module_path,
Darryl Green7c2dd582018-03-01 14:53:49 +0000223 "-o", output_path,
Darryl Green7381bea2019-03-05 16:25:38 +0000224 "-lver", version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000225 ]
226 abi_dump_process = subprocess.Popen(
227 abi_dump_command,
228 stdout=subprocess.PIPE,
229 stderr=subprocess.STDOUT
230 )
231 abi_dump_output, _ = abi_dump_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000232 self.log.debug(abi_dump_output.decode("utf-8"))
Darryl Green7c2dd582018-03-01 14:53:49 +0000233 if abi_dump_process.returncode != 0:
234 raise Exception("abi-dumper failed, aborting")
Darryl Green7381bea2019-03-05 16:25:38 +0000235 version.abi_dumps[mbed_module] = output_path
Darryl Green7c2dd582018-03-01 14:53:49 +0000236
Darryl Green88bfbc22019-03-05 16:30:39 +0000237 def _cleanup_worktree(self, git_worktree_path):
Gilles Peskine9df17632019-02-25 20:36:52 +0100238 """Remove the specified git worktree."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000239 shutil.rmtree(git_worktree_path)
240 worktree_process = subprocess.Popen(
241 [self.git_command, "worktree", "prune"],
242 cwd=self.repo_path,
243 stdout=subprocess.PIPE,
244 stderr=subprocess.STDOUT
245 )
246 worktree_output, _ = worktree_process.communicate()
Darryl Green66025382019-03-08 11:30:04 +0000247 self.log.debug(worktree_output.decode("utf-8"))
Darryl Green7c2dd582018-03-01 14:53:49 +0000248 if worktree_process.returncode != 0:
249 raise Exception("Worktree cleanup failed, aborting")
250
Darryl Green88bfbc22019-03-05 16:30:39 +0000251 def _get_abi_dump_for_ref(self, version):
Gilles Peskine9df17632019-02-25 20:36:52 +0100252 """Generate the ABI dumps for the specified git revision."""
Darryl Green88bfbc22019-03-05 16:30:39 +0000253 git_worktree_path = self._get_clean_worktree_for_git_revision(version)
254 self._update_git_submodules(git_worktree_path, version)
255 self._build_shared_libraries(git_worktree_path, version)
Darryl Green26dff8e2019-04-05 17:06:17 +0100256 self._get_abi_dumps_from_shared_libraries(version)
Darryl Green88bfbc22019-03-05 16:30:39 +0000257 self._cleanup_worktree(git_worktree_path)
Darryl Green7c2dd582018-03-01 14:53:49 +0000258
Darryl Green88bfbc22019-03-05 16:30:39 +0000259 def _remove_children_with_tag(self, parent, tag):
Darryl Green0da45782019-02-21 13:09:26 +0000260 children = parent.getchildren()
261 for child in children:
262 if child.tag == tag:
263 parent.remove(child)
264 else:
Darryl Green88bfbc22019-03-05 16:30:39 +0000265 self._remove_children_with_tag(child, tag)
Darryl Green0da45782019-02-21 13:09:26 +0000266
Darryl Green88bfbc22019-03-05 16:30:39 +0000267 def _remove_extra_detail_from_report(self, report_root):
Darryl Green0da45782019-02-21 13:09:26 +0000268 for tag in ['test_info', 'test_results', 'problem_summary',
Darryl Green26dff8e2019-04-05 17:06:17 +0100269 'added_symbols', 'removed_symbols', 'affected']:
Darryl Green88bfbc22019-03-05 16:30:39 +0000270 self._remove_children_with_tag(report_root, tag)
Darryl Green0da45782019-02-21 13:09:26 +0000271
272 for report in report_root:
273 for problems in report.getchildren()[:]:
274 if not problems.getchildren():
275 report.remove(problems)
276
Darryl Green7c2dd582018-03-01 14:53:49 +0000277 def get_abi_compatibility_report(self):
Gilles Peskine9df17632019-02-25 20:36:52 +0100278 """Generate a report of the differences between the reference ABI
Darryl Green26dff8e2019-04-05 17:06:17 +0100279 and the new ABI. ABI dumps from self.old_version and self.new_version
280 must be available."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000281 compatibility_report = ""
282 compliance_return_code = 0
Darryl Green7381bea2019-03-05 16:25:38 +0000283 shared_modules = list(set(self.old_version.modules.keys()) &
284 set(self.new_version.modules.keys()))
Darryl Greende118092019-02-27 16:53:40 +0000285 for mbed_module in shared_modules:
Darryl Green7c2dd582018-03-01 14:53:49 +0000286 output_path = os.path.join(
287 self.report_dir, "{}-{}-{}.html".format(
Darryl Green7381bea2019-03-05 16:25:38 +0000288 mbed_module, self.old_version.revision,
289 self.new_version.revision
Darryl Green7c2dd582018-03-01 14:53:49 +0000290 )
291 )
292 abi_compliance_command = [
293 "abi-compliance-checker",
294 "-l", mbed_module,
Darryl Green7381bea2019-03-05 16:25:38 +0000295 "-old", self.old_version.abi_dumps[mbed_module],
296 "-new", self.new_version.abi_dumps[mbed_module],
Darryl Green7c2dd582018-03-01 14:53:49 +0000297 "-strict",
Darryl Green0da45782019-02-21 13:09:26 +0000298 "-report-path", output_path,
Darryl Green7c2dd582018-03-01 14:53:49 +0000299 ]
Darryl Green668063b2019-02-20 15:01:56 +0000300 if self.skip_file:
301 abi_compliance_command += ["-skip-symbols", self.skip_file,
302 "-skip-types", self.skip_file]
Darryl Green0da45782019-02-21 13:09:26 +0000303 if self.brief:
304 abi_compliance_command += ["-report-format", "xml",
305 "-stdout"]
Darryl Green7c2dd582018-03-01 14:53:49 +0000306 abi_compliance_process = subprocess.Popen(
307 abi_compliance_command,
308 stdout=subprocess.PIPE,
309 stderr=subprocess.STDOUT
310 )
311 abi_compliance_output, _ = abi_compliance_process.communicate()
Darryl Green7c2dd582018-03-01 14:53:49 +0000312 if abi_compliance_process.returncode == 0:
313 compatibility_report += (
314 "No compatibility issues for {}\n".format(mbed_module)
315 )
Darryl Green0da45782019-02-21 13:09:26 +0000316 if not (self.keep_all_reports or self.brief):
Darryl Green7c2dd582018-03-01 14:53:49 +0000317 os.remove(output_path)
318 elif abi_compliance_process.returncode == 1:
Darryl Green0da45782019-02-21 13:09:26 +0000319 if self.brief:
320 self.log.info(
321 "Compatibility issues found for {}".format(mbed_module)
322 )
323 report_root = ET.fromstring(abi_compliance_output.decode("utf-8"))
Darryl Green88bfbc22019-03-05 16:30:39 +0000324 self._remove_extra_detail_from_report(report_root)
Darryl Green0da45782019-02-21 13:09:26 +0000325 self.log.info(ET.tostring(report_root).decode("utf-8"))
326 else:
327 compliance_return_code = 1
328 self.can_remove_report_dir = False
329 compatibility_report += (
330 "Compatibility issues found for {}, "
331 "for details see {}\n".format(mbed_module, output_path)
332 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000333 else:
334 raise Exception(
335 "abi-compliance-checker failed with a return code of {},"
336 " aborting".format(abi_compliance_process.returncode)
337 )
Darryl Green7381bea2019-03-05 16:25:38 +0000338 os.remove(self.old_version.abi_dumps[mbed_module])
339 os.remove(self.new_version.abi_dumps[mbed_module])
Darryl Green131e24b2019-02-25 17:01:55 +0000340 if self.can_remove_report_dir:
Darryl Green7c2dd582018-03-01 14:53:49 +0000341 os.rmdir(self.report_dir)
342 self.log.info(compatibility_report)
343 return compliance_return_code
344
345 def check_for_abi_changes(self):
Gilles Peskine9df17632019-02-25 20:36:52 +0100346 """Generate a report of ABI differences
347 between self.old_rev and self.new_rev."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000348 self.check_repo_path()
349 self.check_abi_tools_are_installed()
Darryl Green88bfbc22019-03-05 16:30:39 +0000350 self._get_abi_dump_for_ref(self.old_version)
351 self._get_abi_dump_for_ref(self.new_version)
Darryl Green7c2dd582018-03-01 14:53:49 +0000352 return self.get_abi_compatibility_report()
353
354
355def run_main():
356 try:
357 parser = argparse.ArgumentParser(
358 description=(
Darryl Green418527b2018-04-16 12:02:29 +0100359 """This script is a small wrapper around the
360 abi-compliance-checker and abi-dumper tools, applying them
361 to compare the ABI and API of the library files from two
362 different Git revisions within an Mbed TLS repository.
Darryl Green0da45782019-02-21 13:09:26 +0000363 The results of the comparison are either formatted as HTML and
Darryl Green7c0e0522019-03-05 15:21:32 +0000364 stored at a configurable location, or are given as a brief list
365 of problems. Returns 0 on success, 1 on ABI/API non-compliance,
366 and 2 if there is an error while running the script.
367 Note: must be run from Mbed TLS root."""
Darryl Green7c2dd582018-03-01 14:53:49 +0000368 )
369 )
370 parser.add_argument(
Darryl Green66025382019-03-08 11:30:04 +0000371 "-v", "--verbose", action="store_true",
372 help="set verbosity level",
373 )
374 parser.add_argument(
Darryl Green418527b2018-04-16 12:02:29 +0100375 "-r", "--report-dir", type=str, default="reports",
Darryl Green7c2dd582018-03-01 14:53:49 +0000376 help="directory where reports are stored, default is reports",
377 )
378 parser.add_argument(
Darryl Green418527b2018-04-16 12:02:29 +0100379 "-k", "--keep-all-reports", action="store_true",
Darryl Green7c2dd582018-03-01 14:53:49 +0000380 help="keep all reports, even if there are no compatibility issues",
381 )
382 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000383 "-o", "--old-rev", type=str, help="revision for old version.",
384 required=True,
Darryl Green7c2dd582018-03-01 14:53:49 +0000385 )
386 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000387 "-or", "--old-repo", type=str, help="repository for old version."
Darryl Greenae5d66c2019-02-25 11:35:05 +0000388 )
389 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000390 "-oc", "--old-crypto-rev", type=str,
391 help="revision for old crypto submodule."
Darryl Green7c2dd582018-03-01 14:53:49 +0000392 )
Darryl Green668063b2019-02-20 15:01:56 +0000393 parser.add_argument(
Darryl Green06c51d02019-03-01 09:54:44 +0000394 "-ocr", "--old-crypto-repo", type=str,
395 help="repository for old crypto submodule."
396 )
397 parser.add_argument(
398 "-n", "--new-rev", type=str, help="revision for new version",
399 required=True,
400 )
401 parser.add_argument(
402 "-nr", "--new-repo", type=str, help="repository for new version."
403 )
404 parser.add_argument(
405 "-nc", "--new-crypto-rev", type=str,
406 help="revision for new crypto version"
407 )
408 parser.add_argument(
409 "-ncr", "--new-crypto-repo", type=str,
410 help="repository for new crypto submodule."
Darryl Greenae5d66c2019-02-25 11:35:05 +0000411 )
412 parser.add_argument(
Darryl Green668063b2019-02-20 15:01:56 +0000413 "-s", "--skip-file", type=str,
414 help="path to file containing symbols and types to skip"
415 )
Darryl Green0da45782019-02-21 13:09:26 +0000416 parser.add_argument(
417 "-b", "--brief", action="store_true",
418 help="output only the list of issues to stdout, instead of a full report",
419 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000420 abi_args = parser.parse_args()
Darryl Green26dff8e2019-04-05 17:06:17 +0100421 old_version = RepoVersion(
422 "old", abi_args.old_repo, abi_args.old_rev,
423 abi_args.old_crypto_repo, abi_args.old_crypto_rev
424 )
425 new_version = RepoVersion(
426 "new", abi_args.new_repo, abi_args.new_rev,
427 abi_args.new_crypto_repo, abi_args.new_crypto_rev
428 )
Darryl Green7c2dd582018-03-01 14:53:49 +0000429 abi_check = AbiChecker(
Darryl Green66025382019-03-08 11:30:04 +0000430 abi_args.verbose, old_version, new_version, abi_args.report_dir,
Darryl Green7381bea2019-03-05 16:25:38 +0000431 abi_args.keep_all_reports, abi_args.brief, abi_args.skip_file
Darryl Green7c2dd582018-03-01 14:53:49 +0000432 )
433 return_code = abi_check.check_for_abi_changes()
434 sys.exit(return_code)
Gilles Peskineafd19dd2019-02-25 21:39:42 +0100435 except Exception: # pylint: disable=broad-except
436 # Print the backtrace and exit explicitly so as to exit with
437 # status 2, not 1.
Darryl Greena6f430f2018-03-15 10:12:06 +0000438 traceback.print_exc()
Darryl Green7c2dd582018-03-01 14:53:49 +0000439 sys.exit(2)
440
441
442if __name__ == "__main__":
443 run_main()