- Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathcheck-incremental
executable file
·106 lines (80 loc) · 3.19 KB
/
check-incremental
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env python3
# check-incremental - Check if incremental compilation works -*- python -*-
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
"""
check-incremental: Check if incremental compilation works.
This is a wrapper for the Swift compiler. It invokes the compiler
multiple times and checks if the output object file is only written once.
The main purpose of the check is to ensure that the compiler is
deterministic.
"""
importos
importsubprocess
importsys
importtime
VERBOSE=False
NUM_ITERATIONS=4
defcompile_and_stat(compile_args, output_file):
"""Perform a compilation using ``compile_args``, and return a tuple
(md5sum, last modified time) for ``output_file`` after the
compilation has finished.
"""
subprocess.check_call(compile_args)
md5=subprocess.check_output(["md5", "-q", output_file],
universal_newlines=True)
mtime=time.ctime(os.path.getmtime(output_file))
ifVERBOSE:
print(" time = "+str(mtime))
print(" md5 = "+md5)
return (md5, mtime)
defmain():
write_obj_file=False
next_arg_is_output=False
compare_time=True
output_file=None
forarginsys.argv:
ifnext_arg_is_output:
output_file=arg
next_arg_is_output=False
elifarg=='-c':
write_obj_file=True
elifarg=='-disable-incremental-llvm-codegen':
compare_time=False
elifarg=='-o':
next_arg_is_output=True
new_args=sys.argv[1:]
ifnotwrite_obj_fileoroutput_fileisNone:
subprocess.check_call(new_args)
return
ifVERBOSE:
print("Reference compilation of "+output_file+":")
# As a workaround for rdar://problem/43442957 and rdar://problem/43439465
# we have to "warm-up" the clang module cache. Without that in some cases
# we end up with small differences in the debug info.
compile_and_stat(new_args, output_file)
reference_md5, reference_time=compile_and_stat(new_args, output_file)
subprocess.check_call(["cp", output_file, output_file+".ref.o"])
foriterationinrange(1, NUM_ITERATIONS+1):
ifVERBOSE:
print("Iteration {}:".format(iteration))
second_md5, second_time=compile_and_stat(new_args, output_file)
# This is the most important check: is the output file exactly the
# same.
ifreference_md5!=second_md5:
sys.exit("non-determinism when generating: "+output_file+
"\ncommand line:\n"+" ".join(new_args))
# This is the bonus check: does the compiler not re-write the output
# file. (For compilations < 1sec this check may succeed even if the
# file was overwritten).
ifcompare_timeandreference_time!=second_time:
sys.exit("file re-written: "+output_file)
if__name__=='__main__':
main()