Ejemplo n.º 1
0
def gdb(fips_dir, proj_dir, cfg_name, target=None, target_args=None):
    """debug a single target with gdb"""

    # prepare
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        for cfg in configs:
            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir,
                                                        proj_dir,
                                                        cfg,
                                                        print_errors=True)
            if config_valid:
                deploy_dir = util.get_deploy_dir(fips_dir, proj_name,
                                                 cfg['name'])
                log.colored(log.YELLOW, "=== gdb: {}".format(cfg['name']))
                cmdLine = ['gdb', "-ex", "run", "--args", target]
                if target_args:
                    cmdLine.extend(target_args)
                try:
                    subprocess.call(args=cmdLine, cwd=deploy_dir)
                except OSError:
                    log.error("Failed to execute gdb (not installed?)")
            else:
                log.error("Config '{}' not valid in this environment".format(
                    cfg['name']))
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))

    return True
Ejemplo n.º 2
0
def configure(fips_dir, proj_dir, cfg_name):
    """run ccmake or cmake-gui on the provided project and config

    :param fips_dir:    absolute fips path
    :param proj_dir:    absolute project dir
    :cfg_name:          build config name
    """

    dep.fetch_imports(fips_dir, proj_dir)
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)
    dep.gather_and_write_imports(fips_dir, proj_dir, cfg_name)

    # load configs, if more then one, only use first one
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        cfg = configs[0]
        log.colored(log.YELLOW, '=== configuring: {}'.format(cfg['name']))

        # generate build files
        if not gen_project(fips_dir, proj_dir, cfg, True):
            log.error("Failed to generate '{}' of project '{}'".format(
                cfg['name'], proj_name))

        # run ccmake or cmake-gui
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg['name'])
        if ccmake.check_exists(fips_dir):
            ccmake.run(build_dir)
        elif cmake_gui.check_exists(fips_dir):
            cmake_gui.run(build_dir)
        else:
            log.error(
                "Neither 'ccmake' nor 'cmake-gui' found (run 'fips diag')")
    else:
        log.error("No configs found for '{}'".format(cfg_name))
Ejemplo n.º 3
0
Archivo: gdb.py Proyecto: floooh/fips
def gdb(fips_dir, proj_dir, cfg_name, target=None, target_args=None) :
    """debug a single target with gdb"""

    # prepare
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        for cfg in configs :
            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir, proj_dir, cfg, print_errors = True)
            if config_valid :
                deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg['name'])
                log.colored(log.YELLOW, "=== gdb: {}".format(cfg['name']))
                cmdLine = ['gdb', "-ex", "run", "--args", target]
                if target_args :
                    cmdLine.extend(target_args)
                try:
                    subprocess.call(args = cmdLine, cwd = deploy_dir)
                except OSError :
                    log.error("Failed to execute gdb (not installed?)")
            else :
                log.error("Config '{}' not valid in this environment".format(cfg['name']))
    else :
        log.error("No valid configs found for '{}'".format(cfg_name))

    return True
Ejemplo n.º 4
0
def clean(fips_dir, proj_dir, cfg_name):
    """clean build files

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute project path
    :param cfg_name:    config name (or pattern)
    """
    proj_name = util.get_project_name_from_dir(proj_dir)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        num_cleaned_configs = 0
        for cfg in configs:
            build_dir = util.get_build_dir(fips_dir, proj_name, cfg['name'])
            build_dir_exists = os.path.isdir(build_dir)
            deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg['name'])
            deploy_dir_exists = os.path.isdir(deploy_dir)

            if build_dir_exists or deploy_dir_exists:
                log.colored(log.YELLOW, "=== clean: {}".format(cfg['name']))
                num_cleaned_configs += 1

            if build_dir_exists:
                shutil.rmtree(build_dir)
                log.info("  deleted '{}'".format(build_dir))

            if deploy_dir_exists:
                shutil.rmtree(deploy_dir)
                log.info("  deleted '{}'".format(deploy_dir))
        if num_cleaned_configs == 0:
            log.colored(log.YELLOW,
                        "=== clean: nothing to clean for {}".format(cfg_name))
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))
Ejemplo n.º 5
0
def configure(fips_dir, proj_dir, cfg_name) :
    """run ccmake or cmake-gui on the provided project and config

    :param fips_dir:    absolute fips path
    :param proj_dir:    absolute project dir
    :cfg_name:          build config name
    """

    dep.fetch_imports(fips_dir, proj_dir)
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)
    dep.gather_and_write_imports(fips_dir, proj_dir)

    # load configs, if more then one, only use first one
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        cfg = configs[0]
        log.colored(log.YELLOW, '=== configuring: {}'.format(cfg['name']))

        # generate build files
        if not gen_project(fips_dir, proj_dir, cfg, True) :
            log.error("Failed to generate '{}' of project '{}'".format(cfg['name'], proj_name))

        # run ccmake or cmake-gui
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
        if ccmake.check_exists(fips_dir) :
            ccmake.run(build_dir)
        elif cmake_gui.check_exists(fips_dir) :
            cmake_gui.run(build_dir)
        else :
            log.error("Neither 'ccmake' nor 'cmake-gui' found (run 'fips diag')")
    else :
        log.error("No configs found for '{}'".format(cfg_name))
