uh_parser/RaptorRecipe.pm
author Simon Howkins <simonh@symbian.org>
Wed, 14 Apr 2010 12:58:22 +0100
changeset 219 d57b367400c0
parent 190 890789575604
child 230 f593b7acdb37
permissions -rw-r--r--
Updated release notes generation: Added copyright message Proper command line parsing Usage message if inputs are not right Added explanatory preamble to output "NEW" FCLs are marked as such Merge changesets are included in output

# Copyright (c) 2009 Symbian Foundation Ltd
# This component and the accompanying materials are made available
# under the terms of the License "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:
# Symbian Foundation Ltd - initial contribution.
#
# Contributors:
#
# Description:
# Raptor parser module.
# Extract, analyzes and dumps raptor recipes i.e. content of <recipe> tags from a raptor log file

package RaptorRecipe;

use strict;
use RaptorCommon;

our $reset_status = {};
my $buildlog_status = {};
my $buildlog_recipe_status = {};
my $buildlog_recipe_status_status = {};

$reset_status->{name} = 'reset_status';
$reset_status->{next_status} = {buildlog=>$buildlog_status};

$buildlog_status->{name} = 'buildlog_status';
$buildlog_status->{next_status} = {recipe=>$buildlog_recipe_status};
$buildlog_status->{on_start} = 'RaptorRecipe::on_start_buildlog';
$buildlog_status->{on_end} = 'RaptorRecipe::on_end_buildlog';

$buildlog_recipe_status->{name} = 'buildlog_recipe_status';
$buildlog_recipe_status->{next_status} = {status=>$buildlog_recipe_status_status};
$buildlog_recipe_status->{on_start} = 'RaptorRecipe::on_start_buildlog_recipe';
$buildlog_recipe_status->{on_end} = 'RaptorRecipe::on_end_buildlog_recipe';
$buildlog_recipe_status->{on_chars} = 'RaptorRecipe::on_chars_buildlog_recipe';

$buildlog_recipe_status_status->{name} = 'buildlog_recipe_status_status';
$buildlog_recipe_status_status->{next_status} = {};
$buildlog_recipe_status_status->{on_start} = 'RaptorRecipe::on_start_buildlog_recipe_status';


my $filename = '';

my $recipe_info = {};

my $characters = '';

my $CATEGORY_RECIPEFAILURE = 'recipe_failure';
my $CATEGORY_RECIPEFAILURE_ARMCC_CANNOTOPENSOURCEINPUTFILE = 'armcc_cannot_open_source_input_file';
my $CATEGORY_RECIPEFAILURE_ARMLINK_COULDNOTOPENFILE = 'armlink_could_not_open_file';
my $CATEGORY_RECIPEFAILURE_ELF2E32_COULDNOTOPENFILE = 'elf2e32_could_not_open_file';
my $CATEGORY_RECIPEFAILURE_ARMAR_FILEDOESNOTEXIST = 'armar_file_does_not_exist';
my $CATEGORY_RECIPEFAILURE_ARMCC_CONTROLLINGEXPRESSIONISCONSTANT = 'armcc_controlling_expression_is_constant';
my $CATEGORY_RECIPEFAILURE_ARMCC_INTERNALFAULT = 'armcc_internal_fault';
my $CATEGORY_RECIPEFAILURE_ARMCC_MODIFIERNOTALLOWED = 'armcc_modifier_not_allowed';
my $CATEGORY_RECIPEFAILURE_ARMCC_GENERICWARNINGSERRORS = 'armcc_generic_warnings_errors';
my $CATEGORY_RECIPEFAILURE_ELF2E32_SYMBOLMISSINGFROMELFFILE = 'elf2e32_symbol_missing_from_elf_file';
my $CATEGORY_RECIPEFAILURE_MWCCSYM2_FILECANNOTBEOPENED = 'mwccsym2_file_cannot_be_opened';
my $CATEGORY_RECIPEFAILURE_BINSH_COMMANDNOTFOUND = 'binsh_command_not_found';
my $CATEGORY_RECIPEFAILURE_AS_ERROR = 'as_error';
my $CATEGORY_RECIPEFAILURE_GPP_ERROR = 'g++_error';
my $CATEGORY_RECIPEFAILURE_GPP_WARNING = 'g++_warning';

