def do(cls, ws, args): '''Executes the build subcmd.''' ws_config = get_ws_config(get_ws_dir(args.root, ws)) d = parse_manifest(args.root) # Validate. for project in args.projects: if project not in d: raise WSError('unknown project %s' % project) if len(args.projects) == 0: projects = d.keys() else: projects = args.projects # Build in reverse-dependency order. order = dependency_closure(d, projects) # Get all checksums; since this is a nop build bottle-neck, do it in # parallel. On my machine, this produces a ~20% speedup on a nop # "build-all". pool = multiprocessing.Pool(multiprocessing.cpu_count()) src_dirs = [get_source_dir(args.root, d, proj) for proj in order] checksums = pool.map(calculate_checksum, src_dirs) for i, proj in enumerate(order): log('building %s' % proj) checksum = checksums[i] success = _build(args.root, ws, proj, d, checksum, ws_config, args.force) if not success: raise WSError('%s build failed' % proj)
def _polite_clean(root, ws, proj, d): '''Performs a polite-clean of a project, calling the underlying build system of a project and asking it to clean itself.''' builder = get_builder(d, proj) build_dir = get_build_dir(ws, proj) if not os.path.exists(build_dir): return build_env = get_build_env(ws, d, proj) prefix = get_install_dir(ws, proj) source_dir = get_source_dir(root, d, proj) builder.clean(proj, prefix, source_dir, build_dir, build_env)
def _build(root, ws, proj, d, current, ws_config, force): '''Builds a given project.''' if not ws_config['projects'][proj]['enable']: log('not building manually disabled project %s' % proj, logging.WARNING) return True if ws_config['projects'][proj]['taint']: log('force-cleaning tainted project %s' % proj, logging.WARNING) clean(root, ws, proj, d, True) source_dir = get_source_dir(root, d, proj) if not force: stored = get_stored_checksum(ws, proj) if current == stored: log('checksum for %s is current; skipping' % proj) return True else: log('forcing a build of %s' % proj) # Make the project directory if needed. proj_dir = get_proj_dir(ws, proj) try: mkdir(proj_dir) except OSError as e: if e.errno != errno.EEXIST: raise # Make the build directory if needed. build_dir = get_build_dir(ws, proj) try: mkdir(build_dir) except OSError as e: if e.errno != errno.EEXIST: raise needs_configure = False else: needs_configure = True # Populate the convenience source link. source_link = get_source_link(ws, proj) if not os.path.exists(source_link): source_dir = get_source_dir(root, d, proj) symlink(source_dir, source_link) # Invalidate the checksums for any downstream projects. for downstream_dep in d[proj]['downstream']: invalidate_checksum(ws, downstream_dep) # Add envs to find all projects on which this project is dependent. build_env = get_build_env(ws, d, proj) # Configure. builder = get_builder(d, proj) prefix = get_install_dir(ws, proj) extra_args = d[proj]['args'] + ws_config['projects'][proj]['args'] if needs_configure: try: success = builder.conf(proj, prefix, source_dir, build_dir, build_env, ws_config['type'], d[proj]['builder-args'], extra_args) except Exception as _e: success = False e = _e else: e = None if not success: # Remove the build directory if we failed so that we are forced to # re-run configure next time. rmtree(build_dir) if e is not None: raise e else: return False # Build. success = builder.build(proj, prefix, source_dir, build_dir, build_env, d[proj]['targets'], d[proj]['builder-args'], d[proj]['args']) if success: set_stored_checksum(ws, proj, current) return success