Ejemplo n.º 6
0
def run(fips_dir, proj_dir, args):
    """run the 'physx' verb"""
    if len(args) > 0:
        noun = args[0]
        if noun == 'build':

            # FIXME all of this only works on windows at the moment and is super hacky

            if len(args) != 2:
                log.error("expected compiler target (win-vs15, win-vs16)")

            preset = util.fix_path(os.path.dirname(os.path.abspath(
                __file__))) + "/physx-presets/" + "fips" + args[1] + ".xml"
            if not os.path.isfile(preset):
                log.error("unrecognized compiler target")
            shutil.copy2(preset,
                         proj_dir + "/../physx/physx/buildtools/presets/")
            subprocess.call(proj_dir +
                            "/../physx/physx/generate_projects.bat fips" +
                            args[1])

            # figure out a version number for vswhere
            version = args[1][6:]
            version_next = str(int(version) + 1)
            version = version + ".0," + version_next + ".0"
            #use vswhere to figure out where vs is
            devenvPath = subprocess.check_output(
                proj_dir + "/../physx/externals/vswhere/vswhere -version [" +
                version + "] -property productPath").decode("utf-8").rstrip()

            devenvPath = util.fix_path(devenvPath)
            if not os.path.isfile(devenvPath):
                log.error("could not detect visual studio installation")
            log.info("Using Visual Studio from" + devenvPath)
            log.info("Compiling PhysX, this might take a while")
            log.info("Building debug version")
            subprocess.call(devenvPath + " " + proj_dir +
                            "/../physx/physx/compiler/fips" + args[1] +
                            "/PhysXSDK.sln /Build debug /Project INSTALL")
            log.info("Building release version")
            subprocess.call(devenvPath + " " + proj_dir +
                            "/../physx/physx/compiler/fips" + args[1] +
                            "/PhysXSDK.sln /Build release /Project INSTALL")
        if noun == 'deploy':
            ps_deploy = util.get_workspace_dir(
                fips_dir) + "/fips-deploy/physx/bin/"
            cur_cfg = settings.get(proj_dir, "config")
            cfg = config.load(fips_dir, proj_dir, cur_cfg)[0]
            px_target = cfg['defines']['PX_TARGET']
            target_dir = util.get_deploy_dir(
                fips_dir, util.get_project_name_from_dir(proj_dir), cur_cfg)
            for dll in glob.glob(ps_deploy + px_target + "/debug/*.dll"):
                shutil.copy2(dll, target_dir)
            for dll in glob.glob(ps_deploy + px_target + "/release/*.dll"):
                shutil.copy2(dll, target_dir)
    else:

        def run(fips_dir, proj_dir, args):
            log.error("Not supported")
Ejemplo n.º 7
0
def build(fips_dir, proj_dir, cfg_name, target=None, build_tool_args=None):
    """perform a build of config(s) in project

    :param fips_dir:        absolute path of fips
    :param proj_dir:        absolute path of project dir
    :param cfg_name:        config name or pattern
    :param target:          optional target name (build all if None)
    :param build_tool_args: optional string array of cmdline args forwarded to the build tool
    :returns:               True if build was successful
    """

    # prepare
    dep.fetch_imports(fips_dir, proj_dir)
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)
    dep.gather_and_write_imports(fips_dir, proj_dir, cfg_name)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    num_valid_configs = 0
    if configs:
        for cfg in configs:
            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir,
                                                        proj_dir,
                                                        cfg,
                                                        print_errors=True)
            if config_valid:
                log.colored(log.YELLOW, "=== building: {}".format(cfg['name']))

                if not gen_project(fips_dir, proj_dir, cfg, False):
                    log.error("Failed to generate '{}' of project '{}'".format(
                        cfg['name'], proj_name))

                # select and run build tool
                build_dir = util.get_build_dir(fips_dir, proj_name,
                                               cfg['name'])
                num_jobs = settings.get(proj_dir, 'jobs')
                result = cmake.run_build(fips_dir, target, cfg['build_type'],
                                         build_dir, num_jobs, build_tool_args)
                if result:
                    num_valid_configs += 1
                else:
                    log.error(
                        "Failed to build config '{}' of project '{}'".format(
                            cfg['name'], proj_name))
            else:
                log.error("Config '{}' not valid in this environment".format(
                    cfg['name']))
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))

    if num_valid_configs != len(configs):
        log.error('{} out of {} configs failed!'.format(
            len(configs) - num_valid_configs, len(configs)))
        return False
    else:
        log.colored(log.GREEN, '{} configs built'.format(num_valid_configs))
        return True
Ejemplo n.º 8
0
def build(fips_dir, proj_dir, cfg_name, target=None) :
    """perform a build of config(s) in project

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute path of project dir
    :param cfg_name:    config name or pattern
    :param target:      optional target name (build all if None)
    :returns:           True if build was successful
    """

    # prepare
    dep.fetch_imports(fips_dir, proj_dir)
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)
    dep.gather_and_write_imports(fips_dir, proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    num_valid_configs = 0
    if configs :
        for cfg in configs :
            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir, cfg, print_errors=True)
            if config_valid :
                log.colored(log.YELLOW, "=== building: {}".format(cfg['name']))

                if not gen_project(fips_dir, proj_dir, cfg, False) :
                    log.error("Failed to generate '{}' of project '{}'".format(cfg['name'], proj_name))

                # select and run build tool
                build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
                num_jobs = settings.get(proj_dir, 'jobs')
                result = False
                if cfg['build_tool'] == make.name :
                    result = make.run_build(fips_dir, target, build_dir, num_jobs)
                elif cfg['build_tool'] == ninja.name :
                    result = ninja.run_build(fips_dir, target, build_dir, num_jobs)
                elif cfg['build_tool'] == xcodebuild.name :
                    result = xcodebuild.run_build(fips_dir, target, cfg['build_type'], build_dir, num_jobs)
                else :
                    result = cmake.run_build(fips_dir, target, cfg['build_type'], build_dir)
                
                if result :
                    num_valid_configs += 1
                else :
                    log.error("Failed to build config '{}' of project '{}'".format(cfg['name'], proj_name))
            else :
                log.error("Config '{}' not valid in this environment".format(cfg['name']))
    else :
        log.error("No valid configs found for '{}'".format(cfg_name))

    if num_valid_configs != len(configs) :
        log.error('{} out of {} configs failed!'.format(len(configs) - num_valid_configs, len(configs)))
        return False      
    else :
        log.colored(log.GREEN, '{} configs built'.format(num_valid_configs))
        return True
