--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/scripts/conesub_generate.py Thu Mar 11 17:04:37 2010 +0200
@@ -0,0 +1,418 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+#
+
+import os
+import sys
+import logging
+from optparse import OptionParser, OptionGroup
+import cone_common
+import time
+from os import path
+from cone.public import api, plugin, utils, exceptions
+import generation_report
+ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
+
+VERSION = '1.0'
+
+
+def main():
+ parser = OptionParser(version="%%prog %s" % VERSION)
+
+ parser.add_options(cone_common.COMMON_OPTIONS)
+
+ parser.add_option("-c", "--configuration",\
+ dest="configuration",\
+ help="defines the name of the configuration for the action",\
+ metavar="CONFIG")
+
+ parser.add_option("-p", "--project",\
+ dest="project",\
+ help="defines the location of current project. Default is the current working directory.",\
+ default=".",\
+ metavar="STORAGE")
+
+ gen_group = OptionGroup(parser, 'Generate options',
+ 'The generate function will create target files from a specific configuration.'\
+ 'The generate will always work with read-only mode of the project, so no changes are saved to project')
+
+ gen_group.add_option("-o", "--output",\
+ dest="output",\
+ help="defines the target folder where the files are is generated or copied",\
+ metavar="FOLDER",\
+ default="output")
+
+ gen_group.add_option("-l", "--layer",\
+ dest="layers",\
+ type="int",
+ action="append",
+ help="define layers of the configuration that are included to the output. "\
+ "The layer operation can be used several times in a single command."\
+ "Example -l -1 --layer=-2, which would append a layers -1 and -2 to the layers => layers = -1,-2",
+ metavar="LAYER",\
+ default=None)
+
+ gen_group.add_option("--all-layers",
+ dest="all_layers",
+ action="store_true",
+ help="Include all layers in generation. This switch overrides all other layer "\
+ "configurations (iMaker API and using the --layer parameter)",
+ default=False)
+
+ gen_group.add_option("-i", "--impl",\
+ dest="impls",\
+ action="append",
+ help=\
+"""Define a Python regular expression filter for actual ImplML plugin(s) that needs to be executed. The whole path to ImplML filename is used in the regexp matching.
+The impl operation can be used several times in a single command.
+
+Example1 --impl crml => matches for any ImplML file that has a CrML string in the path.
+Example2 --impl makeml$ => matches for ImplML file that has ends with MakeML string.
+""",
+ metavar="IMPLS",\
+ default=None)
+
+ gen_group.add_option("--impl-tag",\
+ dest="tags",\
+ type="string",
+ action="append",
+ help="define a tag for the implementations that are included to the output. "\
+ "A tag is name value pair and has the following format: name:value, e.g. target:rofs3."\
+ "Example --impl-tag=target:uda --impl-tag=target:content, which would include impls include both tags.",
+ metavar="TAG",\
+ default=None)
+
+ gen_group.add_option("--impl-tag-policy",\
+ dest="tags_policy",\
+ type="string",
+ action="append",
+ help="Policy for implementation tags. May have one of the following values: --impl-tag-policy=AND, --impl-tag-policy=OR. "\
+ "Default is OR.",
+ metavar="TAGS_POLICY",\
+ default=None)
+
+ gen_group.add_option("-s", "--set",\
+ dest="overrides",\
+ action="append",
+ type="string",
+ help="Override a ConfML reference in the execution."\
+ "The set operation can be used several times in a single command."\
+ "Example -s foo.bar=10 -s foo.fea='test'.",
+ metavar="SET",\
+ default=None)
+
+ gen_group.add_option("--add",\
+ dest="added",\
+ action="append",
+ type="string",
+ help="Add a given configuration to the given configuration as last element."\
+ "The add operation can be used several times in a single command."\
+ "Example --add foo/root.confml --add bar/root-confml.",
+ metavar="CONF",\
+ default=None)
+
+ gen_group.add_option("-r", "--report",\
+ dest="report",\
+ action="store",
+ type="string",
+ help="Generates a report about settings that are properly generated."\
+ "Example -r report.html.",
+ metavar="FILE",\
+ default=None)
+
+ gen_group.add_option("-t", "--template",\
+ dest="template",\
+ action="store",
+ type="string",
+ help="Template used in report generation."\
+ "Example -t report_template.html.",
+ metavar="FILE",\
+ default=None)
+
+ gen_group.add_option("--report-data-output",\
+ type="string",
+ help="Specifies a file where intermediary report data is generated.",
+ metavar="FILE",\
+ default=None)
+
+ gen_group.add_option("-n", "--dryrun",\
+ dest="dryrun",\
+ action="store_true",
+ help="Executes generation without generation output.",
+ default=False)
+
+ gen_group.add_option("--add-setting-file",\
+ dest="settings",\
+ action="append",
+ type="string",
+ help="Generate specific settings in ini format."\
+ "Example -o my_generate_settings.cfg.",
+ metavar="FILE",\
+ default=None)
+
+ layers = None
+ current = None
+ remote = None
+
+ start_time = time.time()
+
+ parser.add_option_group(gen_group)
+ (options, args) = parser.parse_args()
+
+ settinglist = [os.path.join(ROOT_PATH,'conesub_generate.cfg')]
+ if options.settings:
+ for setting_file in options.settings:
+ settinglist.append(os.path.normpath(os.path.join(ROOT_PATH, setting_file)))
+ gset = cone_common.get_settings(settinglist)
+
+ cone_common.handle_common_options(options, settings=gset)
+
+ current = api.Project(api.Storage.open(options.project,"r"))
+ active_root = current.get_storage().get_active_configuration()
+ if not options.configuration:
+ if active_root == "":
+ parser.error("configuration must be given")
+ else:
+ logging.getLogger('cone').info('No configuration given! Using active root configuration %s' % active_root)
+ options.configuration = active_root
+ try:
+ config = current.get_configuration(options.configuration)
+ except exceptions.NotFound:
+ parser.error("No such configuration: %s" % options.configuration)
+ reffilters = None
+ implfilters = None
+ impltags = None
+
+ # Include possible additional configurations
+ if options.added:
+ for configname in options.added:
+ logging.getLogger('cone').info('Adding configuration %s' % configname)
+ config.include_configuration(utils.resourceref.norm(configname))
+
+ # Get defs from configuration
+ try:
+ layer_str_list = (config.get_default_view().get_feature('imakerapi.cone_layers').get_value() or '').split(',')
+ # Make sure that empty layers definitions are ignored
+ layer_str_list = utils.distinct_array(layer_str_list)
+ if '' in layer_str_list:
+ layer_str_list.remove('')
+ # converting layrs identifiers from strings to int
+ layerdefs = []
+ for layerstr in layer_str_list:
+ try:
+ layerdefs.append(int(layerstr))
+ except ValueError, e:
+ logging.getLogger('cone').error('Invalid layer filter %s' % layerstr)
+ implfilters = (config.get_default_view().get_feature('imakerapi.cone_impls').get_value() or '').split(',')
+ except exceptions.NotFound:
+ layerdefs = []
+ implfilters = []
+ pass
+
+ # Get filters from command line if they exist => cmd overrides configuration
+ if options.layers:
+ layerdefs = options.layers
+ if options.impls:
+ implfilters = options.impls
+ if options.tags and len(options.tags) > 0:
+ impltags = {}
+ for tag in options.tags:
+ (name,value) = tag.split(':',2)
+ existingvalue = impltags.get(name,[])
+ existingvalue.append(value)
+ impltags[name] = existingvalue
+ logging.getLogger('cone').info('Tag filter %s' % impltags)
+ else:
+ impltags = None
+
+ tags_policy = 'OR'
+ if options.tags_policy:
+ tags_policy = options.tags_policy[0]
+
+ # Finally, --all-layers overrides all other layer settings
+ if options.all_layers:
+ layerdefs = []
+
+ logging.getLogger('cone').info('Layer filter %s' % layerdefs)
+
+ # Add reffilters only if the given layerids are somehow reasonable
+ if len(layerdefs) > 0:
+ # get the data references from given layers
+ logging.getLogger('cone').info('Getting layer specific data reference from %s' % layerdefs)
+ reffilters = []
+ for layerid in utils.distinct_array(layerdefs):
+ logging.getLogger('cone').info('Searching layer %s' % layerid)
+ layer = config.get_configuration_by_index(layerid)
+ refs = _get_new_refs(reffilters, layer.list_leaf_datas())
+ logging.getLogger('cone').info("Refs from layer '%s'\n%s" % (layer.get_path(), '\n'.join(refs)))
+ reffilters += refs
+
+
+ if options.overrides:
+ config.add_configuration(api.Configuration('tempdata.confml'))
+ for override in options.overrides:
+ (ref,value) = override.split('=',1)
+ config.get_default_view().get_feature(ref).set_value(value)
+
+ # Make sure that the output folder exists
+ if not os.path.exists(options.output):
+ os.makedirs(options.output)
+
+ impls = plugin.filtered_impl_set(config,implfilters)
+ impls.output = options.output
+
+ logging.getLogger('cone').info("Supported implementation file extensions: %r" % plugin.get_supported_file_extensions())
+
+# logging.getLogger('cone').debug('Loaded implementations:')
+# for impl in impls:
+# msg = "File '%s', impl. type '%s', class '%s', phase '%s'" % \
+# (impl.ref, impl.IMPL_TYPE_ID, type(impl).__name__, impl.invocation_phase())
+# logging.getLogger('cone').debug(msg)
+
+
+ # Create temporary variables
+ temp_feature_refs = impls.create_temp_features(config)
+ if reffilters is not None:
+ reffilters.extend(temp_feature_refs)
+ logging.getLogger('cone').info('Refs from temporary variables:\n%s' % '\n'.join(temp_feature_refs))
+
+
+
+ # ---------------
+ # Generate output
+ # ---------------
+
+ rule_exec_results = []
+
+ # Create an implementation container with all the relevant implementations
+ all_impls = impls.filter_implementations(tags=impltags, policy=tags_policy)
+
+ # Implementations taking part in output generation
+ gen_impls = plugin.ImplSet()
+ context = plugin.GenerationContext()
+ context.configuration = config
+ log = logging.getLogger('cone')
+ for phase in plugin.ImplSet.INVOCATION_PHASES:
+ phase_impls = all_impls.filter_implementations(phase=phase)
+ log.info("Generating phase '%s', %d implementation(s)" % (phase, len(phase_impls)))
+
+ context.phase = phase
+ # No use going any further if there are no implementations
+ # for the phase at all
+ if len(phase_impls) == 0:
+ continue
+
+ # Load and execute rules for this phase
+ # -------------------------------------
+# relation_container = phase_impls.get_relation_container()
+# log.info("%d rule(s) for phase '%s'" % (relation_container.get_relation_count(), phase))
+# if relation_container.get_relation_count() > 0:
+# log.info("Executing rules...")
+# results = relation_container.execute()
+# log.info("Got %d execution result(s)" % len(results))
+# rule_exec_results.extend(results)
+
+
+ # Create an implementation container for the phase with
+ # the new reffilters and generate output with it
+ # -----------------------------------------------------
+ impls = phase_impls.filter_implementations(refs=reffilters)
+ log.info("%d implementation(s) after filtering for phase '%s'" % (len(impls), phase))
+ if len(impls) > 0:
+ if impltags != None:
+ context.tags = impltags
+ context.tags_policy = tags_policy
+ impls.output = options.output
+ log.info("Generating output...")
+ impls.generate(context)
+ impls.post_generate(context)
+
+ # Add new refs after generation
+# if reffilters != None and len(reffilters) > 0:
+# layer = config.get_configuration_by_index(-1)
+# new_refs = _get_new_refs(reffilters, layer.list_leaf_datas())
+# log.info('Added %d ref(s) after generation:\n%s' % (len(new_refs), '\n'.join(new_refs)))
+# reffilters += new_refs
+
+ # Add new references after each phase execution
+ # ---------------------------------------
+ if reffilters != None and len(reffilters) > 0:
+ layer = config.get_configuration_by_index(-1)
+ new_refs = _get_new_refs(reffilters, layer.list_leaf_datas())
+ log.info('Added %d ref(s) after phase %s execution:\n%s' % (len(new_refs), phase, '\n'.join(new_refs)))
+ reffilters += new_refs
+
+ # Add the implementations to the set of implementations participating
+ # in output generation (used in the report)
+ for impl in impls:
+ for actual_impl in impl.get_all_implementations():
+ logging.getLogger('cone').info('Adding impl %s' % impl)
+ gen_impls.add(actual_impl)
+
+ rule_exec_results = context.results
+ print "Generated %s to %s!" % (options.configuration, impls.output)
+
+
+ # ---------------
+ # Generate report
+ # ---------------
+
+ # If reporting is enabled collect data for report
+ if options.report != None or options.report_data_output != None:
+ logging.getLogger('cone').info('Collecting data for report.')
+ all_refs = reffilters or utils.distinct_array(config.get_configuration_by_index(-1).list_leaf_datas())
+ logging.getLogger('cone').info('Collecting data found refs %s' % all_refs)
+ logging.getLogger('cone').info('Collecting data found gen_impls %s' % gen_impls)
+ rep_data = generation_report.collect_report_data(config, options, all_refs, gen_impls, rule_exec_results)
+ logging.getLogger('cone').info('Collecting data found rep_data %s' % rep_data)
+
+ duration = str("%.3f" % (time.time() - start_time) )
+ rep_data.set_duration( duration )
+
+ # Save intermediary report data file if necessary
+ if options.report_data_output != None:
+ logging.getLogger('cone').info('Dumping report data to %s' % options.report_data_output)
+ print "Dumping report data to '%s'" % options.report_data_output
+ generation_report.save_report_data(rep_data, options.report_data_output)
+
+ # Generate the report if necessary
+ if options.report != None:
+ generation_report.generate_report(rep_data, options.report, options.template)
+ print_summary(rep_data)
+
+ if current: current.close()
+
+def _get_new_refs(old_refs, new_refs):
+ """
+ Return a distinct array of refs in ``new_refs`` that are not present in ``old_refs``.
+ """
+ result = []
+ for ref in new_refs:
+ if ref not in old_refs and ref not in result:
+ result.append(ref)
+ return result
+
+def print_summary(rep_data):
+ """ Prints generation summary to logger and console. """
+ print "\nGENERATION SUMMARY:"
+ print "--------------------"
+ print "Refs in files: %s" % rep_data.nbr_of_refs
+ print "Refs with no implementation: %s" % rep_data.nbr_of_refs_noimpl
+ print "Generation duration: %s" % rep_data.duration
+ print "\n\n"
+
+
+if __name__ == "__main__":
+ main()