def add_common_options(buildfile, parser): parser.add_argument( "-p", "--products", dest="products", help="Comma separated list of products (list --products)", default=None ) parser.add_argument( "-a", "--architecture", dest="architecture", help="Comma separated list of architectures to use. \ NOTE: Some platforms may only support a single architecture \ per project. In this case, only the first element will be used.", default=None ) parser.add_argument( "-c", "--configuration", dest="configuration", help="Comma separated list of build types: debug,release", default=None ) parser.add_argument( "-t", "--target", dest="target_platform", help="Target platform override; defaults to host platform", default=None ) parser.add_argument( "-d", "--driver", dest="driver_name", help="Driver override; default is based on target platform", default=None ) parser.add_argument( "-n", "--no-dependencies", dest="recurse_dependencies", action="store_false", help="Execute this command for the top level products only. \ Do not recursively call on dependencies", default=True ) if not Environment.get().use_cache: buildfile.load_arguments(parser=parser)
def main(): Core.startup() Environment.instance = Environment() FileManager.instance = FileManager() # load the file and any options it may contain if len(sys.argv) < 2: raise Exception("No build file specified.") if len(sys.argv) > 1 and os.path.exists(sys.argv[1]): buildfile = BuildFile(sys.argv[1]) else: raise Exception("Build file: \"%s\" does not exist!" % sys.argv[1]) p = argparse.ArgumentParser(prog="pegasus") p.add_argument( "-q", dest="quiet", help="Log to a file, don't output to stdout", action="store_true", default=False ) # position arguments p.add_argument("build_file", help="Target build file") # setup commands p_cmd = p.add_subparsers( dest="command", title="Commands", description="Available Commands" ) p_list = p_cmd.add_parser( "list", help="List all products in the build file" ) p_list.set_defaults(target_platform=None, command_callback=handle_list) p_generate = p_cmd.add_parser( "generate", help="Generate projects for product(s)" ) p_generate.set_defaults( command_callback=handle_action, use_cache=False, action_name="generate" ) add_common_options(buildfile, p_generate) p_build = p_cmd.add_parser("build", help="Build the project") p_build.set_defaults( command_callback=handle_action, use_cache=True, action_name="build" ) add_common_options(buildfile, p_build) p_clean = p_cmd.add_parser("clean", help="Clean the project") p_clean.set_defaults( command_callback=handle_action, use_cache=True, action_name="clean" ) add_common_options(buildfile, p_clean) p_distclean = p_cmd.add_parser( "distclean", help="Purge directories of generated files" ) p_distclean.set_defaults( command_callback=handle_action, use_cache=True, action_name="distclean" ) add_common_options(buildfile, p_distclean) args = p.parse_args() # setup environment Environment.get().use_cache = \ args.use_cache if hasattr(args, "use_cache") else False # register classes (HostPlatforms, Drivers) Core.register_classes(args) logging.info("HostPlatform is %s" % HostPlatform.get()) logging.info("TargetPlatform is %s" % TargetPlatform.get()) logging.info("Compiler is %s, version: %s" % ( TargetPlatform.get_compiler_name(), TargetPlatform.compiler.get_version()) ) # run command args.command_callback(args) if not Environment.get().use_cache: BuildCache.save_caches()
def gather_product_data( cmd_args, architectures, configurations, absolute_buildfile_path, selected_product_names, global_params, executor, context_list ): prepend_dependency_values = True operate_on_dependencies = True process_configs_enabled = True rootcd = None # load the buildfile buildfile = BuildFile.find_or_create( build_file_path=absolute_buildfile_path, architectures=architectures, configurations=configurations ) # fetch a list of potential products to operate on all_products = buildfile.get_products( args=cmd_args, host_platform=HostPlatform, target_platform=TargetPlatform.instance, global_params=global_params ) # need to filter products here products = buildfile.filter_products( selected_product_names, all_products ) for product in products: # ignore targets unsupported by this driver if not TargetPlatform.instance.product_supported( product, Driver.instance, Driver.name ): continue BuildCache.add_product(buildfile.abs_buildfile_path, product) # create the product context context = ProductContext.find_or_create(buildfile=buildfile, product=product) # determine if we need to process config files if process_configs_enabled: process_config_files(context) # whitelist the product root so we don't remove it. FileManager.instance.whitelist(context.abs_root) # fetch architectures and configurations for this product architectures, configurations = buildfile.get_layout_params(product) dependencies = [] prebuild_commands = {} postbuild_commands = [] dependency_contexts = [] if not Environment.get().use_cache: BuildCache.add_product( buildfile.abs_buildfile_path, product ) # fetch all direct dependencies for this product # these are returned as Dependency instances dependencies = product.get_dependencies( context, architectures, configurations ) if operate_on_dependencies and dependencies: for dependency in dependencies: # create a buildfile instance dep_buildfile = BuildFile.find_or_create( build_file_path=dependency.abs_file, parent=buildfile, architectures=architectures, configurations=configurations, ) # create a temp parser and parse the dependency's args # if any exist parser = argparse.ArgumentParser() dep_buildfile.load_arguments(parser=parser) dep_args = parser.parse_args(dependency.arguments) # fetch ALL products for this dependency all_products = dep_buildfile.get_products( args=dep_args, host_platform=HostPlatform, target_platform=TargetPlatform.instance, global_params=global_params ) # filter out only the ones we're interested in using the # dependency instance as a mask ("products") filtered_products = dep_buildfile.filter_products( dependency.products, all_products ) for p in filtered_products: BuildCache.add_product( dep_buildfile.abs_buildfile_path, p ) # NOTE: This is a temporary ProductContext # So it does NOT go through the normal find_or_create # mechanism. dep_context = ProductContext( buildfile=dep_buildfile, product=p, parent=context ) # # populate context with layout params for architecture in architectures: for configuration in configurations: layout_params = LayoutParams( TargetPlatform.instance, dep_context, architecture, configuration ) layout_params.populate() dep_context.add_layout(layout_params) dependency_contexts.append(dep_context) # for each context, add layout params for # arch/config permutations # run command on dependencies for dep_context in dependency_contexts: if not Environment.get().use_cache: BuildCache.add_dependency( buildfile.abs_buildfile_path, product.name, dep_context.buildfile.abs_buildfile_path, dep_context.product.name ) if dep_context.product.output == ProductType.None: continue # run this command on the dependency (recursively) if cmd_args.recurse_dependencies: # for dependencies within the same file, we need to # ensure correct build orders. # # Re-use the base level context_list if this dependency # is in the same buildfile as the current one. # # Due to the recursive nature, dependencies will be # prepended in the context list to their dependents. dep_context_list = [] if buildfile.abs_buildfile_path == dep_context.buildfile.abs_buildfile_path: dep_context_list = context_list # recursive call... gather_product_data( cmd_args, architectures, configurations, dep_context.buildfile.abs_buildfile_path, [dep_context.product.name], global_params, executor, dep_context_list ) for architecture in architectures: if architecture not in prebuild_commands: prebuild_commands[architecture] = {} for configuration in configurations: if configuration not in prebuild_commands[architecture]: prebuild_commands[architecture][configuration] = [] prebuild_commands[architecture][configuration] += \ Driver.instance.prebuild_commands_for_dependency( architecture, configuration, TargetPlatform.instance, context, dep_context ) # maintain a unique ordered set of ProductContexts. if context not in context_list: context_list.append(context) for architecture in architectures: for configuration in configurations: # fetch the layout from the product params = LayoutParams( TargetPlatform.instance, context, architecture, configuration ) # populate params params.populate( global_params=global_params, dependencies=dependency_contexts ) prebuild_command_list = [] if architecture in prebuild_commands and configuration in prebuild_commands[architecture]: prebuild_command_list = prebuild_commands[architecture][configuration] params.prebuild_commands = \ prebuild_command_list + params.prebuild_commands params.postbuild_commands = \ postbuild_commands + params.postbuild_commands # process these through the target platform output_params = \ TargetPlatform.instance.process_params_for_driver( params, Driver.instance, Driver.instance.__class__.__name__.lower() ) # create the abs_project_root FileManager.instance.makedirs(output_params.abs_project_root) # add these params to the context layout context.add_layout(output_params) product_data = BuildCache.get_product_data(buildfile.abs_buildfile_path, context.product.name) if (not product_data.touched) and product._requires_action: product_data.touched = True product_data.built = False BuildCache.queue_product(buildfile.abs_buildfile_path, product)