Ejemplo n.º 1
0
def handle_debug(args):
    """
    Runs a debug command on the buildactions where the analysis
    failed for some reason.
    """
    context = generic_package_context.get_context()

    try:
        workspace = args.workspace
    except AttributeError:
        # If no workspace value was set for some reason
        # in args set the default value.
        workspace = util.get_default_workspace()

    context.codechecker_workspace = workspace
    context.db_username = args.dbusername

    check_env = analyzer_env.get_check_env(context.path_env_extra,
                                           context.ld_lib_path_extra)

    sql_server = SQLServer.from_cmdline_args(args,
                                             context.codechecker_workspace,
                                             context.migration_root,
                                             check_env)
    sql_server.start(context.db_version_info, wait_for_start=True, init=False)

    debug_reporter.debug(context, sql_server.get_connection_string(),
                         args.force)
Ejemplo n.º 2
0
def handle_debug(args):
    """
    Runs a debug command on the buildactions where the analysis
    failed for some reason
    """
    context = generic_package_context.get_context()

    try:
        workspace = args.workspace
    except AttributeError:
        # if no workspace value was set for some reason
        # in args set the default value
        workspace = util.get_default_workspace()

    context.codechecker_workspace = workspace
    context.db_username = args.dbusername

    check_env = analyzer_env.get_check_env(context.path_env_extra,
                                           context.ld_lib_path_extra)

    sql_server = SQLServer.from_cmdline_args(args,
                                             context.codechecker_workspace,
                                             context.migration_root, check_env)
    sql_server.start(context.db_version_info, wait_for_start=True, init=False)

    debug_reporter.debug(context, sql_server.get_connection_string(),
                         args.force)
Ejemplo n.º 3
0
def _do_quickcheck(args):
    """
    Handles the "quickcheck" command.

    For arguments see main function in CodeChecker.py.
    It also requires an extra property in args object, namely workspace which
    is a directory path as a string.
    This function is called from handle_quickcheck.
    """

    context = generic_package_context.get_context()

    try:
        workspace = args.workspace
    except AttributeError:
        # If no workspace value was set for some reason
        # in args set the default value.
        workspace = util.get_default_workspace()

    context.codechecker_workspace = workspace
    args.name = "quickcheck"

    # Load severity map from config file.
    if os.path.exists(context.checkers_severity_map_file):
        with open(context.checkers_severity_map_file, 'r') as sev_conf_file:
            severity_config = sev_conf_file.read()

        context.severity_map = json.loads(severity_config)

    log_file = build_manager.check_log_file(args)

    if not log_file:
        log_file = build_manager.generate_log_file(args,
                                                   context,
                                                   args.quiet_build)
    if not log_file:
        LOG.error("Failed to generate compilation command file: " + log_file)
        sys.exit(1)

    try:
        actions = log_parser.parse_log(log_file)
    except Exception as ex:
        LOG.error(ex)
        sys.exit(1)

    if not actions:
        LOG.warning('There are no build actions in the log file.')
        sys.exit(1)

    analyzer.run_quick_check(args, context, actions)
Ejemplo n.º 4
0
def _do_quickcheck(args):
    """
    Handles the "quickcheck" command.

    For arguments see main function in CodeChecker.py. It also requires an extra
    property in args object, namely workspace which is a directory path as a
    string. This function is called from handle_quickcheck.
    """

    context = generic_package_context.get_context()

    try:
        workspace = args.workspace
    except AttributeError:
        # If no workspace value was set for some reason
        # in args set the default value.
        workspace = util.get_default_workspace()

    context.codechecker_workspace = workspace
    args.jobs = 1
    args.name = "quickcheck"

    # Load severity map from config file.
    if os.path.exists(context.checkers_severity_map_file):
        with open(context.checkers_severity_map_file, 'r') as sev_conf_file:
            severity_config = sev_conf_file.read()

        context.severity_map = json.loads(severity_config)

    log_file = build_manager.check_log_file(args)

    if not log_file:
        log_file = build_manager.generate_log_file(args,
                                                   context,
                                                   args.quiet_build)
    if not log_file:
        LOG.error("Failed to generate compilation command file: " + log_file)
        sys.exit(1)

    try:
        actions = log_parser.parse_log(log_file)
    except Exception as ex:
        LOG.error(ex)
        sys.exit(1)

    if not actions:
        LOG.warning('There are no build actions in the log file.')
        sys.exit(1)

    analyzer.run_quick_check(args, context, actions)
