def main(argv=None):
    # Register a couple functions as targets.
    for name in ('configure', 'build'):
        try:
            fbuild.target.register(name=name)(getattr(fbuildroot, name))
        except __HOLE__:
            pass

    # Get the prune handlers.
    try:
        prune_get_all = fbuildroot.prune_get_all
    except:
        def prune_get_all(ctx, root=None):
            files = set()
            if root is None:
                root = ctx.buildroot
            for dirpath, dirnames, filenames in root.walk():
                files.update(map(dirpath.__truediv__, filenames))
            return files

    try:
        prune_get_bad = fbuildroot.prune_get_bad
    except:
        def prune_get_bad(ctx, files):
            return files

    # --------------------------------------------------------------------------

    ctx = parse_args(sys.argv if argv is None else argv)

    # --------------------------------------------------------------------------
    # Replace the ctrl-c signal handler with one that will shut down the
    # scheduler before moving on.

    old_handler = signal.getsignal(signal.SIGINT)

    def handle_interrupt(signum, frame):
        ctx.scheduler.shutdown()
        old_handler(signum, frame)

    signal.signal(signal.SIGINT, handle_interrupt)

    # --------------------------------------------------------------------------

    # If we don't wrap this in a try...finally block to shutdown the scheduler
    # after all else finishes, fbuild will hang indefinitely
    try:

        # If the fbuildroot doesn't exist, error out. We do this now so that
        # there's a chance to ask fbuild for help first.
        if isinstance(fbuildroot, Exception):
            if not os.path.exists('fbuildroot.py'):
                raise fbuild.Error('Cannot find fbuildroot.py')
            else:
                raise fbuildroot

        # Exit early if we want to clean the buildroot.
        if ctx.options.clean_buildroot:
            # Only try to clean the buildroot if it actually exists.
            if ctx.options.buildroot.exists():
                ctx.options.buildroot.rmtree()
            return

        # Prep the context for running.
        ctx.create_buildroot()
        ctx.load_configuration()

        # ... and then run the build.
        try:
            result = build(ctx)
            if ctx.options.prune:
                ctx.prune(prune_get_all, prune_get_bad)
        except fbuild.Error as e:
            ctx.logger.log(e, color='red')
            sys.exit(1)
        except KeyboardInterrupt:
            # It appears that we can't reliably shutdown the scheduler's threads
            # when SIGINT is emitted, because python may raise KeyboardInterrupt
            # between the finally and the mutex.release call.  So, we can find
            # ourselves exiting functions with the lock still held.  This could
            # then cause deadlocks if that lock was ever acquired again.  Oiy.
            print('Interrupted, saving state...')
            raise
        finally:
            ctx.save_configuration()
            ctx.db.shutdown()
    finally:
        ctx.scheduler.shutdown()

    return result
dataset/ETHPy150Open felix-lang/fbuild/lib/fbuild/main.py/main