Example #1
0
def package(args, config, basepath, workspace):
    """Entry point for the devtool 'package' subcommand"""
    check_workspace_recipe(workspace, args.recipename)

    tinfoil = setup_tinfoil(basepath=basepath)
    try:
        tinfoil.prepare(config_only=True)

        image_pkgtype = config.get('Package', 'image_pkgtype', '')
        if not image_pkgtype:
            image_pkgtype = tinfoil.config_data.getVar('IMAGE_PKGTYPE', True)

        deploy_dir_pkg = tinfoil.config_data.getVar('DEPLOY_DIR_%s' % image_pkgtype.upper(), True)
    finally:
        tinfoil.shutdown()

    package_task = config.get('Package', 'package_task', 'package_write_%s' % image_pkgtype)
    try:
        exec_build_env_command(config.init_path, basepath, 'bitbake -c %s %s' % (package_task, args.recipename), watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode

    logger.info('Your packages are in %s' % deploy_dir_pkg)

    return 0
Example #2
0
def package(args, config, basepath, workspace):
    """Entry point for the devtool 'package' subcommand"""
    check_workspace_recipe(workspace, args.recipename)

    tinfoil = setup_tinfoil(basepath=basepath)
    try:
        tinfoil.prepare(config_only=True)

        image_pkgtype = config.get('Package', 'image_pkgtype', '')
        if not image_pkgtype:
            image_pkgtype = tinfoil.config_data.getVar('IMAGE_PKGTYPE', True)

        deploy_dir_pkg = tinfoil.config_data.getVar('DEPLOY_DIR_%s' % image_pkgtype.upper(), True)
    finally:
        tinfoil.shutdown()

    package_task = config.get('Package', 'package_task', 'package_write_%s' % image_pkgtype)
    try:
        exec_build_env_command(config.init_path, basepath, 'bitbake -c %s %s' % (package_task, args.recipename), watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode

    logger.info('Your packages are in %s' % deploy_dir_pkg)

    return 0
Example #3
0
def edit_recipe(args, config, basepath, workspace):
    """Entry point for the devtool 'edit-recipe' subcommand"""
    if args.any_recipe:
        tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
        try:
            rd = parse_recipe(config, tinfoil, args.recipename, True)
            if not rd:
                return 1
            recipefile = rd.getVar('FILE', True)
        finally:
            tinfoil.shutdown()
    else:
        check_workspace_recipe(workspace, args.recipename)
        recipefile = workspace[args.recipename]['recipefile']
        if not recipefile:
            raise DevtoolError(
                "Recipe file for %s is not under the workspace" %
                args.recipename)

    editor = os.environ.get('EDITOR', None)
    if not editor:
        raise DevtoolError("EDITOR environment variable not set")

    import subprocess
    try:
        subprocess.check_call('%s "%s"' % (editor, recipefile), shell=True)
    except subprocess.CalledProcessError as e:
        return e.returncode

    return 0
Example #4
0
def edit_recipe(args, config, basepath, workspace):
    """Entry point for the devtool 'edit-recipe' subcommand"""
    if args.any_recipe:
        tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
        try:
            rd = parse_recipe(config, tinfoil, args.recipename, True)
            if not rd:
                return 1
            recipefile = rd.getVar('FILE', True)
        finally:
            tinfoil.shutdown()
    else:
        check_workspace_recipe(workspace, args.recipename)
        recipefile = workspace[args.recipename]['recipefile']
        if not recipefile:
            raise DevtoolError("Recipe file for %s is not under the workspace" %
                               args.recipename)

    editor = os.environ.get('EDITOR', None)
    if not editor:
        raise DevtoolError("EDITOR environment variable not set")

    import subprocess
    try:
        subprocess.check_call('%s "%s"' % (editor, recipefile), shell=True)
    except subprocess.CalledProcessError as e:
        return e.returncode

    return 0
Example #5
0
def build(args, config, basepath, workspace):
    """Entry point for the devtool 'build' subcommand"""
    check_workspace_recipe(workspace, args.recipename)

    build_task = config.get('Build', 'build_task', 'populate_sysroot')

    postfile_param = ""
    postfile = ""
    if args.disable_parallel_make:
        logger.info("Disabling 'make' parallelism")
        postfile = os.path.join(basepath, 'conf', 'disable_parallelism.conf')
        _create_conf_file({'PARALLEL_MAKE': ''}, postfile)
        postfile_param = "-R %s" % postfile
    try:
        exec_build_env_command(config.init_path,
                               basepath,
                               'bitbake -c %s %s %s' %
                               (build_task, postfile_param, args.recipename),
                               watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode
    finally:
        if postfile:
            logger.debug('Removing postfile')
            os.remove(postfile)

    return 0
Example #6
0
def menuconfig(args, config, basepath, workspace):
    """Entry point for the devtool 'menuconfig' subcommand"""

    rd = ""
    kconfigpath = ""
    pn_src = ""
    localfilesdir = ""
    workspace_dir = ""
    tinfoil = setup_tinfoil(basepath=basepath)
    try:
        rd = parse_recipe(config,
                          tinfoil,
                          args.component,
                          appends=True,
                          filter_workspace=False)
        if not rd:
            return 1

        check_workspace_recipe(workspace, args.component)
        pn = rd.getVar('PN', True)

        if not rd.getVarFlag('do_menuconfig', 'task'):
            raise DevtoolError(
                "This recipe does not support menuconfig option")

        workspace_dir = os.path.join(config.workspace_path, 'sources')
        kconfigpath = rd.getVar('B')
        pn_src = os.path.join(workspace_dir, pn)

        # add check to see if oe_local_files exists or not
        localfilesdir = os.path.join(pn_src, 'oe-local-files')
        if not os.path.exists(localfilesdir):
            bb.utils.mkdirhier(localfilesdir)
            # Add gitignore to ensure source tree is clean
            gitignorefile = os.path.join(localfilesdir, '.gitignore')
            with open(gitignorefile, 'w') as f:
                f.write(
                    '# Ignore local files, by default. Remove this file if you want to commit the directory to Git\n'
                )
                f.write('*\n')

    finally:
        tinfoil.shutdown()

    logger.info('Launching menuconfig')
    exec_build_env_command(config.init_path,
                           basepath,
                           'bitbake -c menuconfig %s' % pn,
                           watch=True)
    fragment = os.path.join(localfilesdir, 'devtool-fragment.cfg')
    res = standard._create_kconfig_diff(pn_src, rd, fragment)

    return 0
Example #7
0
def reset(args, config, basepath, workspace):
    """Entry point for the devtool 'reset' subcommand"""
    import bb
    if args.recipename:
        if args.all:
            raise DevtoolError("Recipe cannot be specified if -a/--all is used")
        else:
            check_workspace_recipe(workspace, args.recipename, checksrc=False)
    elif not args.all:
        raise DevtoolError("Recipe must be specified, or specify -a/--all to "
                           "reset all recipes")
    if args.all:
        recipes = workspace.keys()
    else:
        recipes = [args.recipename]

    if recipes and not args.no_clean:
        if len(recipes) == 1:
            logger.info('Cleaning sysroot for recipe %s...' % recipes[0])
        else:
            logger.info('Cleaning sysroot for recipes %s...' % ', '.join(recipes))
        try:
            exec_build_env_command(config.init_path, basepath, 'bitbake -c clean %s' % ' '.join(recipes))
        except bb.process.ExecutionError as e:
            raise DevtoolError('Command \'%s\' failed, output:\n%s\nIf you '
                                'wish, you may specify -n/--no-clean to '
                                'skip running this command when resetting' %
                                (e.command, e.stdout))

    for pn in recipes:
        _check_preserve(config, pn)

        preservepath = os.path.join(config.workspace_path, 'attic', pn)
        def preservedir(origdir):
            if os.path.exists(origdir):
                for root, dirs, files in os.walk(origdir):
                    for fn in files:
                        logger.warn('Preserving %s in %s' % (fn, preservepath))
                        _move_file(os.path.join(origdir, fn),
                                   os.path.join(preservepath, fn))
                    for dn in dirs:
                        os.rmdir(os.path.join(root, dn))
                os.rmdir(origdir)

        preservedir(os.path.join(config.workspace_path, 'recipes', pn))
        # We don't automatically create this dir next to appends, but the user can
        preservedir(os.path.join(config.workspace_path, 'appends', pn))

    return 0
Example #8
0
def build(args, config, basepath, workspace):
    """Entry point for the devtool 'build' subcommand"""
    workspacepn = check_workspace_recipe(workspace, args.recipename, bbclassextend=True)

    build_tasks = _get_build_tasks(config)

    bbappend = workspace[workspacepn]['bbappend']
    if args.disable_parallel_make:
        logger.info("Disabling 'make' parallelism")
        _set_file_values(bbappend, {'PARALLEL_MAKE': ''})
    try:
        bbargs = []
        for task in build_tasks:
            if args.recipename.endswith('-native') and 'package' in task:
                continue
            bbargs.append('%s:%s' % (args.recipename, task))
        exec_build_env_command(config.init_path, basepath, 'bitbake %s' % ' '.join(bbargs), watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode
    finally:
        if args.disable_parallel_make:
            _set_file_values(bbappend, {'PARALLEL_MAKE': None})

    return 0
Example #9
0
def build(args, config, basepath, workspace):
    """Entry point for the devtool 'build' subcommand"""
    workspacepn = check_workspace_recipe(workspace,
                                         args.recipename,
                                         bbclassextend=True)

    build_tasks = _get_build_tasks(config)

    bbappend = workspace[workspacepn]['bbappend']
    if args.disable_parallel_make:
        logger.info("Disabling 'make' parallelism")
        _set_file_values(bbappend, {'PARALLEL_MAKE': ''})
    try:
        bbargs = []
        for task in build_tasks:
            if args.recipename.endswith('-native') and 'package' in task:
                continue
            bbargs.append('%s:%s' % (args.recipename, task))
        exec_build_env_command(config.init_path,
                               basepath,
                               'bitbake %s' % ' '.join(bbargs),
                               watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode
    finally:
        if args.disable_parallel_make:
            _set_file_values(bbappend, {'PARALLEL_MAKE': None})

    return 0
Example #10
0
def find_recipe(args, config, basepath, workspace):
    """Entry point for the devtool 'find-recipe' subcommand"""
    if args.any_recipe:
        tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
        try:
            rd = parse_recipe(config, tinfoil, args.recipename, True)
            if not rd:
                return 1
            recipefile = rd.getVar('FILE')
        finally:
            tinfoil.shutdown()
    else:
        check_workspace_recipe(workspace, args.recipename)
        recipefile = workspace[args.recipename]['recipefile']
        if not recipefile:
            raise DevtoolError("Recipe file for %s is not under the workspace" %
                               args.recipename)
Example #11
0
def _find_recipe_path(args, config, basepath, workspace):
    if args.any_recipe:
        tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
        try:
            rd = parse_recipe(config, tinfoil, args.recipename, True)
            if not rd:
                raise DevtoolError("Failed to find specified recipe")
            recipefile = rd.getVar('FILE')
        finally:
            tinfoil.shutdown()
    else:
        check_workspace_recipe(workspace, args.recipename)
        recipefile = workspace[args.recipename]['recipefile']
        if not recipefile:
            raise DevtoolError("Recipe file for %s is not under the workspace" %
                               args.recipename)
    return recipefile
Example #12
0
def _find_recipe_path(args, config, basepath, workspace):
    if args.any_recipe:
        tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
        try:
            rd = parse_recipe(config, tinfoil, args.recipename, True)
            if not rd:
                raise DevtoolError("Failed to find specified recipe")
            recipefile = rd.getVar('FILE')
        finally:
            tinfoil.shutdown()
    else:
        check_workspace_recipe(workspace, args.recipename)
        recipefile = workspace[args.recipename]['recipefile']
        if not recipefile:
            raise DevtoolError(
                "Recipe file for %s is not under the workspace" %
                args.recipename)
    return recipefile
Example #13
0
def edit_recipe(args, config, basepath, workspace):
    """Entry point for the devtool 'edit-recipe' subcommand"""
    if args.any_recipe:
        tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
        try:
            rd = parse_recipe(config, tinfoil, args.recipename, True)
            if not rd:
                return 1
            recipefile = rd.getVar('FILE')
        finally:
            tinfoil.shutdown()
    else:
        check_workspace_recipe(workspace, args.recipename)
        recipefile = workspace[args.recipename]['recipefile']
        if not recipefile:
            raise DevtoolError("Recipe file for %s is not under the workspace" %
                               args.recipename)

    return scriptutils.run_editor(recipefile)
Example #14
0
File: build.py Project: shenki/poky
def build(args, config, basepath, workspace):
    """Entry point for the devtool 'build' subcommand"""
    check_workspace_recipe(workspace, args.recipename)

    build_task = _get_build_task(config)

    bbappend = workspace[args.recipename]["bbappend"]
    if args.disable_parallel_make:
        logger.info("Disabling 'make' parallelism")
        _set_file_values(bbappend, {"PARALLEL_MAKE": ""})
    try:
        exec_build_env_command(
            config.init_path, basepath, "bitbake -c %s %s" % (build_task, args.recipename), watch=True
        )
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode
    finally:
        if args.disable_parallel_make:
            _set_file_values(bbappend, {"PARALLEL_MAKE": None})

    return 0
Example #15
0
def build(args, config, basepath, workspace):
    """Entry point for the devtool 'build' subcommand"""
    check_workspace_recipe(workspace, args.recipename)

    build_task = config.get('Build', 'build_task', 'populate_sysroot')

    postfile_param = ""
    postfile = ""
    if args.disable_parallel_make:
        logger.info("Disabling 'make' parallelism")
        postfile = os.path.join(basepath, 'conf', 'disable_parallelism.conf')
        _create_conf_file({'PARALLEL_MAKE':''}, postfile)
        postfile_param = "-R %s" % postfile
    try:
        exec_build_env_command(config.init_path, basepath, 'bitbake -c %s %s %s' % (build_task, postfile_param, args.recipename), watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode
    finally:
        if postfile:
            logger.debug('Removing postfile')
            os.remove(postfile)

    return 0
Example #16
0
def update_recipe(args, config, basepath, workspace):
    """Entry point for the devtool 'update-recipe' subcommand"""
    check_workspace_recipe(workspace, args.recipename)

    if args.append:
        if not os.path.exists(args.append):
            raise DevtoolError('bbappend destination layer directory "%s" '
                               'does not exist' % args.append)
        if not os.path.exists(os.path.join(args.append, 'conf', 'layer.conf')):
            raise DevtoolError('conf/layer.conf not found in bbappend '
                               'destination layer "%s"' % args.append)

    tinfoil = setup_tinfoil(basepath=basepath, tracking=True)

    rd = parse_recipe(config, tinfoil, args.recipename, True)
    if not rd:
        return 1

    srctree = workspace[args.recipename]['srctree']
    if args.mode == 'auto':
        mode = _guess_recipe_update_mode(srctree, rd)
    else:
        mode = args.mode

    if mode == 'srcrev':
        _update_recipe_srcrev(args, srctree, rd, tinfoil.config_data)
    elif mode == 'patch':
        _update_recipe_patch(args, config, srctree, rd, tinfoil.config_data)
    else:
        raise DevtoolError('update_recipe: invalid mode %s' % mode)

    rf = rd.getVar('FILE', True)
    if rf.startswith(config.workspace_path):
        logger.warn('Recipe file %s has been updated but is inside the workspace - you will need to move it (and any associated files next to it) out to the desired layer before using "devtool reset" in order to keep any changes' % rf)

    return 0
Example #17
0
def build(args, config, basepath, workspace):
    """Entry point for the devtool 'build' subcommand"""
    check_workspace_recipe(workspace, args.recipename)

    build_task = _get_build_task(config)

    bbappend = workspace[args.recipename]['bbappend']
    if args.disable_parallel_make:
        logger.info("Disabling 'make' parallelism")
        _set_file_values(bbappend, {'PARALLEL_MAKE': ''})
    try:
        exec_build_env_command(config.init_path,
                               basepath,
                               'bitbake -c %s %s' %
                               (build_task, args.recipename),
                               watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode
    finally:
        if args.disable_parallel_make:
            _set_file_values(bbappend, {'PARALLEL_MAKE': None})

    return 0
Example #18
0
def build(args, config, basepath, workspace):
    """Entry point for the devtool 'build' subcommand"""
    workspacepn = check_workspace_recipe(workspace,
                                         args.recipename,
                                         bbclassextend=True)
    tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
    try:
        rd = parse_recipe(config,
                          tinfoil,
                          args.recipename,
                          appends=True,
                          filter_workspace=False)
        if not rd:
            return 1
        deploytask = 'do_deploy' in rd.getVar('__BBTASKS')
    finally:
        tinfoil.shutdown()

    if args.clean:
        # use clean instead of cleansstate to avoid messing things up in eSDK
        build_tasks = ['do_clean']
    else:
        build_tasks = _get_build_tasks(config)
        if deploytask:
            build_tasks.append('do_deploy')

    bbappend = workspace[workspacepn]['bbappend']
    if args.disable_parallel_make:
        logger.info("Disabling 'make' parallelism")
        _set_file_values(bbappend, {'PARALLEL_MAKE': ''})
    try:
        bbargs = []
        for task in build_tasks:
            if args.recipename.endswith('-native') and 'package' in task:
                continue
            bbargs.append('%s:%s' % (args.recipename, task))
        exec_build_env_command(config.init_path,
                               basepath,
                               'bitbake %s' % ' '.join(bbargs),
                               watch=True)
    except bb.process.ExecutionError as e:
        # We've already seen the output since watch=True, so just ensure we return something to the user
        return e.exitcode
    finally:
        if args.disable_parallel_make:
            _set_file_values(bbappend, {'PARALLEL_MAKE': None})

    return 0
Example #19
0
def deploy(args, config, basepath, workspace):
    """Entry point for the devtool 'deploy' subcommand"""
    import math
    import oe.recipeutils
    import oe.package

    check_workspace_recipe(workspace, args.recipename, checksrc=False)

    try:
        host, destdir = args.target.split(':')
    except ValueError:
        destdir = '/'
    else:
        args.target = host
    if not destdir.endswith('/'):
        destdir += '/'

    tinfoil = setup_tinfoil(basepath=basepath)
    try:
        try:
            rd = tinfoil.parse_recipe(args.recipename)
        except Exception as e:
            raise DevtoolError('Exception parsing recipe %s: %s' %
                               (args.recipename, e))
        recipe_outdir = rd.getVar('D')
        if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir):
            raise DevtoolError(
                'No files to deploy - have you built the %s '
                'recipe? If so, the install step has not installed '
                'any files.' % args.recipename)

        if args.strip and not args.dry_run:
            # Fakeroot copy to new destination
            srcdir = recipe_outdir
            recipe_outdir = os.path.join(rd.getVar('WORKDIR'),
                                         'devtool-deploy-target-stripped')
            if os.path.isdir(recipe_outdir):
                bb.utils.remove(recipe_outdir, True)
            exec_fakeroot(rd,
                          "cp -af %s %s" %
                          (os.path.join(srcdir, '.'), recipe_outdir),
                          shell=True)
            os.environ['PATH'] = ':'.join(
                [os.environ['PATH'],
                 rd.getVar('PATH') or ''])
            oe.package.strip_execs(args.recipename, recipe_outdir,
                                   rd.getVar('STRIP'), rd.getVar('libdir'),
                                   rd.getVar('base_libdir'), rd)

        filelist = []
        inodes = set({})
        ftotalsize = 0
        for root, _, files in os.walk(recipe_outdir):
            for fn in files:
                fstat = os.lstat(os.path.join(root, fn))
                # Get the size in kiB (since we'll be comparing it to the output of du -k)
                # MUST use lstat() here not stat() or getfilesize() since we don't want to
                # dereference symlinks
                if fstat.st_ino in inodes:
                    fsize = 0
                else:
                    fsize = int(math.ceil(float(fstat.st_size) / 1024))
                inodes.add(fstat.st_ino)
                ftotalsize += fsize
                # The path as it would appear on the target
                fpath = os.path.join(destdir,
                                     os.path.relpath(root, recipe_outdir), fn)
                filelist.append((fpath, fsize))

        if args.dry_run:
            print('Files to be deployed for %s on target %s:' %
                  (args.recipename, args.target))
            for item, _ in filelist:
                print('  %s' % item)
            return 0

        extraoptions = ''
        if args.no_host_check:
            extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
        if not args.show_status:
            extraoptions += ' -q'

        scp_sshexec = ''
        ssh_sshexec = 'ssh'
        if args.ssh_exec:
            scp_sshexec = "-S %s" % args.ssh_exec
            ssh_sshexec = args.ssh_exec
        scp_port = ''
        ssh_port = ''
        if args.port:
            scp_port = "-P %s" % args.port
            ssh_port = "-p %s" % args.port

        if args.key:
            extraoptions += ' -i %s' % args.key

        # In order to delete previously deployed files and have the manifest file on
        # the target, we write out a shell script and then copy it to the target
        # so we can then run it (piping tar output to it).
        # (We cannot use scp here, because it doesn't preserve symlinks.)
        tmpdir = tempfile.mkdtemp(prefix='devtool')
        try:
            tmpscript = '/tmp/devtool_deploy.sh'
            tmpfilelist = os.path.join(os.path.dirname(tmpscript),
                                       'devtool_deploy.list')
            shellscript = _prepare_remote_script(
                deploy=True,
                verbose=args.show_status,
                nopreserve=args.no_preserve,
                nocheckspace=args.no_check_space)
            # Write out the script to a file
            with open(os.path.join(tmpdir, os.path.basename(tmpscript)),
                      'w') as f:
                f.write(shellscript)
            # Write out the file list
            with open(os.path.join(tmpdir, os.path.basename(tmpfilelist)),
                      'w') as f:
                f.write('%d\n' % ftotalsize)
                for fpath, fsize in filelist:
                    f.write('%s %d\n' % (fpath, fsize))
            # Copy them to the target
            ret = subprocess.call("scp %s %s %s %s/* %s:%s" %
                                  (scp_sshexec, scp_port, extraoptions, tmpdir,
                                   args.target, os.path.dirname(tmpscript)),
                                  shell=True)
            if ret != 0:
                raise DevtoolError(
                    'Failed to copy script to %s - rerun with -s to '
                    'get a complete error message' % args.target)
        finally:
            shutil.rmtree(tmpdir)

        # Now run the script
        ret = exec_fakeroot(rd,
                            'tar cf - . | %s  %s %s %s \'sh %s %s %s %s\'' %
                            (ssh_sshexec, ssh_port, extraoptions, args.target,
                             tmpscript, args.recipename, destdir, tmpfilelist),
                            cwd=recipe_outdir,
                            shell=True)
        if ret != 0:
            raise DevtoolError(
                'Deploy failed - rerun with -s to get a complete '
                'error message')

        logger.info('Successfully deployed %s' % recipe_outdir)

        files_list = []
        for root, _, files in os.walk(recipe_outdir):
            for filename in files:
                filename = os.path.relpath(os.path.join(root, filename),
                                           recipe_outdir)
                files_list.append(os.path.join(destdir, filename))
    finally:
        tinfoil.shutdown()

    return 0
Example #20
0
def configure_help(args, config, basepath, workspace):
    """Entry point for the devtool 'configure-help' subcommand"""
    import oe.utils

    check_workspace_recipe(workspace, args.recipename)
    tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
    try:
        rd = parse_recipe(config,
                          tinfoil,
                          args.recipename,
                          appends=True,
                          filter_workspace=False)
        if not rd:
            return 1
        b = rd.getVar('B', True)
        s = rd.getVar('S', True)
        configurescript = os.path.join(s, 'configure')
        confdisabled = 'noexec' in rd.getVarFlags(
            'do_configure') or 'do_configure' not in (rd.getVar(
                '__BBTASKS', False) or [])
        configureopts = oe.utils.squashspaces(
            rd.getVar('CONFIGUREOPTS', True) or '')
        extra_oeconf = oe.utils.squashspaces(
            rd.getVar('EXTRA_OECONF', True) or '')
        extra_oecmake = oe.utils.squashspaces(
            rd.getVar('EXTRA_OECMAKE', True) or '')
        do_configure = rd.getVar('do_configure', True) or ''
        do_configure_noexpand = rd.getVar('do_configure', False) or ''
        packageconfig = rd.getVarFlags('PACKAGECONFIG') or []
        autotools = bb.data.inherits_class(
            'autotools', rd) and ('oe_runconf' in do_configure
                                  or 'autotools_do_configure' in do_configure)
        cmake = bb.data.inherits_class('cmake', rd) and ('cmake_do_configure'
                                                         in do_configure)
        cmake_do_configure = rd.getVar('cmake_do_configure', True)
        pn = rd.getVar('PN', True)
    finally:
        tinfoil.shutdown()

    if 'doc' in packageconfig:
        del packageconfig['doc']

    if autotools and not os.path.exists(configurescript):
        logger.info('Running do_configure to generate configure script')
        try:
            stdout, _ = exec_build_env_command(config.init_path,
                                               basepath,
                                               'bitbake -c configure %s' % msg,
                                               args.recipename,
                                               stderr=subprocess.STDOUT)
        except bb.process.ExecutionError:
            pass

    if confdisabled or do_configure.strip() in ('', ':'):
        raise DevtoolError(
            "do_configure task has been disabled for this recipe")
    elif args.no_pager and not os.path.exists(configurescript):
        raise DevtoolError(
            "No configure script found and no other information to display")
    else:
        configopttext = ''
        if autotools and configureopts:
            configopttext = '''
Arguments currently passed to the configure script:

%s

Some of those are fixed.''' % (configureopts + ' ' + extra_oeconf)
            if extra_oeconf:
                configopttext += ''' The ones that are specified through EXTRA_OECONF (which you can change or add to easily):

%s''' % extra_oeconf

        elif cmake:
            in_cmake = False
            cmake_cmd = ''
            for line in cmake_do_configure.splitlines():
                if in_cmake:
                    cmake_cmd = cmake_cmd + ' ' + line.strip().rstrip('\\')
                    if not line.endswith('\\'):
                        break
                if line.lstrip().startswith('cmake '):
                    cmake_cmd = line.strip().rstrip('\\')
                    if line.endswith('\\'):
                        in_cmake = True
                    else:
                        break
            if cmake_cmd:
                configopttext = '''
The current cmake command line:

%s

Arguments specified through EXTRA_OECMAKE (which you can change or add to easily)

%s''' % (oe.utils.squashspaces(cmake_cmd), extra_oecmake)
            else:
                configopttext = '''
The current implementation of cmake_do_configure:

cmake_do_configure() {
%s
}

Arguments specified through EXTRA_OECMAKE (which you can change or add to easily)

%s''' % (cmake_do_configure.rstrip(), extra_oecmake)

        elif do_configure:
            configopttext = '''
The current implementation of do_configure:

do_configure() {
%s
}''' % do_configure.rstrip()
            if '${EXTRA_OECONF}' in do_configure_noexpand:
                configopttext += '''

Arguments specified through EXTRA_OECONF (which you can change or add to easily):

%s''' % extra_oeconf

        if packageconfig:
            configopttext += '''

Some of these options may be controlled through PACKAGECONFIG; for more details please see the recipe.'''

        if args.arg:
            helpargs = ' '.join(args.arg)
        elif cmake:
            helpargs = '-LH'
        else:
            helpargs = '--help'

        msg = '''configure information for %s
------------------------------------------
%s''' % (pn, configopttext)

        if cmake:
            msg += '''

The cmake %s output for %s follows. After "-- Cache values" you should see a list of variables you can add to EXTRA_OECMAKE (prefixed with -D and suffixed with = followed by the desired value, without any spaces).
------------------------------------------''' % (helpargs, pn)
        elif os.path.exists(configurescript):
            msg += '''

The ./configure %s output for %s follows.
------------------------------------------''' % (helpargs, pn)

        olddir = os.getcwd()
        tmppath = tempfile.mkdtemp()
        with tempfile.NamedTemporaryFile('w', delete=False) as tf:
            if not args.no_header:
                tf.write(msg + '\n')
            tf.close()
            try:
                try:
                    cmd = 'cat %s' % tf.name
                    if cmake:
                        cmd += '; cmake %s %s 2>&1' % (helpargs, s)
                        os.chdir(b)
                    elif os.path.exists(configurescript):
                        cmd += '; %s %s' % (configurescript, helpargs)
                    if sys.stdout.isatty() and not args.no_pager:
                        pager = os.environ.get('PAGER', 'less')
                        cmd = '(%s) | %s' % (cmd, pager)
                    subprocess.check_call(cmd, shell=True)
                except subprocess.CalledProcessError as e:
                    return e.returncode
            finally:
                os.chdir(olddir)
                shutil.rmtree(tmppath)
                os.remove(tf.name)
Example #21
0
def deploy(args, config, basepath, workspace):
    """Entry point for the devtool 'deploy' subcommand"""
    import re
    import math
    import oe.recipeutils

    check_workspace_recipe(workspace, args.recipename, checksrc=False)

    try:
        host, destdir = args.target.split(':')
    except ValueError:
        destdir = '/'
    else:
        args.target = host
    if not destdir.endswith('/'):
        destdir += '/'

    tinfoil = setup_tinfoil(basepath=basepath)
    try:
        try:
            rd = tinfoil.parse_recipe(args.recipename)
        except Exception as e:
            raise DevtoolError('Exception parsing recipe %s: %s' %
                            (args.recipename, e))
        recipe_outdir = rd.getVar('D')
        if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir):
            raise DevtoolError('No files to deploy - have you built the %s '
                            'recipe? If so, the install step has not installed '
                            'any files.' % args.recipename)

        filelist = []
        ftotalsize = 0
        for root, _, files in os.walk(recipe_outdir):
            for fn in files:
                # Get the size in kiB (since we'll be comparing it to the output of du -k)
                # MUST use lstat() here not stat() or getfilesize() since we don't want to
                # dereference symlinks
                fsize = int(math.ceil(float(os.lstat(os.path.join(root, fn)).st_size)/1024))
                ftotalsize += fsize
                # The path as it would appear on the target
                fpath = os.path.join(destdir, os.path.relpath(root, recipe_outdir), fn)
                filelist.append((fpath, fsize))

        if args.dry_run:
            print('Files to be deployed for %s on target %s:' % (args.recipename, args.target))
            for item, _ in filelist:
                print('  %s' % item)
            return 0


        extraoptions = ''
        if args.no_host_check:
            extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
        if not args.show_status:
            extraoptions += ' -q'

        scp_port = ''
        ssh_port = ''
        if not args.port:
            raise DevtoolError("If you specify -P/--port then you must provide the port to be used to connect to the target")
        else:
            scp_port = "-P %s" % args.port
            ssh_port = "-p %s" % args.port

        # In order to delete previously deployed files and have the manifest file on
        # the target, we write out a shell script and then copy it to the target
        # so we can then run it (piping tar output to it).
        # (We cannot use scp here, because it doesn't preserve symlinks.)
        tmpdir = tempfile.mkdtemp(prefix='devtool')
        try:
            tmpscript = '/tmp/devtool_deploy.sh'
            tmpfilelist = os.path.join(os.path.dirname(tmpscript), 'devtool_deploy.list')
            shellscript = _prepare_remote_script(deploy=True,
                                                verbose=args.show_status,
                                                nopreserve=args.no_preserve,
                                                nocheckspace=args.no_check_space)
            # Write out the script to a file
            with open(os.path.join(tmpdir, os.path.basename(tmpscript)), 'w') as f:
                f.write(shellscript)
            # Write out the file list
            with open(os.path.join(tmpdir, os.path.basename(tmpfilelist)), 'w') as f:
                f.write('%d\n' % ftotalsize)
                for fpath, fsize in filelist:
                    f.write('%s %d\n' % (fpath, fsize))
            # Copy them to the target
            ret = subprocess.call("scp %s %s %s/* %s:%s" % (scp_port, extraoptions, tmpdir, args.target, os.path.dirname(tmpscript)), shell=True)
            if ret != 0:
                raise DevtoolError('Failed to copy script to %s - rerun with -s to '
                                'get a complete error message' % args.target)
        finally:
            shutil.rmtree(tmpdir)

        # Now run the script
        ret = exec_fakeroot(rd, 'tar cf - . | ssh  %s %s %s \'sh %s %s %s %s\'' % (ssh_port, extraoptions, args.target, tmpscript, args.recipename, destdir, tmpfilelist), cwd=recipe_outdir, shell=True)
        if ret != 0:
            raise DevtoolError('Deploy failed - rerun with -s to get a complete '
                            'error message')

        logger.info('Successfully deployed %s' % recipe_outdir)

        files_list = []
        for root, _, files in os.walk(recipe_outdir):
            for filename in files:
                filename = os.path.relpath(os.path.join(root, filename), recipe_outdir)
                files_list.append(os.path.join(destdir, filename))
    finally:
        tinfoil.shutdown()

    return 0
Example #22
0
def deploy(args, config, basepath, workspace):
    """Entry point for the devtool 'deploy' subcommand"""
    import re
    import oe.recipeutils

    check_workspace_recipe(workspace, args.recipename, checksrc=False)

    try:
        host, destdir = args.target.split(':')
    except ValueError:
        destdir = '/'
    else:
        args.target = host

    deploy_dir = os.path.join(basepath, 'target_deploy', args.target)
    deploy_file = os.path.join(deploy_dir, args.recipename + '.list')

    tinfoil = setup_tinfoil(basepath=basepath)
    try:
        rd = oe.recipeutils.parse_recipe_simple(tinfoil.cooker, args.recipename, tinfoil.config_data)
    except Exception as e:
        raise DevtoolError('Exception parsing recipe %s: %s' %
                           (args.recipename, e))
    recipe_outdir = rd.getVar('D', True)
    if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir):
        raise DevtoolError('No files to deploy - have you built the %s '
                           'recipe? If so, the install step has not installed '
                           'any files.' % args.recipename)

    if args.dry_run:
        print('Files to be deployed for %s on target %s:' % (args.recipename, args.target))
        for root, _, files in os.walk(recipe_outdir):
            for fn in files:
                print('  %s' % os.path.join(destdir, os.path.relpath(root, recipe_outdir), fn))
        return 0

    if os.path.exists(deploy_file):
        if undeploy(args, config, basepath, workspace):
            # Error already shown
            return 1

    extraoptions = ''
    if args.no_host_check:
        extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
    if args.show_status:
        tarextractopts = 'xv'
    else:
        tarextractopts = 'x'
        extraoptions += ' -q'
    # We cannot use scp here, because it doesn't preserve symlinks
    ret = exec_fakeroot(rd, 'tar cf - . | ssh %s %s \'tar %s -C %s -f -\'' % (extraoptions, args.target, tarextractopts, destdir), cwd=recipe_outdir, shell=True)
    if ret != 0:
        raise DevtoolError('Deploy failed - rerun with -s to get a complete '
                           'error message')

    logger.info('Successfully deployed %s' % recipe_outdir)

    if not os.path.exists(deploy_dir):
        os.makedirs(deploy_dir)

    files_list = []
    for root, _, files in os.walk(recipe_outdir):
        for filename in files:
            filename = os.path.relpath(os.path.join(root, filename), recipe_outdir)
            files_list.append(os.path.join(destdir, filename))

    with open(deploy_file, 'w') as fobj:
        fobj.write('\n'.join(files_list))

    return 0
Example #23
0
def configure_help(args, config, basepath, workspace):
    """Entry point for the devtool 'configure-help' subcommand"""
    import oe.utils

    check_workspace_recipe(workspace, args.recipename)
    tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
    try:
        rd = parse_recipe(config, tinfoil, args.recipename, appends=True, filter_workspace=False)
        if not rd:
            return 1
        b = rd.getVar('B')
        s = rd.getVar('S')
        configurescript = os.path.join(s, 'configure')
        confdisabled = 'noexec' in rd.getVarFlags('do_configure') or 'do_configure' not in (rd.getVar('__BBTASKS', False) or [])
        configureopts = oe.utils.squashspaces(rd.getVar('CONFIGUREOPTS') or '')
        extra_oeconf = oe.utils.squashspaces(rd.getVar('EXTRA_OECONF') or '')
        extra_oecmake = oe.utils.squashspaces(rd.getVar('EXTRA_OECMAKE') or '')
        do_configure = rd.getVar('do_configure') or ''
        do_configure_noexpand = rd.getVar('do_configure', False) or ''
        packageconfig = rd.getVarFlags('PACKAGECONFIG') or []
        autotools = bb.data.inherits_class('autotools', rd) and ('oe_runconf' in do_configure or 'autotools_do_configure' in do_configure)
        cmake = bb.data.inherits_class('cmake', rd) and ('cmake_do_configure' in do_configure)
        cmake_do_configure = rd.getVar('cmake_do_configure')
        pn = rd.getVar('PN')
    finally:
        tinfoil.shutdown()

    if 'doc' in packageconfig:
        del packageconfig['doc']

    if autotools and not os.path.exists(configurescript):
        logger.info('Running do_configure to generate configure script')
        try:
            stdout, _ = exec_build_env_command(config.init_path, basepath,
                                               'bitbake -c configure %s' % args.recipename,
                                               stderr=subprocess.STDOUT)
        except bb.process.ExecutionError:
            pass

    if confdisabled or do_configure.strip() in ('', ':'):
        raise DevtoolError("do_configure task has been disabled for this recipe")
    elif args.no_pager and not os.path.exists(configurescript):
        raise DevtoolError("No configure script found and no other information to display")
    else:
        configopttext = ''
        if autotools and configureopts:
            configopttext = '''
Arguments currently passed to the configure script:

%s

Some of those are fixed.''' % (configureopts + ' ' + extra_oeconf)
            if extra_oeconf:
                configopttext += ''' The ones that are specified through EXTRA_OECONF (which you can change or add to easily):

%s''' % extra_oeconf

        elif cmake:
            in_cmake = False
            cmake_cmd = ''
            for line in cmake_do_configure.splitlines():
                if in_cmake:
                    cmake_cmd = cmake_cmd + ' ' + line.strip().rstrip('\\')
                    if not line.endswith('\\'):
                        break
                if line.lstrip().startswith('cmake '):
                    cmake_cmd = line.strip().rstrip('\\')
                    if line.endswith('\\'):
                        in_cmake = True
                    else:
                        break
            if cmake_cmd:
                configopttext = '''
The current cmake command line:

%s

Arguments specified through EXTRA_OECMAKE (which you can change or add to easily)

%s''' % (oe.utils.squashspaces(cmake_cmd), extra_oecmake)
            else:
                configopttext = '''
The current implementation of cmake_do_configure:

cmake_do_configure() {
%s
}

Arguments specified through EXTRA_OECMAKE (which you can change or add to easily)

%s''' % (cmake_do_configure.rstrip(), extra_oecmake)

        elif do_configure:
            configopttext = '''
The current implementation of do_configure:

do_configure() {
%s
}''' % do_configure.rstrip()
            if '${EXTRA_OECONF}' in do_configure_noexpand:
                configopttext += '''

Arguments specified through EXTRA_OECONF (which you can change or add to easily):

%s''' % extra_oeconf

        if packageconfig:
            configopttext += '''

Some of these options may be controlled through PACKAGECONFIG; for more details please see the recipe.'''

        if args.arg:
            helpargs = ' '.join(args.arg)
        elif cmake:
            helpargs = '-LH'
        else:
            helpargs = '--help'

        msg = '''configure information for %s
------------------------------------------
%s''' % (pn, configopttext)

        if cmake:
            msg += '''

The cmake %s output for %s follows. After "-- Cache values" you should see a list of variables you can add to EXTRA_OECMAKE (prefixed with -D and suffixed with = followed by the desired value, without any spaces).
------------------------------------------''' % (helpargs, pn)
        elif os.path.exists(configurescript):
            msg += '''

The ./configure %s output for %s follows.
------------------------------------------''' % (helpargs, pn)

        olddir = os.getcwd()
        tmppath = tempfile.mkdtemp()
        with tempfile.NamedTemporaryFile('w', delete=False) as tf:
            if not args.no_header:
                tf.write(msg + '\n')
            tf.close()
            try:
                try:
                    cmd = 'cat %s' % tf.name
                    if cmake:
                        cmd += '; cmake %s %s 2>&1' % (helpargs, s)
                        os.chdir(b)
                    elif os.path.exists(configurescript):
                        cmd += '; %s %s' % (configurescript, helpargs)
                    if sys.stdout.isatty() and not args.no_pager:
                        pager = os.environ.get('PAGER', 'less')
                        cmd = '(%s) | %s' % (cmd, pager)
                    subprocess.check_call(cmd, shell=True)
                except subprocess.CalledProcessError as e:
                    return e.returncode
            finally:
                os.chdir(olddir)
                shutil.rmtree(tmppath)
                os.remove(tf.name)
Example #24
0
def deploy(args, config, basepath, workspace):
    """Entry point for the devtool 'deploy' subcommand"""
    import re
    import oe.recipeutils

    check_workspace_recipe(workspace, args.recipename, checksrc=False)

    try:
        host, destdir = args.target.split(':')
    except ValueError:
        destdir = '/'
    else:
        args.target = host

    deploy_dir = os.path.join(basepath, 'target_deploy', args.target)
    deploy_file = os.path.join(deploy_dir, args.recipename + '.list')

    tinfoil = setup_tinfoil(basepath=basepath)
    try:
        rd = oe.recipeutils.parse_recipe_simple(tinfoil.cooker,
                                                args.recipename,
                                                tinfoil.config_data)
    except Exception as e:
        raise DevtoolError('Exception parsing recipe %s: %s' %
                           (args.recipename, e))
    recipe_outdir = rd.getVar('D', True)
    if not os.path.exists(recipe_outdir) or not os.listdir(recipe_outdir):
        raise DevtoolError('No files to deploy - have you built the %s '
                           'recipe? If so, the install step has not installed '
                           'any files.' % args.recipename)

    if args.dry_run:
        print('Files to be deployed for %s on target %s:' %
              (args.recipename, args.target))
        for root, _, files in os.walk(recipe_outdir):
            for fn in files:
                print('  %s' % os.path.join(
                    destdir, os.path.relpath(root, recipe_outdir), fn))
        return 0

    if os.path.exists(deploy_file):
        if undeploy(args, config, basepath, workspace):
            # Error already shown
            return 1

    extraoptions = ''
    if args.no_host_check:
        extraoptions += '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
    if args.show_status:
        tarextractopts = 'xv'
    else:
        tarextractopts = 'x'
        extraoptions += ' -q'
    # We cannot use scp here, because it doesn't preserve symlinks
    ret = exec_fakeroot(rd,
                        'tar cf - . | ssh %s %s \'tar %s -C %s -f -\'' %
                        (extraoptions, args.target, tarextractopts, destdir),
                        cwd=recipe_outdir,
                        shell=True)
    if ret != 0:
        raise DevtoolError('Deploy failed - rerun with -s to get a complete '
                           'error message')

    logger.info('Successfully deployed %s' % recipe_outdir)

    if not os.path.exists(deploy_dir):
        os.makedirs(deploy_dir)

    files_list = []
    for root, _, files in os.walk(recipe_outdir):
        for filename in files:
            filename = os.path.relpath(os.path.join(root, filename),
                                       recipe_outdir)
            files_list.append(os.path.join(destdir, filename))

    with open(deploy_file, 'w') as fobj:
        fobj.write('\n'.join(files_list))

    return 0