Ejemplo n.º 5
0
def handle_server(args):
    """
    Starts the report viewer server.
    """
    if not host_check.check_zlib():
        LOG.error("zlib error")
        sys.exit(1)

    try:
        workspace = args.workspace
    except AttributeError:
        # If no workspace value was set for some reason
        # in args set the default value.
        workspace = util.get_default_workspace()

    # WARNING
    # In case of SQLite args.dbaddress default value is used
    # for which the is_localhost should return true.

    local_db = util.is_localhost(args.dbaddress)
    if local_db and not os.path.exists(workspace):
        os.makedirs(workspace)

    if args.suppress is None:
        LOG.warning(
            "WARNING! No suppress file was given, suppressed results will " +
            'be only stored in the database.')

    else:
        if not os.path.exists(args.suppress):
            LOG.error('Suppress file ' + args.suppress + ' not found!')
            sys.exit(1)

    context = generic_package_context.get_context()
    context.codechecker_workspace = workspace
    session_manager.SessionManager.CodeChecker_Workspace = workspace
    context.db_username = args.dbusername

    check_env = analyzer_env.get_check_env(context.path_env_extra,
                                           context.ld_lib_path_extra)

    sql_server = SQLServer.from_cmdline_args(args,
                                             context.codechecker_workspace,
                                             context.migration_root,
                                             check_env)
    conn_mgr = client.ConnectionManager(sql_server, args.check_address,
                                        args.check_port)
    if args.check_port:
        LOG.debug('Starting CodeChecker server and database server.')
        sql_server.start(context.db_version_info, wait_for_start=True,
                         init=True)
        conn_mgr.start_report_server()
    else:
        LOG.debug('Starting database.')
        sql_server.start(context.db_version_info, wait_for_start=True,
                         init=True)

    # Start database viewer.
    db_connection_string = sql_server.get_connection_string()

    suppress_handler = generic_package_suppress_handler.GenericSuppressHandler()
    try:
        suppress_handler.suppress_file = args.suppress
        LOG.debug('Using suppress file: ' + str(suppress_handler.suppress_file))
    except AttributeError as aerr:
        # Suppress file was not set.
        LOG.debug(aerr)

    package_data = {'www_root': context.www_root, 'doc_root': context.doc_root}

    checker_md_docs = os.path.join(context.doc_root, 'checker_md_docs')

    checker_md_docs_map = os.path.join(checker_md_docs,
                                       'checker_doc_map.json')

    package_data['checker_md_docs'] = checker_md_docs

    with open(checker_md_docs_map, 'r') as dFile:
        checker_md_docs_map = json.load(dFile)

    package_data['checker_md_docs_map'] = checker_md_docs_map

    client_db_access_server.start_server(package_data,
                                         args.view_port,
                                         db_connection_string,
                                         suppress_handler,
                                         args.not_host_only,
                                         context.db_version_info)
Ejemplo n.º 6
0
def handle_check(args):
    """
    Runs the original build and logs the buildactions.
    Based on the log runs the analysis.
    """
    try:

        if not host_check.check_zlib():
            LOG.error("zlib error")
            sys.exit(1)

        try:
            workspace = args.workspace
        except AttributeError:
            # If no workspace value was set for some reason
            # in args set the default value.
            workspace = util.get_default_workspace()

        workspace = os.path.realpath(workspace)
        if not os.path.isdir(workspace):
            os.mkdir(workspace)

        context = generic_package_context.get_context()
        context.codechecker_workspace = workspace
        context.db_username = args.dbusername

        log_file = build_manager.check_log_file(args)

        if not log_file:
            log_file = build_manager.generate_log_file(args,
                                                       context,
                                                       args.quiet_build)
        if not log_file:
            LOG.error("Failed to generate compilation command file: " +
                      log_file)
            sys.exit(1)

        try:
            actions = log_parser.parse_log(log_file)
        except Exception as ex:
            LOG.error(ex)
            sys.exit(1)

        if not actions:
            LOG.warning('There are no build actions in the log file.')
            sys.exit(1)

        check_env = analyzer_env.get_check_env(context.path_env_extra,
                                               context.ld_lib_path_extra)

        sql_server = SQLServer.from_cmdline_args(args,
                                                 context.codechecker_workspace,
                                                 context.migration_root,
                                                 check_env)

        conn_mgr = client.ConnectionManager(sql_server, 'localhost',
                                            util.get_free_port())

        sql_server.start(context.db_version_info, wait_for_start=True,
                         init=True)

        conn_mgr.start_report_server()

        LOG.debug("Checker server started.")

        analyzer.run_check(args,
                           actions,
                           context)

        LOG.info("Analysis has finished.")

        db_data = ""
        if args.postgresql:
            db_data += " --postgresql" \
                       + " --dbname " + args.dbname \
                       + " --dbport " + str(args.dbport) \
                       + " --dbusername " + args.dbusername

        LOG.info("To view results run:\nCodeChecker server -w " +
                 workspace + db_data)

    except Exception as ex:
        LOG.error(ex)
        import traceback
        print(traceback.format_exc())
