Exemplo n.º 1
0
def handle_action(args):
	Core.preprocess_arguments(args)

	# populate args.architecture with sane values
	args.architecture = filter_architectures(
		args.architecture,
		Core.supported_architectures,
		TargetPlatform.instance.default_architectures()
	)

	# Now that we have a list of architectures -- verify the target
	# platform can use that.
	for arch in args.architecture:
		if not TargetPlatform.compiler.supports_build_architecture(
					Language.CPP, arch
				):
			raise Exception(
				"TargetPlatform does not support architecture: %s!" % arch
			)


	global_params = Attributes()



	if args.command in ["generate", "build", "clean"]:
		# required for running command-line utils
		executor = Executor()

		# This first step accomplishes the following:
		# - loops through all product data in buildfile and generates dependencies
		# - use/generate BuildCache by associated products and dependencies with buildfiles
		gather_product_data(
			args,
			args.architecture,
			args.configuration,
			os.path.abspath(args.build_file),
			args.products if getattr(args, "products", None) else None,
			global_params,
			executor,
			[]
		)

		# Using the buildcache we generated (or loaded) above,
		# execute the command on products in the correct order.
		BuildCache.execute_command(executor, args.command, execute_command)

		# save file manager data
		FileManager.instance.save()
	elif args.command in ["distclean"]:
		FileManager.instance.distclean()
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
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)