Ejemplo n.º 9
0
def run(fips_dir, proj_dir, args):
    if util.is_valid_project_dir(proj_dir):
        cfg_name = settings.get(proj_dir, 'config')
        cfg = config.load(fips_dir, proj_dir, cfg_name)[0]
        res = cmake.get_codemodel(fips_dir, proj_dir, cfg)
        if res is not None:
            print(json.dumps(res, indent=2, separators=(',', ':')))
    else:
        log.error("must be run from a project directory")
Ejemplo n.º 10
0
Archivo: open.py Proyecto: rbxnk/fips
def run(fips_dir, proj_dir, args):
    """run the 'open' verb (opens project in IDE)"""
    if not util.is_valid_project_dir(proj_dir):
        log.error('must be run in a project directory')
    proj_name = util.get_project_name_from_dir(proj_dir)
    cfg_name = None
    if len(args) > 0:
        cfg_name = args[0]
    if not cfg_name:
        cfg_name = settings.get(proj_dir, 'config')

    # check the cmake generator of this config
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        # hmm, only look at first match, 'open' doesn't
        # make sense with config-patterns
        cfg = configs[0]

        # find build dir, if it doesn't exist, generate it
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg['name'])
        if not os.path.isdir(build_dir):
            log.warn("build dir not found, generating...")
            project.gen(fips_dir, proj_dir, cfg['name'])

        # first check if this is a VSCode project
        if cfg['build_tool'] == 'vscode_cmake':
            vscode.run(proj_dir)
            return
        # check if this is a CLion project
        if cfg['build_tool'] == 'clion':
            clion.run(proj_dir)
            return
        # try to open as Xcode project
        proj = glob.glob(build_dir + '/*.xcodeproj')
        if proj:
            subprocess.call('open "{}"'.format(proj[0]), shell=True)
            return
        # try to open as VS project
        proj = glob.glob(build_dir + '/*.sln')
        if proj:
            subprocess.call('cmd /c start {}'.format(proj[0]), shell=True)
            return
        # try to open as eclipse project
        proj = glob.glob(build_dir + '/.cproject')
        if proj:
            subprocess.call(
                'eclipse -nosplash --launcher.timeout 60 -application org.eclipse.cdt.managedbuilder.core.headlessbuild -import "{}"'
                .format(build_dir),
                shell=True)
            subprocess.call('eclipse', shell=True)
            return

        log.error("don't know how to open a '{}' project in {}".format(
            cfg['generator'], build_dir))
    else:
        log.error("config '{}' not found".format(cfg_name))
Ejemplo n.º 11
0
Archivo: open.py Proyecto: floooh/fips
def run(fips_dir, proj_dir, args) :
    """run the 'open' verb (opens project in IDE)"""
    if not util.is_valid_project_dir(proj_dir) :
        log.error('must be run in a project directory')
    proj_name = util.get_project_name_from_dir(proj_dir)
    cfg_name = None
    if len(args) > 0 :
        cfg_name = args[0]
    if not cfg_name :
        cfg_name = settings.get(proj_dir, 'config')

    # check the cmake generator of this config
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        # hmm, only look at first match, 'open' doesn't
        # make sense with config-patterns
        cfg = configs[0]

        # find build dir, if it doesn't exist, generate it
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg['name'])
        if not os.path.isdir(build_dir) :
            log.warn("build dir not found, generating...")
            project.gen(fips_dir, proj_dir, cfg['name'])

        # first check if this is a VSCode project
        if cfg['build_tool'] == 'vscode_cmake':
            vscode.run(proj_dir)
            return
        # check if this is a CLion project
        if cfg['build_tool'] == 'clion':
            clion.run(proj_dir)
            return
        # try to open as Xcode project
        proj = glob.glob(build_dir + '/*.xcodeproj')
        if proj :
            subprocess.call('open "{}"'.format(proj[0]), shell=True)
            return
        # try to open as VS project
        proj = glob.glob(build_dir + '/*.sln')
        if proj :
            subprocess.call('cmd /c start {}'.format(proj[0]), shell=True)
            return
        # try to open as eclipse project
        proj = glob.glob(build_dir + '/.cproject')
        if proj :
            subprocess.call('eclipse -nosplash --launcher.timeout 60 -application org.eclipse.cdt.managedbuilder.core.headlessbuild -import "{}"'.format(build_dir), shell=True)
            subprocess.call('eclipse', shell=True)
            return

        log.error("don't know how to open a '{}' project in {}".format(cfg['generator'], build_dir))
    else :
        log.error("config '{}' not found".format(cfg_name))
Ejemplo n.º 12
0
def check_configs(fips_dir, proj_dir):
    """find configs and check if they are valid"""
    log.colored(log.YELLOW, '=== configs:')
    dirs = [fips_dir]
    configs = config.load(fips_dir, proj_dir, '*')
    for cfg in configs:
        log.colored(log.BLUE, cfg['name'])
        valid, errors = config.check_config_valid(fips_dir, proj_dir, cfg)
        if valid:
            log.colored(log.GREEN, '  ok')
        else:
            for error in errors:
                log.info('  {}'.format(error))
Ejemplo n.º 13
0
def check_configs(fips_dir, proj_dir) :
    """find configs and check if they are valid"""
    log.colored(log.YELLOW, '=== configs:')
    dirs = [ fips_dir ]
    configs = config.load(fips_dir, proj_dir, '*')
    for cfg in configs :
        log.colored(log.BLUE, cfg['name'])
        valid, errors = config.check_config_valid(fips_dir, cfg)
        if valid :
            log.colored(log.GREEN, '  ok')
        else :
            for error in errors :
                log.info('  {}'.format(error))