Ejemplo n.º 7
0
def handle_server(args):
    """
    starts the report viewer server
    """
    if not host_check.check_zlib():
        LOG.error("zlib error")
        sys.exit(1)

    try:
        workspace = args.workspace
    except AttributeError:
        # if no workspace value was set for some reason
        # in args set the default value
        workspace = util.get_default_workspace()

    # WARNING
    # in case of SQLite args.dbaddress default value is used
    # for which the is_localhost should return true

    local_db = util.is_localhost(args.dbaddress)
    if local_db and not os.path.exists(workspace):
        os.makedirs(workspace)

    if args.suppress is None:
        LOG.warning(
            'WARNING! No suppress file was given, suppressed results will be only stored in the database.'
        )

    else:
        if not os.path.exists(args.suppress):
            LOG.error('Suppress file ' + args.suppress + ' not found!')
            sys.exit(1)

    context = generic_package_context.get_context()
    context.codechecker_workspace = workspace
    context.db_username = args.dbusername

    check_env = analyzer_env.get_check_env(context.path_env_extra,
                                           context.ld_lib_path_extra)

    sql_server = SQLServer.from_cmdline_args(args,
                                             context.codechecker_workspace,
                                             context.migration_root, check_env)
    conn_mgr = client.ConnectionManager(sql_server, args.check_address,
                                        args.check_port)
    if args.check_port:
        LOG.debug('Starting codechecker server and database server.')
        sql_server.start(context.db_version_info,
                         wait_for_start=True,
                         init=True)
        conn_mgr.start_report_server(context.db_version_info)
    else:
        LOG.debug('Starting database.')
        sql_server.start(context.db_version_info,
                         wait_for_start=True,
                         init=True)

    # start database viewer
    db_connection_string = sql_server.get_connection_string()

    suppress_handler = generic_package_suppress_handler.GenericSuppressHandler(
    )
    try:
        suppress_handler.suppress_file = args.suppress
        LOG.debug('Using suppress file: ' +
                  str(suppress_handler.suppress_file))
    except AttributeError as aerr:
        # suppress file was not set
        LOG.debug(aerr)

    package_data = {}
    package_data['www_root'] = context.www_root
    package_data['doc_root'] = context.doc_root

    checker_md_docs = os.path.join(context.doc_root, 'checker_md_docs')

    checker_md_docs_map = os.path.join(checker_md_docs, 'checker_doc_map.json')

    package_data['checker_md_docs'] = checker_md_docs

    with open(checker_md_docs_map, 'r') as dFile:
        checker_md_docs_map = json.load(dFile)

    package_data['checker_md_docs_map'] = checker_md_docs_map

    client_db_access_server.start_server(package_data, args.view_port,
                                         db_connection_string,
                                         suppress_handler, args.not_host_only,
                                         context.db_version_info)
Ejemplo n.º 8
0
def handle_check(args):
    """
    Runs the original build and logs the buildactions
    Based on the log runs the analysis
    """
    try:

        if not host_check.check_zlib():
            LOG.error("zlib error")
            sys.exit(1)

        try:
            workspace = args.workspace
        except AttributeError:
            # if no workspace value was set for some reason
            # in args set the default value
            workspace = util.get_default_workspace()

        workspace = os.path.realpath(workspace)
        if not os.path.isdir(workspace):
            os.mkdir(workspace)

        context = generic_package_context.get_context()
        context.codechecker_workspace = workspace
        context.db_username = args.dbusername

        log_file = build_manager.check_log_file(args)

        if not log_file:
            log_file = build_manager.generate_log_file(args, context)
        if not log_file:
            LOG.error("Failed to generate compilation command file: " +
                      log_file)
            sys.ecit(1)

        try:
            actions = log_parser.parse_log(log_file)
        except Exception as ex:
            LOG.error(ex)
            sys.exit(1)

        if not actions:
            LOG.warning('There are no build actions in the log file.')
            sys.exit(1)

        check_env = analyzer_env.get_check_env(context.path_env_extra,
                                               context.ld_lib_path_extra)

        sql_server = SQLServer.from_cmdline_args(args,
                                                 context.codechecker_workspace,
                                                 context.migration_root,
                                                 check_env)

        conn_mgr = client.ConnectionManager(sql_server, 'localhost',
                                            util.get_free_port())

        sql_server.start(context.db_version_info,
                         wait_for_start=True,
                         init=True)

        conn_mgr.start_report_server(context.db_version_info)

        LOG.debug("Checker server started.")

        analyzer.run_check(args, actions, context)

        LOG.info("Analysis has finished.")

        db_data = ""
        if args.postgresql:
            db_data += " --postgresql" \
                    +  " --dbname " + args.dbname \
                    +  " --dbport " + str(args.dbport) \
                    +  " --dbusername " + args.dbusername

        LOG.info("To view results run:\nCodeChecker server -w " + workspace +
                 db_data)

    except Exception as ex:
        LOG.error(ex)
        import traceback
        print(traceback.format_exc())
