/tool/geant/src/geant_project.e
Specman e | 669 lines | 518 code | 78 blank | 73 comment | 32 complexity | 6eb585e9731ee626a35cc63d2945f141 MD5 | raw file
- note
- description:
- "Contents of geant project files"
- library: "Gobo Eiffel Ant"
- copyright: "Copyright (c) 2001-2018, Sven Ehrke and others"
- license: "MIT License"
- date: "$Date$"
- revision: "$Revision$"
- class GEANT_PROJECT
- inherit
- ANY
- KL_SHARED_ARGUMENTS
- export {NONE} all end
- KL_SHARED_EXCEPTIONS
- export {NONE} all end
- GEANT_SHARED_PROPERTIES
- export {NONE} all end
- create
- make
- feature {NONE} -- Initialization
- make (a_variables: GEANT_PROJECT_VARIABLES; a_options: GEANT_PROJECT_OPTIONS; a_name: STRING)
- -- Create a new project.
- require
- a_variables_not_void: a_variables /= Void
- a_options_not_void: a_options /= Void
- a_name_not_void: a_name /= Void
- a_name_not_empty: not a_name.is_empty
- local
- a_tester: UC_STRING_EQUALITY_TESTER
- do
- name := a_name
- output_file := std.output
- set_variables (a_variables)
- set_options (a_options)
- create selected_targets.make_map (5)
- create a_tester
- selected_targets.set_key_equality_tester (a_tester)
- create {DS_ARRAYED_STACK [GEANT_TARGET]} targets_stack.make (10)
- create task_factory.make (Current)
- build_successful := True
- ensure
- variables_set: variables = a_variables
- options_set: options = a_options
- selected_targets_not_void: selected_targets /= Void
- name_set: name = a_name
- end
- feature -- Access
- name: STRING
- -- Name of project
- start_target_name: detachable STRING
- -- Name of first target to be built
- description: detachable STRING
- -- Project description
- variables: GEANT_PROJECT_VARIABLES
- -- Project variables
- aggregated_variables_array: ARRAY [GEANT_VARIABLES]
- -- Array of available variables sets
- -- i.e: arguments, locals, variables
- do
- Result := <<target_arguments_stack.item, target_locals_stack.item, variables>>
- ensure
- Result_not_void: Result /= Void
- end
- options: GEANT_PROJECT_OPTIONS
- -- Project options
- targets: detachable DS_HASH_TABLE [GEANT_TARGET, STRING]
- -- Immediate targets
- selected_targets: DS_HASH_TABLE [GEANT_TARGET, STRING]
- -- Targets selected in heir
- preferred_start_target: detachable GEANT_TARGET
- -- Preferred target to start build process
- do
- if attached start_target_name as l_start_target_name and then l_start_target_name.count > 0 then
- if attached targets as l_targets then
- if l_targets.has (l_start_target_name) then
- Result := l_targets.item (l_start_target_name)
- end
- end
- end
- end
- default_target: detachable GEANT_TARGET
- -- Target to start build process in case `preferred_start_target' is Void
- do
- if attached default_target_name as l_default_target_name and then l_default_target_name.count > 0 then
- if attached targets as l_targets then
- if l_targets.has (l_default_target_name) then
- Result := l_targets.item (l_default_target_name)
- end
- end
- end
- end
- start_target: GEANT_TARGET
- -- `preferred_start_target' if not Void; `default_target' otherwise
- do
- Result := default_target
- if attached start_target_name as l_start_target_name and then l_start_target_name.count > 0 then
- if not attached preferred_start_target as l_preferred_start_target then
- exit_application (1, <<"Cannot determine start target `", l_start_target_name + "%'">>)
- else
- Result := l_preferred_start_target
- end
- end
- if Result = Void then
- exit_application (1, <<"Cannot determine start target.">>)
- check exited: False then end
- end
- ensure
- start_target_not_void: Result /= Void
- end
- build_successful: BOOLEAN
- -- Was last build successful?
- inherit_clause: detachable GEANT_INHERIT
- -- Inherit clause
- old_inherit: BOOLEAN
- -- Was current defined via old inheritance mechanism?
- -- TODO: remove after obsolete period
- target_name (a_target: GEANT_TARGET): STRING
- -- Name of target `a_target' within context of current project
- require
- a_target_not_void: a_target /= Void
- targets_not_void: attached targets as l_targets
- has_target: l_targets.has_item (a_target)
- local
- a_cursor: DS_HASH_TABLE_CURSOR [GEANT_TARGET, STRING]
- do
- check precondition: attached targets as l_targets then
- Result := ""
- a_cursor := l_targets.new_cursor
- from a_cursor.start until a_cursor.after loop
- if a_target = a_cursor.item then
- Result := a_cursor.key
- a_cursor.go_after -- Jump out of the loop.
- else
- a_cursor.forth
- end
- end
- end
- ensure
- target_name_not_void: Result /= Void
- target_name_not_empty: Result.count > 0
- end
- default_target_name: detachable STRING
- -- Name of default target if set
- position_table: detachable XM_POSITION_TABLE
- -- Position table for XM_NODES
- feature -- Status report
- has_parent_with_name (a_name: STRING): BOOLEAN
- -- Does current project have a parent project named `a_name'?
- local
- i, nb: INTEGER
- a_parent_project: GEANT_PROJECT
- a_parents: DS_ARRAYED_LIST [GEANT_PARENT]
- do
- if attached inherit_clause as l_inherit_clause then
- a_parents := l_inherit_clause.parents
- nb := a_parents.count
- from i := 1 until i > nb loop
- a_parent_project := a_parents.item (i).parent_project
- if a_parent_project /= Void then
- if STRING_.same_string (a_parent_project.name, a_name) then
- Result := True
- i := nb + 1 -- Jump out of the loop.
- elseif a_parent_project.has_parent_with_name (a_name) then
- Result := True
- i := nb + 1 -- Jump out of the loop.
- end
- end
- i := i + 1
- end
- end
- end
- is_builtin_variable_name (a_name: STRING): BOOLEAN
- -- Is `a_name' the name of a built-in variable?
- require
- a_name_not_void: a_name /= Void
- a_name_not_empty: a_name.count > 0
- do
- Result := variables.is_builtin_variable_name (a_name)
- -- Check also buildscript specific built-in variables (see `GEANT_PROJECT_ELEMENT.make'):
- Result := Result or else STRING_.same_string (STRING_.concat (name, ".absdir"), a_name)
- Result := Result or else STRING_.same_string (STRING_.concat (name, ".dir"), a_name)
- Result := Result or else STRING_.same_string (STRING_.concat (name, ".filename"), a_name)
- end
- feature -- Setting
- set_description (a_description: STRING)
- -- Set `description' to `a_description'.
- require
- a_description_not_void: a_description /= Void
- a_description_not_empty: a_description.count > 0
- do
- description := a_description
- ensure
- description_set: description = a_description
- end
- set_name (a_name: STRING)
- -- Set `name' to `a_name'.
- require
- a_name_not_void: a_name /= Void
- a_name_not_empty: a_name.count > 0
- do
- name := a_name
- ensure
- name_set: name = a_name
- end
- set_start_target_name (a_start_target_name: STRING)
- -- Set `start_target_name' to `a_start_target_name'.
- require
- a_start_target_name_not_void: a_start_target_name /= Void
- a_start_target_name_not_empty: a_start_target_name.count > 0
- targets_has_a_start_target_name: attached targets as l_targets and then l_targets.has (a_start_target_name)
- do
- start_target_name := a_start_target_name
- ensure
- start_target_name_set: start_target_name = a_start_target_name
- end
- set_default_target_name (a_default_target_name: STRING)
- -- Set `default_target_name' to `a_default_target_name'.
- require
- a_default_target_name_not_void: a_default_target_name /= Void
- a_default_target_name_not_empty: a_default_target_name.count > 0
- do
- default_target_name := a_default_target_name
- ensure
- default_target_name_set: default_target_name = a_default_target_name
- end
- set_targets (a_targets: like targets)
- -- Set `targets' to `a_targets'.
- require
- a_targets_not_void: a_targets /= Void
- do
- targets := a_targets
- ensure
- targets_set: targets = a_targets
- end
- set_variables (a_variables: like variables)
- -- Set `variables' to `a_variables'.
- require
- a_variables_not_void: a_variables /= Void
- do
- variables := a_variables
- ensure
- variables_set: variables = a_variables
- end
- set_options (a_options: like options)
- -- Set `options' to `a_options'.
- require
- a_options_not_void: a_options /= Void
- do
- options := a_options
- ensure
- options_set: options = a_options
- end
- set_inherit_clause (a_inherit_clause: like inherit_clause)
- -- Set `inherit_clause' to `a_inherit_clause'.
- require
- a_inherit_clause_not_void: a_inherit_clause /= Void
- do
- inherit_clause := a_inherit_clause
- ensure
- inherit_clause_set: inherit_clause = a_inherit_clause
- end
- set_old_inherit (a_old_inherit: BOOLEAN)
- -- Set `old_inherit' to `a_old_inherit'.
- -- TODO: remove after obsolete period
- do
- old_inherit := a_old_inherit
- ensure
- old_inherit_set: old_inherit = a_old_inherit
- end
- set_position_table (a_position_table: like position_table)
- -- Set `position_table' to `a_position_table'.
- require
- a_position_table_not_void: a_position_table /= Void
- do
- position_table := a_position_table
- ensure
- position_table_set: position_table = a_position_table
- end
- feature {GEANT_GROUP, GEANT_TARGET} -- Task factory
- new_task (a_xml_element: XM_ELEMENT): detachable GEANT_TASK
- -- New GEANT_TASK for `a_xml_element'
- do
- if attached task_factory as l_task_factory then
- Result := l_task_factory.new_task (a_xml_element)
- end
- end
- task_factory: detachable GEANT_TASK_FACTORY
- -- Task factory associated to Current
- feature -- Processing
- merge_in_parent_projects
- -- Load parent projects if present.
- local
- a_parent: GEANT_PARENT
- a_parent_cursor: DS_LINEAR_CURSOR [GEANT_PARENT]
- a_target: GEANT_TARGET
- a_target_cursor: DS_HASH_TABLE_CURSOR [GEANT_TARGET, STRING]
- do
- -- Handle inherit_clause:
- if attached inherit_clause as l_inherit_clause then
- -- Prepare parent projects:
- a_parent_cursor := l_inherit_clause.parents.new_cursor
- from a_parent_cursor.start until a_parent_cursor.after loop
- a_parent := a_parent_cursor.item
- check parents_parent_project_not_void: a_parent.parent_project /= Void end
- a_parent.prepare_project
- a_parent_cursor.forth
- end
- -- Merge parent projects:
- a_parent_cursor := l_inherit_clause.parents.new_cursor
- from a_parent_cursor.start until a_parent_cursor.after loop
- a_parent := a_parent_cursor.item
- l_inherit_clause.merge_in_parent_project (a_parent)
- a_parent_cursor.forth
- end
- l_inherit_clause.apply_selects
- -- List all targets:
- if attached targets as l_targets then
- from
- a_target_cursor := l_targets.new_cursor
- a_target_cursor.start
- trace_debug (<<"Project '", name, "': target list:">>)
- until
- a_target_cursor.after
- loop
- a_target := a_target_cursor.item
- trace_debug (<<" target `", a_target_cursor.key, "' (", a_target.full_name, ")">>)
- a_target.show_precursors
- a_target_cursor.forth
- end
- end
- end
- end
- calculate_depend_order (a_depend_targets: DS_ARRAYED_STACK [GEANT_TARGET])
- -- Setup `build_targets' according to target dependencies.
- require
- loaded: targets /= Void
- depend_targets_not_void: a_depend_targets /= Void
- local
- a_target: GEANT_TARGET
- a_tmp_dependent_targets: DS_ARRAYED_STACK [GEANT_TARGET]
- do
- -- Get dependent targets:
- a_target := a_depend_targets.item
- trace_debug (<<"pushing target: ", a_target.name>>)
- a_tmp_dependent_targets := a_target.dependent_targets
- -- Add all dependent targets to `build_targets':
- from until a_tmp_dependent_targets.count = 0 loop
- a_depend_targets.force (a_tmp_dependent_targets.item)
- a_tmp_dependent_targets.remove
- -- Recursive call of routine for dependent target:
- calculate_depend_order (a_depend_targets)
- end
- end
- build (a_arguments: GEANT_ARGUMENT_VARIABLES)
- -- Build project: execute project's tasks.
- require
- targets_not_void: targets /= Void
- a_arguments_not_void: a_arguments /= Void
- local
- a_target: GEANT_TARGET
- do
- trace (<<"Building Project">>)
- a_target := start_target
- build_target (a_target, a_arguments)
- end
- show_target_info
- -- Print list of name and description for all targets of project.
- require
- targets_not_void: targets /= Void
- local
- a_cursor: DS_HASH_TABLE_CURSOR [GEANT_TARGET, STRING]
- a_target: GEANT_TARGET
- do
- check precondition: attached targets as l_targets then
- a_cursor := l_targets.new_cursor
- from a_cursor.start until a_cursor.after loop
- a_target := a_cursor.item
- if a_target.is_exported_to_any then
- output_file.put_line (a_target.full_name)
- if attached a_target.obsolete_message as l_obsolete_message then
- output_file.put_line (" obsolete. " + l_obsolete_message)
- end
- output_file.put_line (" " + a_target.description)
- end
- a_cursor.forth
- end
- end
- end
- build_target (a_target: GEANT_TARGET; a_arguments: GEANT_ARGUMENT_VARIABLES)
- -- Analyze dependencies and execute `a_target'.
- require
- a_target_not_void: a_target /= Void
- a_arguments_not_void: a_arguments /= Void
- local
- depend_targets: DS_ARRAYED_STACK [GEANT_TARGET]
- depend_arguments: GEANT_ARGUMENT_VARIABLES
- do
- target_arguments_stack.force (a_arguments)
- -- Analyze dependencies of targets:
- create depend_targets.make (10)
- depend_targets.force (a_target)
- calculate_depend_order (depend_targets)
- -- Execute depend targets (use empty arguments since depend does not support argument passing):
- create depend_arguments.make
- target_arguments_stack.force (depend_arguments)
- from until depend_targets.count = 1 loop
- execute_target (depend_targets.item, depend_arguments, False, True)
- depend_targets.remove
- end
- target_arguments_stack.remove
- -- Execute `a_target':
- check last_target: depend_targets.item = a_target end
- execute_target (a_target, a_arguments, True, True)
- target_arguments_stack.remove
- end
- execute_target (a_target: GEANT_TARGET; a_arguments: GEANT_ARGUMENT_VARIABLES; a_force: BOOLEAN; a_polymorph: BOOLEAN)
- -- Execute `a_target' if not executed before;
- -- Execute anyway if `a_force' is True.
- require
- target_not_void: a_target /= Void
- a_arguments_not_void: a_arguments /= Void
- local
- old_current_target: like current_target
- a_execute_target: like current_target
- do
- trace_debug (<<"project '", name, "': executing target `", a_target.full_name, "%'">>)
- old_current_target := current_target
- if a_force or else not a_target.is_executed then
- -- Handle polymorphic calls:
- if a_polymorph then
- a_execute_target := a_target.final_target
- else
- a_execute_target := a_target
- end
- targets_stack.force (a_execute_target)
- target_locals_stack.force (create {GEANT_VARIABLES}.make)
- check current_target = a_execute_target end
- if a_execute_target.project /= Current then
- a_execute_target.project.execute_target (a_execute_target, a_arguments, a_force, a_polymorph)
- else
- target_arguments_stack.force (a_arguments)
- a_execute_target.execute
- target_arguments_stack.remove
- end
- target_locals_stack.remove
- targets_stack.remove
- end
- check current_target = old_current_target end
- end
- feature -- Output
- trace (a_message: ARRAY [STRING])
- -- Write `a_message' to standard output unless `verbose' = False.
- require
- a_message_not_void: a_message /= Void
- -- Note: ARRAY.has is not portable:
- -- no_void_message: not a_message.has (Void)
- local
- i, nb: INTEGER
- do
- if options.verbose then
- i := a_message.lower
- nb := a_message.upper
- from until i > nb loop
- output_file.put_string (a_message.item (i))
- i := i + 1
- end
- output_file.put_new_line
- output_file.flush
- end
- end
- log (a_message: ARRAY [STRING])
- -- Write `a_message' to standard output.
- require
- a_message_not_void: a_message /= Void
- -- Note: ARRAY.has is not portable:
- -- no_void_message: not a_message.has (Void)
- local
- i, nb: INTEGER
- do
- i := a_message.lower
- nb := a_message.upper
- from until i > nb loop
- output_file.put_string (a_message.item (i))
- i := i + 1
- end
- output_file.put_new_line
- output_file.flush
- end
- trace_debug (a_message: ARRAY [STRING])
- -- Write `a_message' to standard output unless `debug_mode' = False.
- require
- a_message_not_void: a_message /= Void
- -- Note: ARRAY.has is not portable:
- -- no_void_message: not a_message.has (Void)
- local
- i, nb: INTEGER
- do
- if options.debug_mode then
- i := a_message.lower
- nb := a_message.upper
- from until i > nb loop
- output_file.put_string (a_message.item (i))
- i := i + 1
- end
- output_file.put_new_line
- output_file.flush
- end
- end
- output_file: KI_TEXT_OUTPUT_STREAM
- -- Output file
- set_output_file (a_file: like output_file)
- -- Set `output_file' to `a_file'.
- require
- a_file_not_void: a_file /= Void
- a_file_open_write: a_file.is_open_write
- do
- output_file := a_file
- ensure
- output_file_set: output_file = a_file
- end
- feature {GEANT_COMMAND} -- Change variable
- set_variable_value (a_name, a_value: STRING_8)
- -- Set value of variable `a_name' to `a_value'.
- -- Either local or global depending the case.
- require
- a_name_not_void: a_name /= Void
- a_name_not_empty: a_name.count > 0
- a_value_not_void: a_value /= Void
- local
- vars: GEANT_VARIABLES
- do
- if is_local_variable (a_name) then
- vars := target_locals_stack.item
- else
- vars := variables
- end
- vars.set_variable_value (a_name, a_value)
- end
- unset_variable (a_name: STRING_8)
- -- Unset variable `a_name'
- -- Either local or global depending the case.
- require
- a_name_not_void: a_name /= Void
- a_name_not_empty: a_name.count > 0
- local
- vars: GEANT_VARIABLES
- do
- if is_local_variable (a_name) then
- vars := target_locals_stack.item
- if vars.has (a_name) then
- vars.replace (create {STRING}.make_empty, a_name)
- end
- else
- variables.remove (a_name)
- end
- end
- is_local_variable (a_name: STRING): BOOLEAN
- -- Is variable `a_name' local ?
- require
- a_name_not_void: a_name /= Void
- a_name_not_empty: a_name.count > 0
- do
- if not attached current_target as l_current_target then
- Result := options.variable_local_by_default
- elseif l_current_target.formal_locals.has (a_name) then
- Result := True
- elseif l_current_target.formal_globals.has (a_name) then
- Result := False
- else
- Result := options.variable_local_by_default
- end
- end
- feature {GEANT_COMMAND} -- Access GEANT_COMMAND
- targets_stack: DS_STACK [GEANT_TARGET]
- -- Stack of targets
- current_target: detachable GEANT_TARGET
- -- Currently executing target;
- -- Set during processing `execute_target'
- do
- if not targets_stack.is_empty then
- Result := targets_stack.item
- end
- end
- invariant
- name_not_void: name /= Void
- name_not_empty: not name.is_empty
- no_void_target: attached targets as l_targets implies not l_targets.has_void
- output_file_not_void: output_file /= Void
- output_file_open_write: output_file.is_open_write
- variables_not_void: variables /= Void
- end