Ejemplo n.º 14
0
def make_clean(fips_dir, proj_dir, cfg_name):
    """perform a 'make clean' on the project

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute path of project dir
    :param cfg_name:    config name or pattern
    """

    proj_name = util.get_project_name_from_dir(proj_dir)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    num_valid_configs = 0
    if configs:
        for cfg in configs:
            config_valid, _ = config.check_config_valid(fips_dir,
                                                        proj_dir,
                                                        cfg,
                                                        print_errors=True)
            if config_valid:
                log.colored(log.YELLOW, "=== cleaning: {}".format(cfg['name']))

                build_dir = util.get_build_dir(fips_dir, proj_name,
                                               cfg['name'])
                result = False
                if cfg['build_tool'] == make.name:
                    result = make.run_clean(fips_dir, build_dir)
                elif cfg['build_tool'] == ninja.name:
                    result = ninja.run_clean(fips_dir, build_dir)
                elif cfg['build_tool'] == xcodebuild.name:
                    result = xcodebuild.run_clean(fips_dir, build_dir)
                else:
                    result = cmake.run_clean(fips_dir, build_dir)

                if result:
                    num_valid_configs += 1
                else:
                    log.error(
                        "Failed to clean config '{}' of project '{}'".format(
                            cfg['name'], proj_name))
            else:
                log.error("Config '{}' not valid in this environment".format(
                    cfg['name']))
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))

    if num_valid_configs != len(configs):
        log.error('{} out of {} configs failed!'.format(
            len(configs) - num_valid_configs, len(configs)))
        return False
    else:
        log.colored(log.GREEN, '{} configs cleaned'.format(num_valid_configs))
        return True
Ejemplo n.º 15
0
def get_target_list(fips_dir, proj_dir, cfg_name):
    """get project targets config name, only works
    if a cmake run was performed before

    :param fips_dir:        absolute path to fips
    :param proj_dir:        absolute project path
    :param cfg_name:        the config name
    :returns:   (success, targets)
    """
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        return util.get_cfg_target_list(fips_dir, proj_dir, configs[0])
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))
Ejemplo n.º 16
0
def gen(fips_dir, proj_dir, cfg_name) :
    """generate build files with cmake

    :param fips_dir:    absolute path to fips
    :param proj_dir:    absolute path to project
    :param cfg_name:    config name or pattern (e.g. osx-make-debug)
    :returns:           True if successful
    """

    # prepare
    dep.fetch_imports(fips_dir, proj_dir)
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)
    dep.gather_and_write_imports(fips_dir, proj_dir, cfg_name)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    fips_yml_defines = dep.get_fips_yml_defines(proj_dir)

    num_valid_configs = 0
    if configs :
        for cfg in configs :

            # Merge fips.yml defines into config defines
            if fips_yml_defines:
                if 'defines' in cfg and cfg['defines']:
                    cfg['defines'].update(fips_yml_defines)
                else:
                    cfg['defines'] = fips_yml_defines

            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir, proj_dir, cfg, print_errors = True)
            if config_valid :
                if gen_project(fips_dir, proj_dir, cfg, True) :
                    num_valid_configs += 1
                else :
                    log.error("failed to generate build files for config '{}'".format(cfg['name']), False)
            else :
                log.error("'{}' is not a valid config".format(cfg['name']), False)
    else :
        log.error("No configs found for '{}'".format(cfg_name))

    if num_valid_configs != len(configs) :
        log.error('{} out of {} configs failed!'.format(len(configs) - num_valid_configs, len(configs)))
        return False      
    else :
        log.colored(log.GREEN, '{} configs generated'.format(num_valid_configs))
        return True
Ejemplo n.º 17
0
def valgrind(fips_dir, proj_dir, cfg_name, target, target_args):
    """debug a single target with valgrind"""

    # prepare
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        for cfg in configs:
            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir,
                                                        proj_dir,
                                                        cfg,
                                                        print_errors=True)
            if config_valid:
                deploy_dir = util.get_deploy_dir(fips_dir, proj_name,
                                                 cfg['name'])
                valgrind_bin = settings.get(proj_dir, 'valgrind')
                if not valgrind_bin:
                    valgrind_bin = 'valgrind'
                log.colored(
                    log.YELLOW,
                    "=== valgrind: {} ({})".format(cfg['name'], valgrind_bin))
                cmd_line = valgrind_bin
                if target_args:
                    cmd_line += ' ' + ' '.join(target_args)
                else:
                    cmd_line += ' ' + '--leak-check=no'
                    cmd_line += ' ' + '--show-reachable=yes'
                    cmd_line += ' ' + '--track-fds=yes'
                    cmd_line += ' ' + '--run-libc-freeres=no'
                    cmd_line += ' ' + "--log-file={}/valgrind-{}.log".format(
                        proj_dir, target)
                cmd_line += ' ' + "./{}".format(target)
                #log.colored(log.GREEN, "cmdline: {}".format(cmd_line))
                subprocess.call(args=cmd_line, cwd=deploy_dir, shell=True)
            else:
                log.error("Config '{}' not valid in this environment".format(
                    cfg['name']))
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))

    return True
Ejemplo n.º 18
0
def make_clean(fips_dir, proj_dir, cfg_name) :
    """perform a 'make clean' on the project

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute path of project dir
    :param cfg_name:    config name or pattern
    """

    proj_name = util.get_project_name_from_dir(proj_dir)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    num_valid_configs = 0
    if configs :
        for cfg in configs :
            config_valid, _ = config.check_config_valid(fips_dir, cfg, print_errors=True)
            if config_valid :
                log.colored(log.YELLOW, "=== cleaning: {}".format(cfg['name']))

                build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
                result = False
                if cfg['build_tool'] == make.name :
                    result = make.run_clean(fips_dir, build_dir)
                elif cfg['build_tool'] == ninja.name :
                    result = ninja.run_clean(fips_dir, build_dir)
                elif cfg['build_tool'] == xcodebuild.name :
                    result = xcodebuild.run_clean(fips_dir, build_dir)
                else :
                    result = cmake.run_clean(fips_dir, build_dir)
                    
                if result :
                    num_valid_configs += 1
                else :
                    log.error("Failed to clean config '{}' of project '{}'".format(cfg['name'], proj_name))
            else :
                log.error("Config '{}' not valid in this environment".format(cfg['name']))
    else :
        log.error("No valid configs found for '{}'".format(cfg_name))

    if num_valid_configs != len(configs) :
        log.error('{} out of {} configs failed!'.format(len(configs) - num_valid_configs, len(configs)))
        return False      
    else :
        log.colored(log.GREEN, '{} configs cleaned'.format(num_valid_configs))
        return True
