#!/usr/bin/env python # check-incremental - Check if incremental compilation works -*- python -*- # # This source file is part of the Swift.org open source project # # Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors # Licensed under Apache License v2.0 with Runtime Library Exception # # See http://swift.org/LICENSE.txt for license information # See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors # # ---------------------------------------------------------------------------- # # This is a wrapper for the swift compiler. # It invokes the compiler multiple times and checks if the output object file # is only written a single time. # The main purpose of the check is to ensure that the compiler is # deterministic. # # ---------------------------------------------------------------------------- import os import subprocess import sys def main(): verbose = False num_iterations = 4 write_obj_file = False next_arg_is_output = False compare_time = True output_file = None for arg in sys.argv: if next_arg_is_output: output_file = arg next_arg_is_output = False elif arg == '-c': write_obj_file = True elif arg == '-disable-incremental-llvm-codegen': compare_time = False elif arg == '-o': next_arg_is_output = True if not write_obj_file or output_file is None: return new_args = sys.argv[1:] subprocess.check_call(new_args) if verbose: print "Reference compilation of " + output_file + ":" reference_md5 = subprocess.check_output(["md5", "-q", output_file]) reference_time = os.path.getmtime(output_file) if verbose: print " time = {}".format(reference_time) print " md5 = " + reference_md5 subprocess.check_call(["cp", output_file, output_file + ".ref.o"]) for iteration in range(0, num_iterations): if verbose: print "Iteration {}:".format(iteration) subprocess.check_call(new_args) second_md5 = subprocess.check_output(["md5", "-q", output_file]) second_time = os.path.getmtime(output_file) if verbose: print " time = {}".format(second_time) print " md5 = " + second_md5 # This is the most important check: is the output file exactly the # same. if reference_md5 != second_md5: sys.exit("non-determinism when generating: " + output_file) # 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). if compare_time and reference_time != second_time: sys.exit("file re-written: " + output_file) main()