Ejemplo n.º 9
0
def main():
    '''
    codechecker main command line
    '''

    def signal_handler(sig, frame):
        '''
        Without this handler the postgreSql
        server does not terminated at signal
        '''
        sys.exit(1)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    try:
        parser = argparse.ArgumentParser(
            prog='CodeChecker',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description='''
Run the CodeChecker source analyzer framework.
See the subcommands for specific features.''',
            epilog='''
Example usage:
--------------
Analyzing a project with default settings:
CodeChecker check -w ~/workspace -b "cd ~/myproject && make" -n myproject

Start the viewer to see the results:
CodeChecker server -w ~/workspace

See the results in a web browser: localhost:8001
See results in  the command line: CodeChecker cmd results -p 8001 -n myproject

To analyze a small project quickcheck feature can be used.
The results will be printed only to the standard output. (No database will be used)

CodeChecker quickcheck -w ~/workspace -b "cd ~/myproject && make"
''')

        subparsers = parser.add_subparsers(help='commands')

        workspace_help_msg = """Directory where the codechecker can store analysis related data."""

        name_help_msg = """Name of the analysis."""

        jobs_help_msg = """Number of jobs. Start multiple processes for faster analysis""";

        log_argument_help_msg="""Path to the log file which is created during the build. \nIf there is an already generated log file with the compilation commands\ngenerated by 'CodeChecker log' or 'cmake -DCMAKE_EXPORT_COMPILE_COMMANDS' \nCodechecker check can use it for the analysis in that case running the original build will \nbe left out from the analysis process (no log is needed)."""

        # --------------------------------------
        # check commands
        check_parser = subparsers.add_parser('check',
                                             formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                             help='''\
Run the supported source code analyzers on a project''')
        check_parser.add_argument('-w', '--workspace', type=str,
                                  default=util.get_default_workspace(),
                                  dest="workspace",
                                  help=workspace_help_msg)
        check_parser.add_argument('-n', '--name', type=str,
                                  dest="name", required=True,
                                  default=argparse.SUPPRESS,
                                  help=name_help_msg)
        checkgroup = check_parser.add_mutually_exclusive_group(required=True)
        checkgroup.add_argument('-b', '--build', type=str, dest="command",
                                default=argparse.SUPPRESS,
                                required=False, help='''\
Build command which is used to build the project''')
        checkgroup.add_argument('-l', '--log', type=str, dest="logfile",
                                default=argparse.SUPPRESS,
                                required=False,
                                help=log_argument_help_msg)
        check_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                  default=1, required=False,
                                  help=jobs_help_msg)
        check_parser.add_argument('-u', '--suppress', type=str, dest="suppress",
                                  default=argparse.SUPPRESS,
                                  required=False, help="""Path to suppress file. \nSuppress file can be used to suppress analysis results during the analysis.\nIt is based on the bug identifier generated by the compiler which is experimental.\nDo not depend too much on this file because identifier or file format can be changed.\nFor other in source suppress features see the user guide.""")
        check_parser.add_argument('-c', '--clean',
                                  default=argparse.SUPPRESS,
                                  action=DeprecatedOptionAction)
        check_parser.add_argument('--update', action=DeprecatedOptionAction,
                                  dest="update", default=False, required=False,
                                  help='''\
Incremental parsing, update the results of a previous run.
Only the files changed since the last build will be reanalyzed. Depends on the build system.''')

        check_parser.add_argument('--force', action="store_true",
                                  dest="force", default=False, required=False,
                                  help='''\
Delete analysis results form the database if a run with the given name already exists''')
        check_parser.add_argument('-s', '--skip', type=str, dest="skipfile",
                                  default=argparse.SUPPRESS,
                                  required=False, help='Path to skip file.')
        add_analyzer_arguments(check_parser)
        add_database_arguments(check_parser)
        check_parser.set_defaults(func=arg_handler.handle_check)

        # --------------------------------------
        # quickcheck commands
        qcheck_parser = subparsers.add_parser('quickcheck',
                                              formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                              help='''\
Run CodeChecker for a project without database.''')
        qcheckgroup = qcheck_parser.add_mutually_exclusive_group(required=True)
        qcheckgroup.add_argument('-b', '--build', type=str, dest="command",
                                 default=argparse.SUPPRESS,
                                 required=False, help='Build command.')
        qcheckgroup.add_argument('-l', '--log', type=str, dest="logfile",
                                 required=False,
                                 default=argparse.SUPPRESS,
                                 help=log_argument_help_msg)
        qcheck_parser.add_argument('-s', '--steps', action="store_true",
                                   dest="print_steps", help='Print steps.')
        add_analyzer_arguments(qcheck_parser)
        qcheck_parser.set_defaults(func=arg_handler.handle_quickcheck)


        # --------------------------------------
        # log commands
        logging_parser = subparsers.add_parser('log',
                                              formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                               help='''\
Runs the given build command. During the build the compilation commands are collected and
stored into a compilation command json file (no analysis is done during the build).''')
        logging_parser.add_argument('-o', '--output', type=str, dest="logfile",
                                    default=argparse.SUPPRESS,
                                    required=True, help='Path to the log file.')
        logging_parser.add_argument('-b', '--build', type=str, dest="command",
                                    default=argparse.SUPPRESS,
                                    required=True, help='Build command.')
        logging_parser.set_defaults(func=arg_handler.handle_log)

        # --------------------------------------
        # checkers parser
        checkers_parser = subparsers.add_parser('checkers',
                                                formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                                help="""List the available checkers for the supported analyzers and show their default status (+ for being enabled, - for being disabled by default).""")
        checkers_parser.add_argument('--analyzers', nargs='+',
                            dest="analyzers", required=False,
                            help="""Select which analyzer checkers should be listed.\nCurrently supported analyzers:\n""" + analyzers)
        checkers_parser.set_defaults(func=arg_handler.handle_list_checkers)

        # --------------------------------------
        # server
        server_parser = subparsers.add_parser('server',
                                             formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                              help='Start the codechecker web server.')
        server_parser.add_argument('-w', '--workspace', type=str,
                                   dest="workspace",
                                   default=util.get_default_workspace(),
                                   help=workspace_help_msg)
        server_parser.add_argument('-v', '--view-port', type=int, dest="view_port",
                                   default=8001, required=False,
                                   help='Port used for viewing.')
        server_parser.add_argument('-u', '--suppress', type=str, dest="suppress",
                                   required=False, help='Path to suppress file.')
        server_parser.add_argument('--not-host-only', action="store_true",
                                   dest="not_host_only",
                                   help='Viewing the results is possible not \
                                   only by browsers or clients started locally.')
        server_parser.add_argument('--check-port', type=int, dest="check_port",
                                   default=None, required=False,
                                   help='Port used for checking.')
        server_parser.add_argument('--check-address', type=str,
                                   dest="check_address", default="localhost",
                                   required=False, help='Server address.')
        add_database_arguments(server_parser)
        server_parser.set_defaults(func=arg_handler.handle_server)

        # --------------------------------------
        # cmd_line
        cmd_line_parser = subparsers.add_parser('cmd',
                                                help='Command line client')
        cmd_line_client.register_client_command_line(cmd_line_parser)

        # --------------------------------------
        # debug parser
        debug_parser = subparsers.add_parser('debug',
                                             formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                             help="""Generate gdb debug dump files for all the failed compilation commands in the last analyzer run.\nRequires a database with the failed compilation commands""")
        debug_parser.add_argument('-w', '--workspace', type=str,
                                  dest="workspace",
                                  default=util.get_default_workspace(),
                                  help=workspace_help_msg)
        debug_parser.add_argument('-f', '--force', action="store_true",
                                  dest="force", required=False, default=False,
                                  help='Overwrite already generated files.')
        add_database_arguments(debug_parser)
        debug_parser.set_defaults(func=arg_handler.handle_debug)

        # --------------------------------------
        # plist parser
        plist_parser = subparsers.add_parser('plist',
                                             formatter_class=argparse.ArgumentDefaultsHelpFormatter,
                                             help='Parse plist files in the given directory.')
        plist_parser.add_argument('-w', '--workspace', type=str,
                                  dest="workspace",
                                  default=util.get_default_workspace(),
                                  help=workspace_help_msg)
        plist_parser.add_argument('-n', '--name', type=str,
                                  dest="name", required=True,
                                  default=argparse.SUPPRESS,
                                  help=name_help_msg)
        plist_parser.add_argument('-d', '--directory', type=str,
                                  dest="directory", required=True,
                                  help='Path of a directory containing plist files to parse.')
        plist_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                  default=1, required=False,
                                  help=jobs_help_msg)
        plist_parser.add_argument('-s', '--steps', action="store_true",
                                  dest="print_steps", help='Print steps.')
        plist_parser.add_argument('--stdout', action="store_true", dest="stdout",
                                  required=False, default=False,
                                  help="Print results to stdout instead of database.")
        plist_parser.add_argument('--force', action="store_true",
                                  dest="force", default=False, required=False,
                                  help='''\
Delete analysis results form the database if a run with the given name already exists''')
        add_database_arguments(plist_parser)
        plist_parser.set_defaults(func=arg_handler.handle_plist)

        # --------------------------------------
        # package version info
        version_parser = subparsers.add_parser('version',
                                               help='Print package version information.')
        version_parser.set_defaults(func=arg_handler.handle_version_info)

        args = parser.parse_args()
        args.func(args)

    except KeyboardInterrupt as kb_err:
        LOG.info(str(kb_err))
        LOG.info("Interupted by user...")
        sys.exit(1)

    except shared.ttypes.RequestFailed as thrift_ex:
        LOG.info("Server error.")
        LOG.info("Error code: " + str(thrift_ex.error_code))
        LOG.info("Error message: " + str(thrift_ex.message))
        sys.exit(1)

    # Handle all exception, but print stacktrace. It is needed for atexit.
    # atexit does not work correctly when an unhandled exception occured.
    # So in this case, the servers left running when the script exited.
    except Exception:
        import traceback
        traceback.print_exc(file=sys.stdout)
        sys.exit(2)