Ejemplo n.º 19
0
def gen(fips_dir, proj_dir, cfg_name) :
    """generate build files with cmake

    :param fips_dir:    absolute path to fips
    :param proj_dir:    absolute path to project
    :param cfg_name:    config name or pattern (e.g. osx-make-debug)
    :returns:           True if successful
    """

    # prepare
    dep.fetch_imports(fips_dir, proj_dir)
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)
    dep.gather_and_write_imports(fips_dir, proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    num_valid_configs = 0
    if configs :
        for cfg in configs :
            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir, cfg, print_errors = True)
            if config_valid :
                if gen_project(fips_dir, proj_dir, cfg, True) :
                    num_valid_configs += 1
                else :
                    log.error("failed to generate build files for config '{}'".format(cfg['name']), False)
            else :
                log.error("'{}' is not a valid config".format(cfg['name']), False)
    else :
        log.error("No configs found for '{}'".format(cfg_name))

    if num_valid_configs != len(configs) :
        log.error('{} out of {} configs failed!'.format(len(configs) - num_valid_configs, len(configs)))
        return False      
    else :
        log.colored(log.GREEN, '{} configs generated'.format(num_valid_configs))
        return True
Ejemplo n.º 20
0
def run(fips_dir, proj_dir, args) :
    """run the 'open' verb (opens project in IDE)"""
    if not util.is_valid_project_dir(proj_dir) :
        log.error('must be run in a project directory')
    proj_name = util.get_project_name_from_dir(proj_dir)
    cfg_name = None
    if len(args) > 0 :
        cfg_name = args[0]
    if not cfg_name :
        cfg_name = settings.get(proj_dir, 'config')
        
    # check the cmake generator of this config
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        # hmm, only look at first match, 'open' doesn't
        # make sense with config-patterns
        cfg = configs[0]

        # find build dir, if it doesn't exist, generate it
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
        if not os.path.isdir(build_dir) :
            log.warn("build dir not found, generating...")
            project.gen(fips_dir, proj_dir, cfg['name'])
        
        # try to open as Xcode project
        proj = glob.glob(build_dir + '/*.xcodeproj')
        if proj :
            subprocess.call('open {}'.format(proj[0]), shell=True)
        else :
            # try to open as VS project
            proj = glob.glob(build_dir + '/*.sln')
            if proj :
                subprocess.call('cmd /c start {}'.format(proj[0]), shell=True)
            else :
                log.error("don't know how to open a '{}' project".format(cfg['generator']))
    else :
        log.error("config '{}' not found".format(cfg_name))
Ejemplo n.º 21
0
def valgrind(fips_dir, proj_dir, cfg_name, target, target_args) :
    """debug a single target with valgrind"""

    # prepare
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        for cfg in configs :
            # check if config is valid
            config_valid, _ = config.check_config_valid(fips_dir, proj_dir, cfg, print_errors = True)
            if config_valid :
                deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg['name'])
                valgrind_bin = settings.get(proj_dir, 'valgrind')
                if not valgrind_bin :
                    valgrind_bin = 'valgrind'
                log.colored(log.YELLOW, "=== valgrind: {} ({})".format(cfg['name'], valgrind_bin))
                cmd_line = valgrind_bin
                if target_args :
                    cmd_line += ' ' + ' '.join(target_args)
                else :
                    cmd_line += ' ' + '--leak-check=no'
                    cmd_line += ' ' + '--show-reachable=yes'
                    cmd_line += ' ' + '--track-fds=yes'
                    cmd_line += ' ' + '--run-libc-freeres=no'
                    cmd_line += ' ' + "--log-file={}/valgrind-{}.log".format(proj_dir, target)
                cmd_line += ' ' + "./{}".format(target)
                #log.colored(log.GREEN, "cmdline: {}".format(cmd_line))
                subprocess.call(args = cmd_line, cwd = deploy_dir, shell = True)
            else :
                log.error("Config '{}' not valid in this environment".format(cfg['name']))
    else :
        log.error("No valid configs found for '{}'".format(cfg_name))

    return True
Ejemplo n.º 22
0
def run(fips_dir, proj_dir, args):
    """run the 'open' verb (opens project in IDE)"""
    if not util.is_valid_project_dir(proj_dir):
        log.error('must be run in a project directory')
    proj_name = util.get_project_name_from_dir(proj_dir)
    cfg_name = None
    if len(args) > 0:
        cfg_name = args[0]
    if not cfg_name:
        cfg_name = settings.get(proj_dir, 'config')

    # check the cmake generator of this config
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        # hmm, only look at first match, 'open' doesn't
        # make sense with config-patterns
        cfg = configs[0]

        # find build dir, if it doesn't exist, generate it
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
        if not os.path.isdir(build_dir):
            log.warn("build dir not found, generating...")
            project.gen(fips_dir, proj_dir, cfg['name'])

        if 'Xcode' in cfg['generator']:
            # find the Xcode project
            proj = glob.glob(build_dir + '/*.xcodeproj')
            subprocess.call(['open', proj[0]])
        elif 'Visual Studio' in cfg['generator']:
            # find the VisualStudio project file
            proj = glob.glob(build_dir + '/*.sln')
            subprocess.call(['cmd', '/c', 'start', proj[0]])
        else:
            log.error("don't know how to open a '{}' project".format(
                cfg['generator']))
    else:
        log.error("config '{}' not found".format(cfg_name))
