Esempio n. 1
0
def scan_build():
    """ Entry point for scan-build command. """

    args = parse_args_for_scan_build()
    # will re-assign the report directory as new output
    with report_directory(
            args.output, args.keep_empty, args.output_format) as args.output:
        # Run against a build command. there are cases, when analyzer run
        # is not required. But we need to set up everything for the
        # wrappers, because 'configure' needs to capture the CC/CXX values
        # for the Makefile.
        if args.intercept_first:
            # Run build command with intercept module.
            exit_code = capture(args)
            # Run the analyzer against the captured commands.
            if need_analyzer(args.build):
                govern_analyzer_runs(args)
        else:
            # Run build command and analyzer with compiler wrappers.
            environment = setup_environment(args)
            exit_code = run_build(args.build, env=environment)
        # Cover report generation and bug counting.
        number_of_bugs = document(args)
        # Set exit status as it was requested.
        return number_of_bugs if args.status_bugs else exit_code
Esempio n. 2
0
def scan_build():
    # type: () -> int
    """ Entry point for scan-build command. """

    args = parse_args_for_scan_build()
    # will re-assign the report directory as new output
    with report_directory(args.output, args.keep_empty) as args.output:
        # run against a build command. there are cases, when analyzer run
        # is not required. but we need to set up everything for the
        # wrappers, because 'configure' needs to capture the CC/CXX values
        # for the Makefile.
        if args.intercept_first:
            # run build command with intercept module
            exit_code, compilations = capture(args)
            if need_analyzer(args.build):
                # run the analyzer against the captured commands
                run_analyzer_parallel(compilations, args)
        else:
            # run build command and analyzer with compiler wrappers
            environment = setup_environment(args)
            exit_code = run_build(args.build, env=environment)
        # cover report generation and bug counting
        number_of_bugs = document(args)
        # set exit status as it was requested
        return number_of_bugs if args.status_bugs else exit_code
Esempio n. 3
0
def capture(args):
    """ Implementation of compilation database generation.

    :param args:    the parsed and validated command line arguments
    :return:        the exit status of build process. """

    with temporary_directory(prefix='intercept-', dir=tempdir()) as tmp_dir:
        # run the build command
        environment = setup_environment(args, tmp_dir)
        exit_code = run_build(args.build, env=environment)
        # read the intercepted exec calls
        calls = (parse_exec_trace(file) for file in exec_trace_files(tmp_dir))
        current = compilations(calls, args.cc, args.cxx)

        return exit_code, iter(set(current))
Esempio n. 4
0
def capture(args):
    """ Implementation of compilation database generation.

    :param args:    the parsed and validated command line arguments
    :return:        the exit status of build process. """

    with temporary_directory(prefix='intercept-') as tmp_dir:
        # run the build command
        environment = setup_environment(args, tmp_dir)
        exit_code = run_build(args.build, env=environment)
        # read the intercepted exec calls
        calls = (parse_exec_trace(file) for file in exec_trace_files(tmp_dir))
        current = compilations(calls, args.cc, args.cxx)

        return exit_code, iter(set(current))
Esempio n. 5
0
def capture(args):
    """ The entry point of build command interception. """

    def post_processing(commands):
        """ To make a compilation database, it needs to filter out commands
        which are not compiler calls. Needs to find the source file name
        from the arguments. And do shell escaping on the command.

        To support incremental builds, it is desired to read elements from
        an existing compilation database from a previous run. These elements
        shall be merged with the new elements. """

        # create entries from the current run
        current = itertools.chain.from_iterable(
            # creates a sequence of entry generators from an exec,
            format_entry(command) for command in commands)
        # read entries from previous run
        if 'append' in args and args.append and os.path.isfile(args.cdb):
            with open(args.cdb) as handle:
                previous = iter(json.load(handle))
        else:
            previous = iter([])
        # filter out duplicate entries from both
        duplicate = duplicate_check(entry_hash)
        return (entry
                for entry in itertools.chain(previous, current)
                if os.path.exists(entry['file']) and not duplicate(entry))

    with TemporaryDirectory(prefix='intercept-', dir=tempdir()) as tmp_dir:
        # run the build command
        environment = setup_environment(args, tmp_dir)
        exit_code = run_build(args.build, env=environment)
        # read the intercepted exec calls
        exec_traces = itertools.chain.from_iterable(
            parse_exec_trace(os.path.join(tmp_dir, filename))
            for filename in sorted(glob.iglob(os.path.join(tmp_dir, '*.cmd'))))
        # do post processing
        entries = post_processing(exec_traces)
        # dump the compilation database
        with open(args.cdb, 'w+') as handle:
            json.dump(list(entries), handle, sort_keys=True, indent=4)
        return exit_code
Esempio n. 6
0
def analyze_build_main(bin_dir, from_build_command):
    """ Entry point for 'analyze-build' and 'scan-build'. """

    parser = create_parser(from_build_command)
    args = parser.parse_args()
    validate(parser, args, from_build_command)

    # setup logging
    initialize_logging(args.verbose)
    logging.debug('Parsed arguments: %s', args)

    with report_directory(args.output, args.keep_empty) as target_dir:
        if not from_build_command:
            # run analyzer only and generate cover report
            run_analyzer(args, target_dir)
            number_of_bugs = document(args, target_dir, True)
            return number_of_bugs if args.status_bugs else 0
        elif args.intercept_first:
            # run build command and capture compiler executions
            exit_code = capture(args, bin_dir)
            # next step to run the analyzer against the captured commands
            if need_analyzer(args.build):
                run_analyzer(args, target_dir)
                # cover report generation and bug counting
                number_of_bugs = document(args, target_dir, True)
                # remove the compilation database when it was not requested
                if os.path.exists(args.cdb):
                    os.unlink(args.cdb)
                # set exit status as it was requested
                return number_of_bugs if args.status_bugs else exit_code
            else:
                return exit_code
        else:
            # run the build command with compiler wrappers which
            # execute the analyzer too. (interposition)
            environment = setup_environment(args, target_dir, bin_dir)
            exit_code = run_build(args.build, env=environment)
            # cover report generation and bug counting
            number_of_bugs = document(args, target_dir, False)
            # set exit status as it was requested
            return number_of_bugs if args.status_bugs else exit_code
Esempio n. 7
0
def scan_build():
    """ Entry point for scan-build command. """

    args = parse_args_for_scan_build()
    with report_directory(args.output, args.keep_empty) as target_dir:
        # Run against a build command. there are cases, when analyzer run
        # is not required. But we need to set up everything for the
        # wrappers, because 'configure' needs to capture the CC/CXX values
        # for the Makefile.
        if args.intercept_first:
            # Run build command with intercept module.
            exit_code = capture(args)
            # Run the analyzer against the captured commands.
            if need_analyzer(args.build):
                run_analyzer(args, target_dir)
        else:
            # Run build command and analyzer with compiler wrappers.
            environment = setup_environment(args, target_dir)
            exit_code = run_build(args.build, env=environment)
        # Cover report generation and bug counting.
        number_of_bugs = document(args, target_dir, False)
        # Set exit status as it was requested.
        return number_of_bugs if args.status_bugs else exit_code