Ejemplo n.º 10
0
def main():
    """
    CodeChecker main command line.
    """

    def signal_handler(sig, frame):
        """
        Without this handler the PostgreSQL
        server does not terminated at signal.
        """
        sys.exit(1)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    try:
        parser = argparse.ArgumentParser(
            prog='CodeChecker',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description='''
Run the CodeChecker source analyzer framework.
See the subcommands for specific features.''',
            epilog='''
Example usage:
--------------
Analyzing a project with default settings:
CodeChecker check -w ~/workspace -b "cd ~/myproject && make" -n myproject

Start the viewer to see the results:
CodeChecker server -w ~/workspace

See the results in a web browser: localhost:8001
See results in  the command line: CodeChecker cmd results -p 8001 -n myproject

To analyze a small project quickcheck feature can be used.
The results will be printed only to the standard output.
(No database will be used)

CodeChecker quickcheck -w ~/workspace -b "cd ~/myproject && make"
''')

        subparsers = parser.add_subparsers(help='commands')

        workspace_help_msg = 'Directory where the CodeChecker can' \
            ' store analysis related data.'

        name_help_msg = 'Name of the analysis.'

        jobs_help_msg = 'Number of jobs.' \
            'Start multiple processes for faster analysis'

        log_argument_help_msg = "Path to the log file which is created "
        "during the build. \nIf there is an already generated log file "
        "with the compilation commands\ngenerated by 'CodeChecker log' or "
        "'cmake -DCMAKE_EXPORT_COMPILE_COMMANDS' \n CodeChecker check can "
        "use it for the analysis in that case running the original build "
        "will \nbe left out from the analysis process (no log is needed)."

        suppress_help_msg = "Path to suppress file.\nSuppress file can be used"
        "to suppress analysis results during the analysis.\nIt is based on the"
        "bug identifier generated by the compiler which is experimental.\nDo"
        "not depend too much on this file because identifier or file format "
        "can be changed.\nFor other in source suppress features see the user"
        "guide."

        # --------------------------------------
        # check commands
        check_parser = subparsers.add_parser('check',
                                             formatter_class=ADHF,
                                             help=''' \
Run the supported source code analyzers on a project''')

        check_parser.add_argument('-w', '--workspace', type=str,
                                  default=util.get_default_workspace(),
                                  dest="workspace",
                                  help=workspace_help_msg)

        check_parser.add_argument('-n', '--name', type=str,
                                  dest="name", required=True,
                                  default=argparse.SUPPRESS,
                                  help=name_help_msg)

        checkgroup = check_parser.add_mutually_exclusive_group(required=True)

        checkgroup.add_argument('-b', '--build', type=str, dest="command",
                                default=argparse.SUPPRESS,
                                required=False, help='''\
Build command which is used to build the project''')

        checkgroup.add_argument('-l', '--log', type=str, dest="logfile",
                                default=argparse.SUPPRESS,
                                required=False,
                                help=log_argument_help_msg)

        check_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                  default=1, required=False,
                                  help=jobs_help_msg)

        check_parser.add_argument('-u', '--suppress', type=str,
                                  dest="suppress",
                                  default=argparse.SUPPRESS,
                                  required=False,
                                  help=suppress_help_msg)
        check_parser.add_argument('-c', '--clean',
                                  default=argparse.SUPPRESS,
                                  action=DeprecatedOptionAction)

        check_parser.add_argument('--update', action=DeprecatedOptionAction,
                                  dest="update", default=False, required=False,
                                  help="Incremental parsing, update the "
                                       "results of a previous run. "
                                       "Only the files changed since the last "
                                       "build will be reanalyzed. Depends on"
                                       " the build system.")

        check_parser.add_argument('--force', action="store_true",
                                  dest="force", default=False, required=False,
                                  help="Delete analysis results form the "
                                       "database if a run with the "
                                       "given name already exists")

        check_parser.add_argument('-s', '--skip', type=str, dest="skipfile",
                                  default=argparse.SUPPRESS,
                                  required=False, help='Path to skip file.')

        check_parser.add_argument('--quiet-build',
                                  action='store_true',
                                  default=False,
                                  required=False,
                                  help='Do not print out the output of the '
                                       'original build')

        add_analyzer_arguments(check_parser)
        add_database_arguments(check_parser)
        check_parser.set_defaults(func=arg_handler.handle_check)

        # --------------------------------------
        # QuickCheck commands.
        qcheck_parser = subparsers.add_parser('quickcheck',
                                              formatter_class=ADHF,
                                              help='Run CodeChecker for a'
                                                   'project without database.')

        qcheckgroup = qcheck_parser.add_mutually_exclusive_group(required=True)

        qcheckgroup.add_argument('-b', '--build', type=str, dest="command",
                                 default=argparse.SUPPRESS,
                                 required=False, help='Build command.')

        qcheckgroup.add_argument('-l', '--log', type=str, dest="logfile",
                                 required=False,
                                 default=argparse.SUPPRESS,
                                 help=log_argument_help_msg)

        qcheck_parser.add_argument('-s', '--steps', action="store_true",
                                   dest="print_steps", help='Print steps.')

        qcheck_parser.add_argument('--quiet-build',
                                   action='store_true',
                                   default=False,
                                   required=False,
                                   help='Do not print out the output of the '
                                        'original build')
        qcheck_parser.add_argument('-i', '--skip', type=str, dest="skipfile",
                                   default=argparse.SUPPRESS,
                                   required=False, help='Path to skip file.')
        qcheck_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                   default=1, required=False,
                                   help=jobs_help_msg)
        qcheck_parser.add_argument('-u', '--suppress', type=str,
                                   dest="suppress",
                                   default=argparse.SUPPRESS,
                                   required=False,
                                   help=suppress_help_msg)
        add_analyzer_arguments(qcheck_parser)
        qcheck_parser.set_defaults(func=arg_handler.handle_quickcheck)

        # --------------------------------------
        # Log commands.
        logging_p = subparsers.add_parser('log',
                                          formatter_class=ADHF,
                                          help='Runs the given build '
                                               'command. During the '
                                               'build the compilation '
                                               'commands are collected '
                                               'and stored into a '
                                               'compilation command '
                                               'json file '
                                               '(no analysis is done '
                                               'during the build).')

        logging_p.add_argument('-o', '--output', type=str, dest="logfile",
                               default=argparse.SUPPRESS,
                               required=True,
                               help='Path to the log file.')

        logging_p.add_argument('-b', '--build', type=str, dest="command",
                               default=argparse.SUPPRESS,
                               required=True, help='Build command.')

        logging_p.set_defaults(func=arg_handler.handle_log)

        # --------------------------------------
        # Checkers parser.
        checker_p = subparsers.add_parser('checkers',
                                          formatter_class=ADHF,
                                          help='List the available checkers '
                                               'for the supported analyzers '
                                               'and show their default status '
                                               '(+ for being enabled, '
                                               '- for being disabled by '
                                               'default).')

        checker_p.add_argument('--analyzers', nargs='+',
                               dest="analyzers", required=False,
                               help='Select which analyzer checkers '
                               'should be listed.\nCurrently supported '
                               'analyzers:\n' + analyzers)

        checker_p.set_defaults(func=arg_handler.handle_list_checkers)

        # --------------------------------------
        # Server.
        server_parser = subparsers.add_parser('server',
                                              formatter_class=ADHF,
                                              help='Start the codechecker '
                                                   'web server.')
        server_parser.add_argument('-w', '--workspace', type=str,
                                   dest="workspace",
                                   default=util.get_default_workspace(),
                                   help=workspace_help_msg)

        server_parser.add_argument('-v', '--view-port', type=int,
                                   dest="view_port",
                                   default=8001, required=False,
                                   help='Port used for viewing.')

        server_parser.add_argument('-u', '--suppress', type=str,
                                   dest="suppress",
                                   required=False,
                                   help='Path to suppress file.')

        server_parser.add_argument('--not-host-only', action="store_true",
                                   dest="not_host_only",
                                   help='Viewing the results is possible not'
                                        'only by browsers or clients'
                                        ' started locally.')

        server_parser.add_argument('--check-port', type=int, dest="check_port",
                                   default=None, required=False,
                                   help='Port used for checking.')

        server_parser.add_argument('--check-address', type=str,
                                   dest="check_address", default="localhost",
                                   required=False, help='Server address.')

        add_database_arguments(server_parser)
        server_parser.set_defaults(func=arg_handler.handle_server)

        # --------------------------------------
        # Cmd_line.
        cmd_line_parser = subparsers.add_parser('cmd',
                                                help='Command line client')
        cmd_line_client.register_client_command_line(cmd_line_parser)

        # --------------------------------------
        # Debug parser.
        debug_parser = subparsers.add_parser('debug',
                                             formatter_class=ADHF,
                                             help='Generate gdb debug dump '
                                                  'files for all the failed '
                                                  'compilation commands in '
                                                  'the last analyzer run.\n'
                                                  'Requires a database with '
                                                  'the failed compilation '
                                                  'commands')

        debug_parser.add_argument('-w', '--workspace', type=str,
                                  dest="workspace",
                                  default=util.get_default_workspace(),
                                  help=workspace_help_msg)

        debug_parser.add_argument('-f', '--force', action="store_true",
                                  dest="force", required=False, default=False,
                                  help='Overwrite already generated files.')

        add_database_arguments(debug_parser)
        debug_parser.set_defaults(func=arg_handler.handle_debug)

        # --------------------------------------
        # Plist parser.
        plist_parser = subparsers.add_parser('plist',
                                             formatter_class=ADHF,
                                             help='Parse plist files in '
                                                  'the given directory.')

        plist_parser.add_argument('-w', '--workspace', type=str,
                                  dest="workspace",
                                  default=util.get_default_workspace(),
                                  help=workspace_help_msg)

        plist_parser.add_argument('-n', '--name', type=str,
                                  dest="name", required=True,
                                  default=argparse.SUPPRESS,
                                  help=name_help_msg)

        plist_parser.add_argument('-d', '--directory', type=str,
                                  dest="directory", required=True,
                                  help='Path of a directory containing plist '
                                  ' files to parse.')

        plist_parser.add_argument('-j', '--jobs', type=int, dest="jobs",
                                  default=1, required=False,
                                  help=jobs_help_msg)

        plist_parser.add_argument('-s', '--steps', action="store_true",
                                  dest="print_steps", help='Print steps.')

        plist_parser.add_argument('--stdout', action="store_true",
                                  dest="stdout",
                                  required=False, default=False,
                                  help='Print results to stdout instead of '
                                       'storing to the database.')

        plist_parser.add_argument('--force', action="store_true",
                                  dest="force", default=False, required=False,
                                  help='Delete analysis results form the '
                                       'database if a run with the given '
                                       'name already exists')

        add_database_arguments(plist_parser)
        plist_parser.set_defaults(func=arg_handler.handle_plist)

        # --------------------------------------
        # Package version info.
        version_parser = subparsers.add_parser('version',
                                               help='Print package version '
                                                    'information.')
        version_parser.set_defaults(func=arg_handler.handle_version_info)

        args = parser.parse_args()
        args.func(args)

    except KeyboardInterrupt as kb_err:
        LOG.info(str(kb_err))
        LOG.info("Interrupted by user...")
        sys.exit(1)

    except shared.ttypes.RequestFailed as thrift_ex:
        LOG.info("Server error.")
        LOG.info("Error code: " + str(thrift_ex.error_code))
        LOG.info("Error message: " + str(thrift_ex.message))
        sys.exit(1)

    # Handle all exception, but print stacktrace. It is needed for atexit.
    # atexit does not work correctly when an unhandled exception occurred.
    # So in this case, the servers left running when the script exited.
    except Exception:
        import traceback
        traceback.print_exc(file=sys.stdout)
        sys.exit(2)