my $mmp_with_issues = {};


sub process
{
	my ($text, $config, $component, $mmp, $phase, $recipe, $file) = @_;
	
	my $dumped = 1;
	
	my $category = $CATEGORY_RECIPEFAILURE;
	my $severity = '';
	my $subcategory = '';
	
	# if mmp is defined assign severity=MAJOR for the first failure
	# then severity=MINOR to all other (for each logfile)
	if ($mmp and defined $mmp_with_issues->{$::current_log_file}->{$mmp})
	{
		$severity = $RaptorCommon::SEVERITY_MINOR;
	}
	elsif ($mmp)
	{
		$mmp_with_issues->{$::current_log_file} = {} if (!defined $mmp_with_issues->{$::current_log_file});
		$mmp_with_issues->{$::current_log_file}->{$mmp} = 1;
		$severity = $RaptorCommon::SEVERITY_MAJOR;
	}
	else
	{
		$severity = $RaptorCommon::SEVERITY_MAJOR;
	}
	
	
	if ($text =~ m,Error:  #5: cannot open source input file .*: No such file or directory,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ARMCC_CANNOTOPENSOURCEINPUTFILE;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,Fatal error: L6002U: Could not open file .*: No such file or directory,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ARMLINK_COULDNOTOPENFILE;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,elf2e32 : Error: E1001: Could not open file : .*.,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ELF2E32_COULDNOTOPENFILE;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,elf2e32 : Error: E1036: Symbol .* Missing from ELF File,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ELF2E32_SYMBOLMISSINGFROMELFFILE;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,Error: L6833E: File '.*' does not exist,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ARMAR_FILEDOESNOTEXIST;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,: Warning:  #236-D: controlling expression is constant,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ARMCC_CONTROLLINGEXPRESSIONISCONSTANT;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,/armcc.exe , and $text =~ m,Internal fault: ,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ARMCC_INTERNALFAULT;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,/armcc.exe , and $text =~ m,Error:  #655-D: the modifier ".*" is not allowed on this declaration,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ARMCC_MODIFIERNOTALLOWED;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,^\+.*/make.exe .*\n/bin/sh: .*: command not found,m)
	{
		$severity = $RaptorCommon::SEVERITY_CRITICAL;
		my $subcategory = $CATEGORY_RECIPEFAILURE_BINSH_COMMANDNOTFOUND;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,^\+.*/arm-none-symbianelf-as\.exe .*^Error: .*,ms)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_AS_ERROR;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,^\+.*/arm-none-symbianelf-g\+\+\.exe .*:\d+: [Ee]rror: .*,ms)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_GPP_ERROR;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,^\+.*/arm-none-symbianelf-g\+\+\.exe .*:\d+: [Ww]arning: .*,ms)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_GPP_WARNING;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	# the following captures generic armcc error/warnings, not captured by regexps above
	elsif ($text =~ m,/armcc.exe , and $text =~ m,: \d+ warnings\, \d+ errors$,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_ARMCC_GENERICWARNINGSERRORS;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	elsif ($text =~ m,mwccsym2.exe , and $text =~ m,: the file '.*' cannot be opened,)
	{
		my $subcategory = $CATEGORY_RECIPEFAILURE_MWCCSYM2_FILECANNOTBEOPENED;
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	else # log everything by default
	{
		RaptorCommon::dump_fault($category, $subcategory, $severity, $config, $component, $mmp, $phase, $recipe, $file);
	}
	
	return $dumped;
}

sub on_start_buildlog
{
	#print FILE "line,layer,component,name,armlicence,platform,phase,code,bldinf,mmp,target,source,\n";
	
	RaptorCommon::init();
}

sub on_start_buildlog_recipe
{
	my ($el) = @_;
	
	#print "on_start_buildlog_recipe\n";
	
	$recipe_info = {};
	
	my $attributes = $el->{Attributes};
	for (keys %{$attributes})
	{
		$recipe_info->{$attributes->{$_}->{'LocalName'}} = $attributes->{$_}->{'Value'};
		#print "$_ -> $attributes->{$_}->{'Value'}\n";
	}
}

sub on_chars_buildlog_recipe
{
	my ($ch) = @_;
	
	#print "on_chars_buildlog_recipe\n";
	
	$characters .= $ch->{Data};
	
	#print "characters is now -->$characters<--\n";
}

sub on_start_buildlog_recipe_status
{
	my ($el) = @_;
	
	my $attributes = $el->{Attributes};
	for (keys %{$attributes})
	{
		if ($attributes->{$_}->{'LocalName'} eq 'code')
		{
			$recipe_info->{$attributes->{$_}->{'LocalName'}} = $attributes->{$_}->{'Value'};
		}
		elsif ($attributes->{$_}->{'LocalName'} eq 'exit')
		{
			$recipe_info->{$attributes->{$_}->{'LocalName'}} = $attributes->{$_}->{'Value'};
		}
		elsif ($attributes->{$_}->{'LocalName'} eq 'attempt')
		{
			$recipe_info->{$attributes->{$_}->{'LocalName'}} = $attributes->{$_}->{'Value'};
		}
		elsif ($attributes->{$_}->{'LocalName'} eq 'forcesuccess')
		{
			$recipe_info->{$attributes->{$_}->{'LocalName'}} = $attributes->{$_}->{'Value'};
		}
	}
}

sub on_end_buildlog_recipe
{
	$::allbldinfs->{$recipe_info->{bldinf}} = 1;
	
	if ($recipe_info->{exit} =~ /failed/i || $recipe_info->{exit} =~ /retry/i && $recipe_info->{forcesuccess} =~ /FORCESUCCESS/i)
	{
		# normalize bldinf path
		$recipe_info->{bldinf} = lc($recipe_info->{bldinf});
		$recipe_info->{bldinf} =~ s,^[A-Za-z]:,,;
		$recipe_info->{bldinf} =~ s,[\\],/,g;
		
		my $package = '';
		if ($recipe_info->{bldinf} =~ m,/((os|mw|app|tools|ostools|adaptation)/[^/]*),)
		{
			$package = $1;
			$package =~ s,/,_,;
		}
		else
		{
			print "WARNING: can't understand bldinf attribute of recipe: $recipe_info->{bldinf}. Won't dump to failed recipes file.\n";
		}
		
		# also normalize mmp path if this exists
		if ($recipe_info->{mmp})
		{
			$recipe_info->{mmp} = lc($recipe_info->{mmp});
			$recipe_info->{mmp} =~ s,^[A-Za-z]:,,;
			$recipe_info->{mmp} =~ s,[\\],/,g;
		}
		
		$characters =~ s,^[\r\n]*,,;
		$characters =~ s,[\r\n]*$,,;
		
		if ($package)
		{
			$filename = "$::raptorbitsdir/$package.txt";
			if (!-f$filename)
			{
				print "Writing recipe file $filename\n";
				open(FILE, ">$filename");
				close(FILE);
			}
			
			my $dumped = process($characters, $recipe_info->{config}, $recipe_info->{bldinf}, $recipe_info->{mmp}, $recipe_info->{phase}, $recipe_info->{name}, "$package.txt");
			
			if ($dumped)
			{
				open(FILE, ">>$filename");
				print FILE "---failure_item_$::failure_item_number\---\n";
				print FILE "$characters\n\n";
				close(FILE);
			}
		}
	}

	$characters = '';
}

sub on_end_buildlog
{
}


1;