Ejemplo n.º 23
0
def get_target_list(fips_dir, proj_dir, cfg_name) :
    """get project targets config name, only works
    if a cmake run was performed before

    :param fips_dir:        absolute path to fips
    :param proj_dir:        absolute project path
    :param cfg_name:        the config name
    :returns:   (success, targets)
    """
    proj_name = util.get_project_name_from_dir(proj_dir)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        cfg = configs[0]
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
        targets_path = build_dir + '/fips_targets.yml'
        if os.path.isfile(targets_path) :
            targets = []
            with open(targets_path) as f :
                targets = yaml.load(f)
            return True, targets
        else :
            return False, []
    else :
        log.error("No valid configs found for '{}'".format(cfg_name))
Ejemplo n.º 24
0
def clean(fips_dir, proj_dir, cfg_name) :
    """clean build files

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute project path
    :param cfg_name:    config name (or pattern)
    """
    proj_name = util.get_project_name_from_dir(proj_dir)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        for cfg in configs :
            log.colored(log.YELLOW, "=== clean: {}".format(cfg['name']))

            build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
            if os.path.isdir(build_dir) :
                shutil.rmtree(build_dir)
                log.info("  deleted '{}'".format(build_dir))

            deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg)
            if os.path.isdir(deploy_dir) :
                shutil.rmtree(deploy_dir)
                log.info("  deleted '{}'".format(deploy_dir))
    else :
        log.error("No valid configs found for '{}'".format(cfg_name))
Ejemplo n.º 25
0
def get_target_list(fips_dir, proj_dir, cfg_name):
    """get project targets config name, only works
    if a cmake run was performed before

    :param fips_dir:        absolute path to fips
    :param proj_dir:        absolute project path
    :param cfg_name:        the config name
    :returns:   (success, targets)
    """
    proj_name = util.get_project_name_from_dir(proj_dir)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        cfg = configs[0]
        build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
        targets_path = build_dir + '/fips_targets.yml'
        if os.path.isfile(targets_path):
            targets = []
            with open(targets_path) as f:
                targets = yaml.load(f)
            return True, targets
        else:
            return False, []
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))
Ejemplo n.º 26
0
def clean(fips_dir, proj_dir, cfg_name):
    """clean build files

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute project path
    :param cfg_name:    config name (or pattern)
    """
    proj_name = util.get_project_name_from_dir(proj_dir)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        for cfg in configs:
            log.colored(log.YELLOW, "=== clean: {}".format(cfg['name']))

            build_dir = util.get_build_dir(fips_dir, proj_name, cfg)
            if os.path.isdir(build_dir):
                shutil.rmtree(build_dir)
                log.info("  deleted '{}'".format(build_dir))

            deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg)
            if os.path.isdir(deploy_dir):
                shutil.rmtree(deploy_dir)
                log.info("  deleted '{}'".format(deploy_dir))
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))
Ejemplo n.º 27
0
def run(fips_dir, proj_dir, cfg_name, target_name, target_args, target_cwd):
    """run a build target executable

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute path of project dir
    :param cfg_name:    config name or pattern
    :param target_name: the target name
    :param target_args: command line arguments for build target
    :param target_cwd:  working directory or None
    """

    retcode = 10
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        for cfg in configs:
            log.colored(
                log.YELLOW, "=== run '{}' (config: {}, project: {}):".format(
                    target_name, cfg['name'], proj_name))

            # find deploy dir where executables live
            deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg['name'])
            if not target_cwd:
                target_cwd = deploy_dir

            if cfg['platform'] == 'emscripten':
                # special case: emscripten app
                html_name = target_name + '.html'
                if util.get_host_platform() == 'osx':
                    try:
                        subprocess.call(
                            'open http://localhost:8080/{} ; http-server -c-1 -g'
                            .format(html_name),
                            cwd=target_cwd,
                            shell=True)
                    except KeyboardInterrupt:
                        return 0
                elif util.get_host_platform() == 'win':
                    try:
                        cmd = 'cmd /c start http://localhost:8080/{} && http-server -c-1 -g'.format(
                            html_name)
                        subprocess.call(cmd, cwd=target_cwd, shell=True)
                    except KeyboardInterrupt:
                        return 0
                elif util.get_host_platform() == 'linux':
                    try:
                        subprocess.call(
                            'xdg-open http://localhost:8080/{}; http-server -c-1 -g'
                            .format(html_name),
                            cwd=target_cwd,
                            shell=True)
                    except KeyboardInterrupt:
                        return 0
                else:
                    log.error(
                        "don't know how to start HTML app on this platform")
            elif cfg['platform'] == 'android':
                try:
                    adb_path = android.get_adb_path(fips_dir)
                    pkg_name = android.target_to_package_name(target_name)
                    # Android: first re-install the apk...
                    cmd = '{} install -r {}.apk'.format(adb_path, target_name)
                    subprocess.call(cmd, shell=True, cwd=deploy_dir)
                    # ...then start the apk
                    cmd = '{} shell am start -n {}/android.app.NativeActivity'.format(
                        adb_path, pkg_name)
                    subprocess.call(cmd, shell=True)
                    # ...then run adb logcat
                    cmd = '{} logcat'.format(adb_path)
                    subprocess.call(cmd, shell=True)
                    return 0
                except KeyboardInterrupt:
                    return 0

            elif os.path.isdir('{}/{}.app'.format(deploy_dir, target_name)):
                # special case: Mac app
                cmd_line = '{}/{}.app/Contents/MacOS/{}'.format(
                    deploy_dir, target_name, target_name)
            else:
                cmd_line = '{}/{}'.format(deploy_dir, target_name)
            if cmd_line:
                if target_args:
                    cmd_line += ' ' + ' '.join(target_args)
                try:
                    retcode = subprocess.call(args=cmd_line,
                                              cwd=target_cwd,
                                              shell=True)
                except OSError as e:
                    log.error("Failed to execute '{}' with '{}'".format(
                        target_name, e.strerror))
    else:
        log.error("No valid configs found for '{}'".format(cfg_name))

    return retcode
Ejemplo n.º 28
0
def run(fips_dir, proj_dir, args):
    """run the 'physx' verb"""
    if len(args) > 0:
        noun = args[0]
        if noun == 'build':
            if sys.platform == "win32":
                # FIXME all of this only works on windows at the moment and is super hacky

                if len(args) != 2:
                    log.error("expected compiler target (win-vs15, win-vs16)")

                preset = util.fix_path(
                    os.path.dirname(os.path.abspath(__file__))
                ) + "/physx-presets/" + "fips" + args[1] + ".xml"
                if not os.path.isfile(preset):
                    log.error("Unrecognized compiler target")
                shutil.copy2(preset,
                             proj_dir + "/../physx/physx/buildtools/presets/")
                subprocess.call(proj_dir +
                                "/../physx/physx/generate_projects.bat fips" +
                                args[1])

                # figure out a version number for vswhere
                version = args[1][6:]
                version_next = str(int(version) + 1)
                version = version + ".0," + version_next + ".0"
                #use vswhere to figure out where vs is
                devenvPath = subprocess.check_output(
                    proj_dir +
                    "/../physx/externals/vswhere/vswhere -version [" +
                    version +
                    "] -property productPath").decode("utf-8").rstrip()
                devenvPath = util.fix_path(devenvPath)
                if not os.path.isfile(devenvPath):
                    #try to find msbuild
                    log.info(
                        "Could not find Visual Studio, trying to find lastest version of MSBuild..."
                        + devenvPath)
                    devenvPath = subprocess.check_output(
                        proj_dir +
                        "/../physx/externals/vswhere/vswhere -version [" +
                        version +
                        "] -products * -requires Microsoft.Component.MSBuild -property installationPath"
                    ).decode("utf-8").rstrip()
                    devenvPath = util.fix_path(
                        devenvPath + "/MSBuild/Current/Bin/MSBuild.exe")
                    if not os.path.isfile(devenvPath):
                        log.error(
                            "Could not detect Visual Studio installation.")
                    log.optional("Using MSBuild from", devenvPath)

                    log.info("Compiling PhysX, this might take a while.")
                    log.info("Building debug version...")
                    #-noConsoleLogger
                    retcode = subprocess.call(
                        devenvPath + " " + proj_dir +
                        "/../physx/physx/compiler/fips" + args[1] +
                        "/INSTALL.vcxproj /verbosity:quiet /noLogo /noConsoleLogger /property:Configuration=Debug"
                    )
                    if retcode == 0:
                        log.colored(log.GREEN, "PhysX debug build completed.")
                    else:
                        log.colored(log.RED, "PhysX debug build failed!")

                    log.info("Building release version...")
                    retcode = subprocess.call(
                        devenvPath + " " + proj_dir +
                        "/../physx/physx/compiler/fips" + args[1] +
                        "/INSTALL.vcxproj /verbosity:quiet /noLogo /noConsoleLogger /property:Configuration=Release"
                    )
                    if retcode == 0:
                        log.colored(log.GREEN,
                                    "PhysX release build completed.")
                    else:
                        log.colored(log.RED, "PhysX release build failed!")
                else:
                    log.optional("Using Visual Studio from", devenvPath)

                    log.info("Compiling PhysX, this might take a while...")
                    log.info("Building debug version...")
                    retcode = subprocess.call(
                        devenvPath + " " + proj_dir +
                        "/../physx/physx/compiler/fips" + args[1] +
                        "/PhysXSDK.sln /Build debug /Project INSTALL")
                    if retcode == 0:
                        log.colored(log.GREEN, "PhysX debug build completed.")
                    else:
                        log.colored(log.RED, "PhysX debug build failed!")

                    log.info("Building release version...")
                    retcode = subprocess.call(
                        devenvPath + " " + proj_dir +
                        "/../physx/physx/compiler/fips" + args[1] +
                        "/PhysXSDK.sln /Build release /Project INSTALL")
                    if retcode == 0:
                        log.colored(log.GREEN,
                                    "PhysX release build completed.")
                    else:
                        log.colored(log.RED, "PhysX release build failed!")
            else:
                preset = util.fix_path(
                    os.path.dirname(os.path.abspath(
                        __file__))) + "/physx-presets/fipslinux.xml"
                shutil.copy2(preset,
                             proj_dir + "/../physx/physx/buildtools/presets/")
                subprocess.run([
                    proj_dir + "/../physx/physx/generate_projects.sh",
                    "fipslinux"
                ])
                subprocess.run(["make", "-j", "10"],
                               cwd=proj_dir +
                               "/../physx/physx/compiler/fipslinux-checked")
                subprocess.run(["make", "install"],
                               cwd=proj_dir +
                               "/../physx/physx/compiler/fipslinux-checked")
        if noun == 'deploy':
            if sys.platform == "win32":
                cur_cfg = None
                if len(args) > 1:
                    cur_cfg = args[1]
                if not cur_cfg:
                    cur_cfg = settings.get(proj_dir, 'config')

                ps_deploy = util.get_workspace_dir(
                    fips_dir) + "/fips-deploy/physx/bin/"
                cfg = config.load(fips_dir, proj_dir, cur_cfg)[0]
                px_target = cfg['defines']['PX_TARGET']
                target_dir = util.get_deploy_dir(
                    fips_dir, util.get_project_name_from_dir(proj_dir),
                    cur_cfg)

                dllFiles = glob.glob(ps_deploy + px_target + "/debug/*.dll")
                log.info("Looking for PhysX dlls in '{}/'".format(ps_deploy +
                                                                  px_target))
                if not dllFiles:
                    log.error(
                        "PhysX debug dlls not found! Have you built them? (fips physx build [compiler target])"
                    )
                else:
                    for dll in dllFiles:
                        shutil.copy2(dll, target_dir)
                    log.colored(
                        log.GREEN,
                        "Deployed PhysX debug binaries to '{}'".format(
                            target_dir))

                dllFiles = glob.glob(ps_deploy + px_target + "/release/*.dll")
                if not dllFiles:
                    log.error(
                        "PhysX release dlls not found! Have you built them? (fips physx build [compiler target])"
                    )
                else:
                    for dll in dllFiles:
                        shutil.copy2(dll, target_dir)
                    log.colored(
                        log.GREEN,
                        "Deployed PhysX release binaries to '{}'".format(
                            target_dir))
    else:

        def run(fips_dir, proj_dir, args):
            log.error("Not supported")
Ejemplo n.º 29
0
def run(fips_dir, proj_dir, cfg_name, target_name, target_args, target_cwd) :
    """run a build target executable

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute path of project dir
    :param cfg_name:    config name or pattern
    :param target_name: the target name
    :param target_args: command line arguments for build target
    :param target_cwd:  working directory or None
    """

    retcode = 10
    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)
    
    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs :
        for cfg in configs :
            log.colored(log.YELLOW, "=== run '{}' (config: {}, project: {}):".format(target_name, cfg['name'], proj_name))

            # find deploy dir where executables live
            deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg)
            if not target_cwd :
                target_cwd = deploy_dir

            if cfg['platform'] in ['emscripten', 'pnacl'] : 
                # special case: emscripten app
                if cfg['platform'] == 'emscripten' :
                    html_name = target_name + '.html'
                else :
                    html_name = target_name + '_pnacl.html'
                if util.get_host_platform() == 'osx' :
                    try :
                        subprocess.call(
                            'open http://localhost:8000/{} ; python {}/mod/httpserver.py'.format(html_name, fips_dir),
                            cwd = target_cwd, shell=True)
                    except KeyboardInterrupt :
                        return 0
                elif util.get_host_platform() == 'win' :
                    try :
                        cmd = 'cmd /c start http://localhost:8000/{} && python {}/mod/httpserver.py'.format(html_name, fips_dir)
                        subprocess.call(cmd, cwd = target_cwd, shell=True)
                    except KeyboardInterrupt :
                        return 0
                elif util.get_host_platform() == 'linux' :
                    try :
                        subprocess.call(
                            'xdg-open http://localhost:8000/{}; python {}/mod/httpserver.py'.format(html_name, fips_dir),
                            cwd = target_cwd, shell=True)
                    except KeyboardInterrupt :
                        return 0
                else :
                    log.error("don't know how to start HTML app on this platform")
            elif os.path.isdir('{}/{}.app'.format(deploy_dir, target_name)) :
                # special case: Mac app
                cmd_line = '{}/{}.app/Contents/MacOS/{}'.format(deploy_dir, target_name, target_name)
            else :
                cmd_line = '{}/{}'.format(deploy_dir, target_name) 
            if cmd_line :
                if target_args :
                    cmd_line += ' ' + ' '.join(target_args)
                try:
                    retcode = subprocess.call(args=cmd_line, cwd=target_cwd, shell=True)
                except OSError, e:
                    log.error("Failed to execute '{}' with '{}'".format(target_name, e.strerror))
Ejemplo n.º 30
0
def run(fips_dir, proj_dir, cfg_name, target_name, target_args):
    """run a build target executable

    :param fips_dir:    absolute path of fips
    :param proj_dir:    absolute path of project dir
    :param cfg_name:    config name or pattern
    :param target_name: the target name
    :param target_args: command line arguments for build target
    """

    proj_name = util.get_project_name_from_dir(proj_dir)
    util.ensure_valid_project_dir(proj_dir)

    # load the config(s)
    configs = config.load(fips_dir, proj_dir, cfg_name)
    if configs:
        for cfg in configs:
            log.colored(
                log.YELLOW, "=== run '{}' (config: {}, project: {}):".format(
                    target_name, cfg['name'], proj_name))

            # find deploy dir where executables live
            deploy_dir = util.get_deploy_dir(fips_dir, proj_name, cfg)

            cmd_line = []
            if cfg['platform'] in ['emscripten', 'pnacl']:
                # special case: emscripten app
                if cfg['platform'] == 'emscripten':
                    html_name = target_name + '.html'
                else:
                    html_name = target_name + '_pnacl.html'
                if util.get_host_platform() == 'osx':
                    try:
                        subprocess.call([
                            'open http://localhost:8000/{} ; python {}/mod/httpserver.py'
                            .format(html_name, fips_dir)
                        ],
                                        cwd=deploy_dir,
                                        shell=True)
                    except KeyboardInterrupt:
                        pass
                elif util.get_host_platform() == 'win':
                    try:
                        cmd = [
                            'cmd /c start http://localhost:8000/{} && python {}/mod/httpserver.py'
                            .format(html_name, fips_dir)
                        ]
                        subprocess.call(cmd, cwd=deploy_dir, shell=True)
                    except KeyboardInterrupt:
                        pass
                elif util.get_host_platform() == 'linux':
                    try:
                        subprocess.call([
                            'xdg-open http://localhost:8000/{}; python {}/mod/httpserver.py'
                            .format(html_name, fips_dir)
                        ],
                                        cwd=deploy_dir,
                                        shell=True)
                    except KeyboardInterrupt:
                        pass
                else:
                    log.error(
                        "don't know how to start HTML app on this platform")
            elif os.path.isdir('{}/{}.app'.format(deploy_dir, target_name)):
                # special case: Mac app
                cmd_line = [
                    'open', '{}/{}.app'.format(deploy_dir, target_name)
                ]
                if target_args:
                    cmd_line.append('--args')
            else:
                cmd_line = ['{}/{}'.format(deploy_dir, target_name)]
            if cmd_line:
                if target_args:
                    cmd_line.extend(target_args)
                try:
                    subprocess.call(args=cmd_line, cwd=deploy_dir)
                except OSError, e:
                    log.error("Failed to execute '{}' with '{}'".format(
                        target_name, e.strerror))