2 eval 'exec perl -S $0 ${1+"$@"}'
4 #*************************************************************************
6 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 # Copyright 2008 by Sun Microsystems, Inc.
10 # OpenOffice.org - a multi-platform office productivity suite
12 # $RCSfile: build.pl,v $
16 # This file is part of OpenOffice.org.
18 # OpenOffice.org is free software: you can redistribute it and/or modify
19 # it under the terms of the GNU Lesser General Public License version 3
20 # only, as published by the Free Software Foundation.
22 # OpenOffice.org is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU Lesser General Public License version 3 for more details
26 # (a copy is included in the LICENSE file that accompanied this code).
28 # You should have received a copy of the GNU Lesser General Public License
29 # version 3 along with OpenOffice.org. If not, see
30 # <http://www.openoffice.org/license.html>
31 # for a copy of the LGPLv3 License.
33 #*************************************************************************
35 # build - build entire project
41 use File
::Temp
qw(tmpnam);
46 use lib
("$ENV{SOLARENV}/bin/modules");
50 if (defined $ENV{COMMON_ENV_TOOLS
}) {
51 unshift(@INC, "$ENV{COMMON_ENV_TOOLS}/modules");
54 if (defined $ENV{CWS_WORK_STAMP
}) {
55 require GenInfoParser
; import GenInfoParser
;
56 require IO
::Handle
; import IO
::Handle
;
59 if (defined $ENV{verbose
} || defined $ENV{VERBOSE
}) {
60 $verbose_mode = ($ENV{verbose
} =~ /^t\S*$/i);
62 my $enable_multiprocessing = 1;
64 $cygwin++ if ($^O
eq 'cygwin');
65 if ($ENV{GUI
} eq 'WNT' && !$cygwin) {
66 eval { require Win32
::Process
; import Win32
::Process
; };
67 $enable_multiprocessing = 0 if ($@
);
70 ### for XML file format
71 eval { require XMLBuildListParser
; import XMLBuildListParser
; };
74 @modes_array = split('\s' , $ENV{BUILD_TYPE
});
78 ( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/;
80 $id_str = ' $Revision$ ';
81 $id_str =~ /Revision:\s+(\S+)\s+\$/
82 ?
($script_rev = $1) : ($script_rev = "-");
84 print "$script_name -- version: $script_rev\n";
86 #########################
90 #########################
95 if ( $^O
eq 'MSWin32' ) {
97 $remove_command = "rmdir /S /Q";
102 $remove_command = 'rm -rf';
103 $nul = '> /dev/null';
106 $QuantityToBuild = 0;
107 # delete $pid when not needed
108 %projects_deps_hash = (); # hash of projects with no dependencies,
109 # that could be built now
110 %broken_build = (); # hash of hashes of the modules,
111 # where build was broken (error occurred)
112 %folders_hashes = ();
113 %running_children = ();
114 $dependencies_hash = 0;
116 $BuildAllParents = 0;
120 $pre_custom_job = '';
122 $post_custom_job = '';
127 %AliveDependencies = ();
128 %global_deps_hash = (); # hash of dependencies of the all modules
129 %broken_modules_hashes = (); # hash of modules hashes, which cannot be built further
130 @broken_modules_names = (); # array of modules, which cannot be built further
137 $build_all_cont = '';
141 %processes_hash = ();
142 # %module_announced = ();
143 $prepare = ''; # prepare for following incompatible build
146 @ignored_errors = ();
148 $only_platform = ''; # the only platform to prepare
149 $only_common = ''; # the only common output tree to delete when preparing
151 $maximal_processes = 0; # the max number of the processes run
152 %modules_types = (); # modules types ('mod', 'img', 'lnk') hash
153 %platforms = (); # platforms available or being working with
154 %platforms_to_copy = (); # copy output trees for the platforms when --prepare
155 $tmp_dir = get_tmp_dir
(); # temp directory for checkout and other actions
156 # $dmake_batch = undef; #
157 @possible_build_lists = ('build.lst', 'build.xlist'); # build lists names
158 %build_list_paths = (); # build lists names
159 %build_lists_hash = (); # hash of arrays $build_lists_hash{$module} = \($path, $xml_list_object)
160 $pre_job = 'announce'; # job to add for not-single module build
161 $post_job = ''; # -"-
163 @warnings = (); # array of warnings to be shown at the end of the process
164 @errors = (); # array of errors to be shown at the end of the process
165 %html_info = (); # hash containing all necessary info for generating of html page
166 %module_by_hash = (); # hash containing all modules names as values and correspondent hashes as keys
167 %build_in_progress = (); # hash of modules currently being built
168 %build_is_finished = (); # hash of already built modules
169 %modules_with_errors = (); # hash of modules with build errors
170 %build_in_progress_shown = (); # hash of modules being built,
171 # and shown last time (to keep order)
173 $html_last_updated = 0;
176 $html_file = CorrectPath
($ENV{SOLARSRC
} . '/' . $ENV{INPATH
}. '.build.html');
178 %had_error = (); # hack for misteriuos windows problems - try run dmake 2 times if first time there was an error
179 $mkout = CorrectPath
("$ENV{SOLARENV}/bin/mkout.pl");
180 %weights_hash = (); # hash contains info about how many modules are dependent from one module
181 # %weight_stored = ();
183 $stop_build_on_error = 0; # for multiprocessing mode: do not build further module if there is an error
185 $setenv_string = ''; # string for configuration of the client environment
186 $ports_string = ''; # string with possible ports for server
188 $socket_obj = undef; # socket object for server
189 my %clients_jobs = ();
190 my %clients_times = ();
191 my $client_timeout = 0; # time for client to build (in sec)...
192 # The longest time period after that
193 # the server considered as an error/client crash
194 my %lost_client_jobs = (); # hash containing lost jobs
195 my %job_jobdir = (); # hash containing job-dir pairs
196 my %module_paths = (); # hash with absolute module paths
197 my %active_modules = ();
198 my $generate_config = 0;
199 my %add_to_config = ();
200 my %remove_from_config = ();
201 my $clear_config = 0;
206 $html_file = CorrectPath
($html_path . '/' . $ENV{INPATH
}. '.build.html') if (defined $html_path);
207 # my $temp_html_file = CorrectPath($tmp_dir. '/' . $ENV{INPATH}. '.build.html');
211 get_platforms
(\
%platforms);
214 $deliver_env{'BUILD_SOSL'}++;
215 $deliver_env{'COMMON_OUTDIR'}++;
216 $deliver_env{'GUI'}++;
217 $deliver_env{'INPATH'}++;
218 $deliver_env{'OFFENV_PATH'}++;
219 $deliver_env{'OUTPATH'}++;
220 $deliver_env{'L10N_framework'}++;
223 if ($generate_config) {
224 generate_config_file
();
227 $StandDir = get_stand_dir
(); # This also sets $CurrentPrj
228 get_module_and_buildlist_paths
();
229 provide_consistency
() if (defined $ENV{CWS_WORK_STAMP
} && defined($ENV{COMMON_ENV_TOOLS
}));
231 $deliver_command = $ENV{DELIVER
};
232 $deliver_command .= ' '. $dlv_switch if ($dlv_switch);
235 $check_error_string = '';
245 if (open (CMD_FILE
, ">>$cmd_file")) {
248 if ($ENV{GUI
} ne 'UNX') {
249 $new_line = "echo.\n";
250 print "\@$echo off\npushd\n";
252 $new_line = $echo."\"\"\n";
255 print_error
("Cannot open file $cmd_file");
264 GetParentDeps
( $CurrentPrj, \
%global_deps_hash );
268 if (scalar keys %broken_build) {
270 # } elsif (!$custom_job && $post_custom_job) {
271 # do_post_custom_job(CorrectPath($StandDir.$CurrentPrj));
274 if (scalar keys %active_modules) {
275 foreach (keys %dead_parents) {
276 delete $dead_parents{$_} if (!defined $active_modules{$_});
279 if (scalar keys %dead_parents) {
281 print $new_line.$new_line;
282 print $echo."WARNING! Project(s):\n";
283 foreach $DeadPrj (keys %dead_parents) {
284 print $echo."$DeadPrj\n";
287 print $echo."not found and couldn't be built. Dependencies on that module(s) ignored. Maybe you should correct build lists.\n";
289 do_exit
(1) if ($checkparents);
291 if (($ENV{GUI
} ne 'UNX') && $cmd_file) {
297 print STDOUT
"Script $cmd_file generated\n";
299 if ($ignore && scalar @ignored_errors) {
300 print STDERR
"\nERROR: next directories could not be built:\n";
301 foreach (@ignored_errors) {
302 print STDERR
"\t$_\n";
304 print STDERR
"\nERROR: please check these directories and build the corresponding module(s) anew!!\n\n";
310 #########################
314 #########################
317 if (scalar @warnings) {
318 print STDERR
"\nWARNING(S):\n";
319 print STDERR
$_ foreach (@warnings);
324 my ($old_file_name, $new_file_name, $throw_error) = @_;
326 if(-e
$old_file_name) {
327 rename($old_file_name, $new_file_name) or system("mv", $old_file_name, $new_file_name);
328 if (-e
$old_file_name) {
329 system("rm -rf $old_file_name") if (!unlink $old_file_name);
331 } elsif ($throw_error) {
332 print_error
("No such file $old_file_name");
336 sub generate_config_file
{
337 my $source_config = SourceConfig
-> new
();
338 my $source_config_file = $source_config->get_config_file_path();
339 my $temp_config_file = File
::Temp
::tmpnam
($ENV{TMP
});
340 my @config_content_new = ();
341 my $addition_message;
343 my %present_modules = ();
344 if ($source_config_file) {
345 open(SOURCE_CONFIG_FILE
, $source_config_file);
346 my @config_content = <SOURCE_CONFIG_FILE
>;
347 close SOURCE_CONFIG_FILE
;
348 my ($module_section, $repository_section);
349 foreach (@config_content) {
351 if ((!/^\S+/)||(/^\s*#+/)) {
352 push(@config_content_new, $_);
355 if (/^\[repositories\]\s*(\s+#)*/) {
356 if ($module_section) {
357 $addition_message = add_modules_to_source_config
(\
%add_to_config, \
@config_content_new);
360 $repository_section = 1;
361 push(@config_content_new, $_);
364 if (/^\[modules\]\s*(\s+#)*/) {
366 $repository_section = 0;
367 push(@config_content_new, $_);
370 if ($module_section && /\s*(\S+)=active\s*(\s+#)*/) {
371 if ($clear_config || defined $remove_from_config{$1}) {
372 delete $remove_from_config{$1};
373 $removal_message .= "$1 ";
375 push(@config_content_new, $_);
376 if (defined $add_to_config{$1}) {
377 push(@warnings, "Module $1 already activated in $source_config_file\n");
378 delete $add_to_config{$1};
382 push(@config_content_new, $_);
385 if (keys %add_to_config) {
386 if (!$module_section) {
387 push(@config_content_new, "[modules]\n");
389 $addition_message = add_modules_to_source_config
(\
%add_to_config, \
@config_content_new);
392 if ($clear_config || scalar %remove_from_config) {
393 print_error
('No source config file found');
395 $source_config_file = $source_config->get_config_file_default_path();
396 push(@config_content_new, "[modules]\n");
397 $addition_message = add_modules_to_source_config
(\
%add_to_config, \
@config_content_new);
399 die("Cannot open $temp_config_file") if (!open(NEW_CONFIG
, ">$temp_config_file"));
400 print NEW_CONFIG
$_ foreach (@config_content_new);
402 rename_file
($temp_config_file, $source_config_file, 1);
403 foreach (keys %remove_from_config) {
404 push(@warnings, "Module(s) $_ not found in " . $source_config_file . "\n");
407 print $addition_message if ($addition_message);
408 print "Module(s) $removal_message removed from $source_config_file\n" if ($removal_message);
413 # Add modules from the passed hash to the array of config strigns
415 sub add_modules_to_source_config
{
416 my ($modules_hash_ref, $config_content_new) = @_;
418 foreach (keys %$modules_hash_ref) {
419 push(@
$config_content_new, "$_=active\n");
423 return 'Module(s) ' .$message . 'are added to the ' . $source_config_file . "\n\n";
430 # procedure retrieves build list path
431 # (all possibilities are taken into account)
433 sub get_build_list_path
{
435 my @possible_dirs = ($module, $module. '.lnk', $module. '.link');
436 return $build_list_paths{$module} if (defined $build_list_paths{$module});
437 foreach (@possible_dirs) {
438 my $possible_dir_path = $module_paths{$_}.'/prj/';
439 if (-d
$possible_dir_path) {
440 foreach my $build_list (@possible_build_lists) {
441 my $possible_build_list_path = CorrectPath
($possible_dir_path . $build_list);
442 if (-f
$possible_build_list_path) {
443 $build_list_paths{$module} = $possible_build_list_path;
444 return $possible_build_list_path;
447 print_error
("There's no build list for $module");
450 $dead_parents{$module}++;
451 $build_list_paths{$module} = CorrectPath
(retrieve_build_list
($module)) if (!defined $build_list_paths{$module});
452 return $build_list_paths{$module};
456 # Get dependencies hash of the current and all parent projects
459 my (%parents_deps_hash, $module, $parent);
461 my $deps_hash = shift;
462 my @UnresolvedParents = get_parents_array
($prj_dir);
463 $parents_deps_hash{$_}++ foreach (@UnresolvedParents);
464 $$deps_hash{$prj_dir} = \
%parents_deps_hash;
465 while ($module = pop(@UnresolvedParents)) {
466 my %parents_deps_hash = ();
467 $parents_deps_hash{$_}++ foreach (get_parents_array
($module));
468 $$deps_hash{$module} = \
%parents_deps_hash;
469 foreach $Parent (keys %parents_deps_hash) {
470 if (!defined($$deps_hash{$Parent})) {
471 push (@UnresolvedParents, $Parent);
475 check_deps_hash
($deps_hash);
479 my $deps_hash = shift;
480 foreach (keys %$deps_hash) {
481 foreach my $module_deps_hash ($$deps_hash{$_}) {
482 foreach my $dependency (keys %$module_deps_hash) {
483 $weights_hash{$dependency}++;
490 # Build everything that should be built
493 if ($BuildAllParents) {
494 my ($Prj, $PrjDir, $orig_prj);
495 GetParentDeps
( $CurrentPrj, \
%global_deps_hash);
496 if (scalar keys %active_modules) {
497 $active_modules{$CurrentPrj}++;
498 $modules_types{$CurrentPrj} = 'mod';
500 modules_classify
(keys %global_deps_hash);
501 store_weights
(\
%global_deps_hash);
502 if (keys %active_modules && ($build_from || $incompatible)) {
503 print_error
("There are active module in $source_config_file. Please remove these modules to proceed.\n");
505 prepare_build_from
(\
%global_deps_hash) if ($build_from);
506 prepare_incompatible_build
(\
%global_deps_hash) if ($incompatible);
507 if ($build_all_cont || $build_since) {
508 print STDERR
"There are active module in $source_config_file. Inactive modules will be skipped.\n";
509 push (@warnings, "\nThere are active module in $source_config_file. Inactive modules are skipped.\n\n");
510 prepare_build_all_cont
(\
%global_deps_hash);
512 $modules_number = scalar keys %global_deps_hash;
513 initialize_html_info
($_) foreach (keys %global_deps_hash);
514 if ($QuantityToBuild) {
515 build_multiprocessing
();
521 while ($Prj = PickPrjToBuild
(\
%global_deps_hash)) {
522 if (!defined $dead_parents{$Prj}) {
523 if (scalar keys %broken_build) {
524 print $echo . "Skipping project $Prj because of error(s)\n";
525 RemoveFromDependencies
($Prj, \
%global_deps_hash);
526 $build_is_finished{$Prj}++;
530 $PrjDir = $module_paths{$Prj};
531 get_deps_hash
($Prj, \
%LocalDepsHash);
532 my $info_hash = $html_info{$Prj};
533 $$info_hash{DIRS
} = check_deps_hash
(\
%LocalDepsHash, $Prj);
534 $module_by_hash{\
%LocalDepsHash} = $Prj;
535 BuildDependent
(\
%LocalDepsHash);
536 print $check_error_string;
539 RemoveFromDependencies
($Prj, \
%global_deps_hash);
540 $build_is_finished{$Prj}++;
544 store_build_list_content
($CurrentPrj);
545 get_deps_hash
($CurrentPrj, \
%LocalDepsHash);
546 initialize_html_info
($CurrentPrj);
547 my $info_hash = $html_info{$CurrentPrj};
548 $$info_hash{DIRS
} = check_deps_hash
(\
%LocalDepsHash, $CurrentPrj);
549 $module_by_hash{\
%LocalDepsHash} = $CurrentPrj;
553 BuildDependent
(\
%LocalDepsHash);
558 sub initialize_html_info
{
560 return if (defined $dead_parents{$module});
561 $html_info{$module} = { 'DIRS' => [],
571 my ($new_BuildDir, $OldBuildDir, $error_code);
572 my $BuildDir = shift;
573 $jobs_hash{$BuildDir}->{START_TIME
} = time();
574 $jobs_hash{$BuildDir}->{STATUS
} = 'building';
575 if ($BuildDir =~ /(\s)/o) {
576 $error_code = do_custom_job
($BuildDir, \
%LocalDepsHash);
578 html_store_job_info
(\
%LocalDepsHash, $BuildDir);
579 print_error
("$BuildDir not found!!\n") if (!-d
$BuildDir);
581 $new_BuildDir = $BuildDir;
582 $new_BuildDir =~ s/_simple//g;
583 if ((-d
$new_BuildDir)) {
584 print("\nTrying $new_BuildDir, $BuildDir not found!!\n");
585 $BuildDir = $new_BuildDir;
587 print_error
("\n$BuildDir not found!!\n");
591 print "cd $BuildDir\n";
592 print $check_error_string;
593 print $echo.$BuildDir."\n";
595 print $check_error_string;
597 print "\nEntering $BuildDir\n";
599 RemoveFromDependencies
($BuildDir, \
%LocalDepsHash) if (!$child);
600 return if ($cmd_file || $show);
601 $error_code = run_job
($dmake, $BuildDir);
602 html_store_job_info
(\
%LocalDepsHash, $BuildDir, $error_code) if (!$child);
604 if ($error_code && $ignore) {
605 push(@ignored_errors, $BuildDir);
609 my $oldfh = select STDERR
;
614 _exit
($error_code >> 8);
616 _exit
($?
>> 8) if ($?
&& ($?
!= -1));
619 } elsif ($error_code && ($error_code != -1)) {
620 print_error
("Error $? occurred while making $BuildDir");
625 # Procedure stores information about build list (and)
626 # build list object in build_lists_hash
628 sub store_build_list_content
{
630 my $build_list_path = get_build_list_path
($module);
631 return undef if (!defined $build_list_path);
632 return if (!$build_list_path);
633 my $xml_list = undef;
634 if ($build_list_path =~ /\.xlist$/o) {
635 print_error
("XMLBuildListParser.pm couldn\'t be found, so XML format for build lists is not enabled") if (!defined $enable_xml);
636 $xml_list = XMLBuildListParser
->new();
637 if (!$xml_list->loadXMLFile($build_list_path)) {
638 print_error
("Cannot use $build_list_path");
640 $build_lists_hash{$module} = $xml_list;
642 if (open (BUILD_LST
, $build_list_path)) {
643 my @build_lst = <BUILD_LST
>;
644 $build_lists_hash{$module} = \
@build_lst;
648 $dead_parents{$module}++;
652 # Get string (list) of parent projects to build
654 sub get_parents_array
{
656 store_build_list_content
($module);
657 my $build_list_ref = $build_lists_hash{$module};
659 if (ref($build_list_ref) eq 'XMLBuildListParser') {
660 return $build_list_ref->getModuleDependencies(\
@modes_array);
662 foreach (@
$build_list_ref) {
671 if ($_ =~ /\:+\s+/) {
672 return pick_for_build_type
($');
679 # get folders' platform infos
681 sub get_prj_platform
{
682 my $build_list_ref = shift;
683 my ($prj_alias, $line);
684 foreach(@
$build_list_ref) {
687 if ($_ =~ /\snmake\s/) {
688 if ($' =~ /\s*-\s+(\w+)[,\S+]*\s+(\S+)/ ) {
691 print_error ("There is no correct alias set in the line $line!") if ($alias eq 'NULL
');
692 mark_platform($alias, $platform);
694 print_error("Misspelling in line: \n$_");
698 #seek(BUILD_LST, 0, 0);
702 # Procedure populate the dependencies hash with
703 # information from XML build list object
705 sub get_deps_from_object {
706 my ($module, $build_list_object, $dependencies_hash) = @_;
708 foreach my $dir ($build_list_object->getJobDirectories("make", $ENV{GUI})) {
709 $PathHash{$dir} = $module_paths{$module};
710 $PathHash{$dir} .= $dir if ($dir ne '/');
713 foreach my $dep ($build_list_object->getJobDependencies($dir, "make", $ENV{GUI})) {
716 $$dependencies_hash{$dir} = \%deps_hash;
722 # Getting hashes of all internal dependencies and additional
723 # information for given project
726 my ($dummy, $module_to_build);
727 %DeadDependencies = ();
728 $module_to_build = shift;
729 my $dependencies_hash = shift;
731 if ($modules_types{$module_to_build} ne 'lnk
') {
732 add_prerequisite_job($dependencies_hash, $module_to_build, $pre_custom_job);
733 add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job);
734 add_dependent_job($dependencies_hash, $module_to_build, $custom_job);
735 add_dependent_job($dependencies_hash, $module_to_build, $post_job);
736 add_dependent_job($dependencies_hash, $module_to_build, $post_custom_job);
740 if ( defined $modules_types{$module_to_build} && $modules_types{$module_to_build} ne 'mod
') {
741 add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job);
745 my $build_list_ref = $build_lists_hash{$module_to_build};
746 delete $build_lists_hash{$module_to_build};
747 if (ref($build_list_ref) eq 'XMLBuildListParser
') {
748 get_deps_from_object($module_to_build, $build_list_ref, $dependencies_hash);
750 get_prj_platform($build_list_ref);
751 foreach (@$build_list_ref) {
757 if ($_ =~ /\s+nmake\s+/o) {
758 my ($Platform, $Dependencies, $Dir, $DirAlias);
762 $dummy =~ /(\S+)\s+(\S*)/o;
764 $Dependencies =~ /(\w+)/o;
767 while ($Dependencies =~ /,(\w+)/o) {
770 $Dependencies =~ /\s+(\S+)\s+/o;
772 if (!CheckPlatform($Platform)) {
773 next if (defined $PlatformHash{$DirAlias});
774 $DeadDependencies{$DirAlias}++;
777 delete $DeadDependencies{$DirAlias} if (defined $DeadDependencies{$DirAlias});
778 print_error("Directory alias $DirAlias is defined at least twice!! Please, correct build.lst in module $module_to_build") if (defined $$dependencies_hash{$DirAlias});
779 $PlatformHash{$DirAlias}++;
781 print_error("$module_to_build/prj/build.lst has wrongly written dependencies string:\n$_\n") if (!$Dependencies);
782 $deps_hash{$_}++ foreach (GetDependenciesArray($Dependencies));
783 $$dependencies_hash{$DirAlias} = \%deps_hash;
784 $BuildQueue{$DirAlias}++;
786 if ($Dir =~ /(\\|\/)/o) {
789 $PathHash{$DirAlias} = CorrectPath($module_paths{$module_to_build} . "/$local_dir");
790 } elsif ($_ !~ /^\s*$/ && $_ !~ /^\w*\s/o) {
795 if (scalar @errors) {
796 my $message = "$module_to_build/prj/build.lst has wrongly written string(s):\n";
797 $message .= "$_\n" foreach(@errors);
798 if ($QuantityToBuild) {
799 $broken_build{$module_to_build} = $message;
800 $dependencies_hash = undef;
803 print_error($message);
806 foreach my $alias (keys %DeadDependencies) {
807 next if defined $AliveDependencies{$alias};
808 if (!IsHashNative($alias)) {
809 RemoveFromDependencies($alias, $dependencies_hash);
810 delete $DeadDependencies{$alias};
814 # check_deps_hash($dependencies_hash);
815 resolve_aliases($dependencies_hash, \%PathHash);
817 add_prerequisite_job($dependencies_hash, $module_to_build, $pre_custom_job);
818 add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job);
819 add_dependent_job($dependencies_hash, $module_to_build, $custom_job);
820 add_dependent_job($dependencies_hash, $module_to_build, $post_job) if ($module_to_build ne $CurrentPrj);
821 add_dependent_job($dependencies_hash, $module_to_build, $post_custom_job);
823 store_weights($dependencies_hash);
827 # procedure adds which is independent from anothers, but anothers are dependent from it
829 sub add_prerequisite_job {
830 my ($dependencies_hash, $module, $job) = @_;
832 $job = "$module $job";
833 foreach (keys %$dependencies_hash) {
834 $deps_hash = $$dependencies_hash{$_};
837 $$dependencies_hash{$job} = {};
841 # procedure adds a job wich is dependent from all already registered jobs
843 sub add_dependent_job {
844 # $post_job is dependent from all jobs
845 my ($dependencies_hash, $module, $job) = @_;
848 $deps_hash{$_}++ foreach (keys %$dependencies_hash);
849 $$dependencies_hash{"$module $job"} = \%deps_hash;
853 # this procedure converts aliases to absolute paths
855 sub resolve_aliases {
856 my ($dependencies_hash, $PathHash) = @_;
857 foreach my $dir_alias (keys %$dependencies_hash) {
858 my $aliases_hash_ref = $$dependencies_hash{$dir_alias};
860 foreach (keys %$aliases_hash_ref) {
861 $paths_hash{$$PathHash{$_}}++;
863 delete $$dependencies_hash{$dir_alias};
864 $$dependencies_hash{$$PathHash{$dir_alias}} = \%paths_hash;
869 # mark platform in order to prove if alias has been used according to specs
872 my $prj_alias = shift;
873 if (exists $prj_platform{$prj_alias}) {
874 $prj_platform{$prj_alias} = 'all';
876 $prj_platform{$prj_alias} = shift;
881 # Convert path from abstract (with '\' and/or '/' delimiters)
882 # to system-independent
886 if ( ($^O eq 'MSWin32') && (!defined $ENV{SHELL})) {
896 #print "Checking dmake...";
897 if (open(DMAKEVERSION, "dmake -V |")) {
898 # if (open(DMAKEVERSION, "dmake -V |")) {
899 my @dmake_version = <DMAKEVERSION>;
901 # if ($dmake_version[0] =~ /^dmake\s\-\sCopyright\s\(c\)/) {
902 # print " Using version $1\n" if ($dmake_version[0] =~ /Version\s(\d+\.*\d*)/);
906 my $error_message = 'dmake: Command not found.';
907 $error_message .= ' Please rerun bootstrap' if (!defined $ENV{COMMON_ENV_TOOLS});
908 print_error($error_message);
912 # Get platform-dependent commands
916 # Setting alias for dmake
921 if ($ENV{GUI} eq 'UNX') {
922 $check_error_string = "if \"\$?\" != \"0\" exit\n";
924 $check_error_string = "if \"\%?\" != \"0\" quit\n";
928 $dmake_args = join(' ', 'dmake', @dmake_args);
930 while ($arg = pop(@dmake_args)) {
936 # Procedure retrieves list of projects to be built from build.lst
939 if (!defined $ENV{GUI}) {
941 die "No environment set\n";
944 if ( defined $ENV{PWD} ) {
945 $StandDir = $ENV{PWD};
946 } elsif (defined $ENV{_cwd}) {
947 $StandDir = $ENV{_cwd};
951 my $previous_dir = '';
953 foreach (@possible_build_lists) {# ('build.lst', 'build.xlist');
954 if (-e $StandDir . '/prj/'.$_) {
955 $CurrentPrj = File::Basename::basename($StandDir);
956 $StandDir = File::Basename::dirname($StandDir);
958 } elsif ($StandDir eq $previous_dir) {
960 print_error('Found no project to build');
963 $previous_dir = $StandDir;
964 $StandDir = File::Basename::dirname(Cwd::realpath($StandDir));
965 print_error('Found no project to build') if (!$StandDir);
967 # while (chdir '..');
968 while (chdir "$StandDir");
972 # Picks project which can be built now from hash and then deletes it from hash
975 my $DepsHash = shift;
976 handle_dead_children(0) if ($QuantityToBuild);
977 my $Prj = FindIndepPrj($DepsHash);
978 delete $$DepsHash{$Prj};
979 generate_html_file();
984 # Make a decision if the project should be built on this platform
987 my $Platform = shift;
988 return 1 if ($Platform eq 'all');
989 return 1 if (($ENV{GUI} eq 'WIN') && ($Platform eq 'w'));
990 return 1 if (($ENV{GUI} eq 'UNX') && ($Platform eq 'u'));
991 return 1 if (($ENV{GUI} eq 'OS2') && ($Platform eq 'p'));
992 return 1 if (($ENV{GUI} eq 'WNT') &&
993 (($Platform eq 'w') || ($Platform eq 'n')));
998 # Remove project to build ahead from dependencies and make an array
999 # of all from given project dependent projects
1001 sub RemoveFromDependencies {
1002 my ($ExclPrj, $i, $Prj, $Dependencies);
1004 my $ExclPrj_orig = '';
1005 $ExclPrj_orig = $` if (($ExclPrj =~ /\.lnk$/o) || ($ExclPrj =~ /\.link$/o));
1006 $Dependencies = shift;
1007 foreach $Prj (keys %$Dependencies) {
1008 my $prj_deps_hash = $$Dependencies{$Prj};
1009 delete $$prj_deps_hash{$ExclPrj} if (defined $$prj_deps_hash{$ExclPrj});
1015 # Check the hash for consistency
1017 sub check_deps_hash
{
1018 my ($deps_hash_ref, $module) = @_;
1020 my $module_path = $module_paths{$module} if (defined $module);
1021 return if (!scalar keys %$deps_hash_ref);
1022 my %deps_hash = %$deps_hash_ref;
1024 foreach $key (keys %$deps_hash_ref) {
1025 my %values_hash = %{$$deps_hash_ref{$key}};
1026 $deps_hash{$key} = \
%values_hash;
1030 my $build_number = 0;
1034 foreach $key (sort keys %deps_hash) {
1035 $local_deps_ref = $deps_hash{$key};
1036 if (!scalar keys %$local_deps_ref) {
1037 if (defined $module) {
1040 if ($key =~ /(\s)/o) {
1043 if (length($key) == length($module_path)) {
1046 $string = substr($key, length($module_path) + 1);
1047 $string =~ s/\\/\//go
;
1050 $log_name = $string;
1051 if ($log_name eq "$module $custom_job") {
1052 $log_name = "custom_job";
1054 if ($log_name eq "$module $pre_custom_job") {
1055 $log_name = "pre_custom_job";
1057 if ($log_name eq "$module $post_custom_job") {
1058 $log_name = "post_custom_job";
1060 $log_name =~ s/\\|\//\
./g
;
1061 $log_name =~ s/\s/_/g;
1062 $log_name = $module if ($log_name =~ /^\.+$/);
1063 $log_name .= '.txt';
1064 push(@possible_order, $key);
1065 $jobs_hash{$key} = { SHORT_NAME
=> $string,
1066 BUILD_NUMBER
=> $build_number,
1067 STATUS
=> 'waiting',
1068 LOG_PATH
=> $module . "/$ENV{INPATH}/misc/logs/$log_name",
1069 LONG_LOG_PATH
=> CorrectPath
($module_paths{$module} . "/$ENV{INPATH}/misc/logs/$log_name"),
1075 RemoveFromDependencies
($key, \
%deps_hash);
1076 delete $deps_hash{$key};
1080 } while ($consistent && (scalar keys %deps_hash));
1081 return \
@possible_order if ($consistent);
1082 print STDERR
"Fatal error:";
1083 foreach (keys %deps_hash) {
1084 print STDERR
"\n\t$_ depends on: ";
1085 foreach my $i (keys %{$deps_hash{$_}}) {
1086 print STDERR
(' ', $i);
1090 my $oldfh = select STDERR
;
1094 print_error
("There are dead or circular dependencies\n");
1099 # Find project with no dependencies left.
1102 my ($Prj, @Prjs, $Dependencies, $i);
1103 my @candidates = ();
1104 my $children = children_number
();
1105 return '' if (!$server_mode && $children && ($children >= $QuantityToBuild));
1106 $Dependencies = shift;
1107 @Prjs = keys %$Dependencies;
1109 foreach $Prj (@Prjs) {
1110 next if (&IsHashNative
($Prj));
1111 my $PrjDeps = $$Dependencies{$Prj};
1112 push(@candidates, $Prj) if (!scalar keys %$PrjDeps);
1114 if (scalar @candidates) {
1115 my $best_candidate = undef;
1117 foreach my $candidate (sort @candidates) {
1118 if (defined $weights_hash{$candidate} && $weights_hash{$candidate} > $weight) {
1119 $best_candidate = $candidate;
1120 $weight = $weights_hash{$candidate};
1123 if (defined $best_candidate) {
1124 return $best_candidate;
1126 my @sorted_candidates = sort(@candidates);
1127 return $sorted_candidates[0];
1137 # Check if given entry is HASH-native, that is not a user-defined data
1141 return 1 if ($Prj =~ /^HASH\(0x[\d | a | b | c | d | e | f]{6,}\)/);
1146 # Getting array of dependencies from the string given
1148 sub GetDependenciesArray
{
1149 my ($DepString, @Dependencies, $ParentPrj, $prj, $string);
1152 $string = $DepString;
1154 while ($DepString !~ /^NULL/o) {
1155 print_error
("Project $prj has wrongly written dependencies string:\n $string") if (!$DepString);
1156 $DepString =~ /(\S+)\s*/o;
1159 if ($ParentPrj =~ /\.(\w+)$/o) {
1161 if (($prj_platform{$ParentPrj} ne $1) &&
1162 ($prj_platform{$ParentPrj} ne 'all
')) {
1163 print_error ("$ParentPrj\.$1 is a wrongly dependency identifier!\nCheck if it is platform dependent");
1165 $AliveDependencies{$ParentPrj}++ if (CheckPlatform($1));
1166 push(@Dependencies, $ParentPrj);
1168 if ((exists($prj_platform{$ParentPrj})) &&
1169 ($prj_platform{$ParentPrj} ne 'all
') ) {
1170 print_error("$ParentPrj is a wrongly used dependency identifier!\nCheck if it is platform dependent");
1172 push(@Dependencies, $ParentPrj);
1175 return @Dependencies;
1180 # Getting current directory list
1182 sub GetDirectoryList {
1185 opendir(CurrentDirList, $Path);
1186 @DirectoryList = readdir(CurrentDirList);
1187 closedir(CurrentDirList);
1188 return @DirectoryList;
1192 my $message = shift;
1194 $modules_number -= scalar keys %global_deps_hash;
1195 $modules_number -= 1;
1196 print STDERR "\nERROR: $message\n";
1204 close CMD_FILE if ($cmd_file);
1208 do_exit(1) if (defined $force);
1212 print STDERR "\nbuild\n";
1213 print STDERR "Syntax: build [--all|-a[:prj_name]]|[--from|-f prj_name1[:prj_name2] [prj_name3 [...]]]|[--since|-c prj_name] [--with_branches|-b]|[--prepare|-p][:platform] [--dontchekoutmissingmodules]] [--deliver|-d [--dlv_switch deliver_switch]]] [-P processes|--server [--setenvstring \"string\"] [--client_timeout MIN] [--port port1[:port2:...:portN]]] [--show|-s] [--help|-h] [--file|-F] [--ignore|-i] [--version|-V] [--mode|-m OOo[,SO[,EXT]] [--html [--html_path html_file_path] [--dontgraboutput]] [--pre_job=pre_job_sring] [--job=job_string|-j] [--post_job=post_job_sring] [--stoponerror] [--genconf [--removeall|--clear|--remove|--add module1,module2[,...,moduleN]]]\n";
1214 print STDERR "Example1: build --from sfx2\n";
1215 print STDERR " - build all projects dependent from sfx2, starting with sfx2, finishing with the current module\n";
1216 print STDERR "Example2: build --all:sfx2\n";
1217 print STDERR " - the same as --all, but skip all projects that have been already built when using \"--all\" switch before sfx2\n";
1218 print STDERR "Example3: build --all --server\n";
1219 print STDERR " - build all projects in server mode, use first available port from default range 7890-7894 (running clients required!!)\n";
1220 print STDERR "Example4(for unixes):\n";
1221 print STDERR " build --all --pre_job=echo\\ Starting\\ job\\ in\\ \\\$PWD --job=some_script.sh --post_job=echo\\ Job\\ in\\ \\\$PWD\\ is\\ made\n";
1222 print STDERR " - go through all projects, echo \"Starting job in \$PWD\" in each module, execute script some_script.sh, and finally echo \"Job in \$PWD is made\"\n";
1223 print STDERR "\nSwitches:\n";
1224 print STDERR " --all - build all projects from very beginning till current one\n";
1225 print STDERR " --from - build all projects dependent from the specified (including it) till current one\n";
1226 print STDERR " --mode OOo - build only projects needed for OpenOffice.org\n";
1227 print STDERR " --prepare - clear all projects for incompatible build from prj_name till current one [for platform] (cws version)\n";
1228 print STDERR " --with_branches- build all projects in neighbour branches and current branch starting from actual project\n";
1229 print STDERR " --since - build all projects beginning from the specified till current one (the same as \"--all:prj_name\", but skipping prj_name)\n";
1230 print STDERR " --checkmodules - check if all required parent projects are availlable\n";
1231 print STDERR " --show - show what is going to be built\n";
1232 print STDERR " --file - generate command file file_name\n";
1233 print STDERR " --deliver - only deliver, no build (usable for \'-all\' and \'-from\' keys)\n";
1234 print STDERR " -P - start multiprocessing build, with number of processes passed\n";
1235 print STDERR " --server - start build in server mode (clients required)\n";
1236 print STDERR " --setenvstring - string for configuration of the client environment\n";
1237 print STDERR " --port - set server port, default is 7890. You may pass several ports, the server will be started on the first available\n";
1238 print STDERR " otherwise the server will be started on first available port from the default range 7890-7894\n";
1239 print STDERR " --client_timeout - time frame after which the client/job is considered to be lost. Default is 120 min\n";
1240 print STDERR " --dlv_switch - use deliver with the switch specified\n";
1241 print STDERR " --help - print help info\n";
1242 print STDERR " --ignore - force tool to ignore errors\n";
1243 print STDERR " --html - generate html page with build status\n";
1244 print STDERR " file named $ENV{INPATH}.build.html will be generated in $ENV{SOLARSRC}\n";
1245 print STDERR " --html_path - set html page path\n";
1246 print STDERR " --dontgraboutput - do not grab console output when generating html page\n";
1247 print STDERR " --genconf - generate/modify workspace configuration file\n";
1248 print STDERR " --add - add active module(s) to configuration file\n";
1249 print STDERR " --remove - removeactive modules(s) from configuration file\n";
1250 print STDERR " --removeall|--clear - remove all active modules(s) from configuration file\n";
1252 print STDERR " --stoponerror - stop build when error occurs (for mp builds)\n";
1253 print STDERR " --dontchekoutmissingmodules - do not chekout missing modules when running prepare (links still will be broken)\n";
1254 print STDERR " Custom jobs:\n";
1255 print STDERR " --job=job_string - execute custom job in (each) module. job_string is a shell script/command to be executed instead of regular dmake jobs\n";
1256 print STDERR " --pre_job=pre_job_string - execute preliminary job in (each) module. pre_job_string is a shell script/command to be executed before regular job in the module\n";
1257 print STDERR " --post_job=job_string - execute a postprocess job in (each) module. post_job_string is a shell script/command to be executed after regular job in the module\n";
1258 print STDERR "Default: - build current project\n";
1259 print STDERR "Unknown switches passed to dmake\n";
1263 # Get all options passed
1266 my ($arg, $dont_grab_output);
1267 while ($arg = shift @ARGV) {
1268 $arg =~ /^-P$/ and $QuantityToBuild = shift @ARGV and next;
1269 $arg =~ /^-P(\d+)$/ and $QuantityToBuild = $1 and next;
1270 $arg =~ /^--all$/ and $BuildAllParents = 1 and next;
1271 $arg =~ /^-a$/ and $BuildAllParents = 1 and next;
1272 $arg =~ /^--show$/ and $show = 1 and next;
1273 $arg =~ /^--checkmodules$/ and $checkparents = 1 and $ignore = 1 and next;
1274 $arg =~ /^-s$/ and $show = 1 and next;
1275 $arg =~ /^--deliver$/ and $deliver = 1 and next;
1276 $arg =~ /^(--job=)/ and $custom_job = $' and next;
1277 $arg =~ /^(--pre_job=)/ and $pre_custom_job = $' and next;
1278 $arg =~ /^(--post_job=)/ and $post_custom_job = $' and next;
1279 $arg =~ /^-d$/ and $deliver = 1 and next;
1280 $arg =~ /^--dlv_switch$/ and $dlv_switch = shift @ARGV and next;
1281 $arg =~ /^--file$/ and $cmd_file = shift @ARGV and next;
1282 $arg =~ /^-F$/ and $cmd_file = shift @ARGV and next;
1284 $arg =~ /^--with_branches$/ and $BuildAllParents = 1
1285 and $build_from = shift @ARGV and next;
1286 $arg =~ /^-b$/ and $BuildAllParents = 1
1287 and $build_from = shift @ARGV and next;
1289 $arg =~ /^--all:(\S+)$/ and $BuildAllParents = 1
1290 and $build_all_cont = $1 and next;
1291 $arg =~ /^-a:(\S+)$/ and $BuildAllParents = 1
1292 and $build_all_cont = $1 and next;
1293 if ($arg =~ /^--from$/ || $arg =~ /^-f$/) {
1294 $BuildAllParents = 1;
1295 get_incomp_projects
();
1298 $arg =~ /^--prepare$/ and $prepare = 1 and next;
1299 $arg =~ /^-p$/ and $prepare = 1 and next;
1300 $arg =~ /^--prepare:/ and $prepare = 1 and $only_platform = $' and next;
1301 $arg =~ /^-p:/ and $prepare = 1 and $only_platform = $' and next;
1302 $arg =~ /^--since$/ and $BuildAllParents = 1
1303 and $build_since = shift @ARGV and next;
1304 $arg =~ /^-c$/ and $BuildAllParents = 1
1305 and $build_since = shift @ARGV and next;
1306 $arg =~ /^-s$/ and $BuildAllParents = 1
1307 and $build_since = shift @ARGV and next;
1308 $arg =~ /^--help$/ and usage
() and do_exit
(0);
1309 $arg =~ /^-h$/ and usage
() and do_exit
(0);
1310 $arg =~ /^--ignore$/ and $ignore = 1 and next;
1311 $arg =~ /^--genconf$/ and $generate_config = 1 and next;
1312 if ($arg =~ /^--add$/) {
1313 get_list_of_modules
(\
%add_to_config);
1316 if ($arg =~ /^--remove$/) {
1317 get_list_of_modules
(\
%remove_from_config);
1320 ($arg =~ /^--clear$/ || $arg =~ /^--removeall$/) and $clear_config = 1 and next;
1321 $arg =~ /^--html$/ and $html = 1 and next;
1322 $arg =~ /^--dontgraboutput$/ and $dont_grab_output = 1 and next;
1323 $arg =~ /^--html_path$/ and $html_path = shift @ARGV and next;
1324 $arg =~ /^-i$/ and $ignore = 1 and next;
1325 $arg =~ /^--server$/ and $server_mode = 1 and next;
1326 $arg =~ /^--client_timeout$/ and $client_timeout = (shift @ARGV)*60 and next;
1327 $arg =~ /^--setenvstring$/ and $setenv_string = shift @ARGV and next;
1328 $arg =~ /^--port$/ and $ports_string = shift @ARGV and next;
1329 $arg =~ /^--version$/ and do_exit
(0);
1330 $arg =~ /^-V$/ and do_exit
(0);
1331 $arg =~ /^-m$/ and get_modes
() and next;
1332 $arg =~ /^--mode$/ and get_modes
() and next;
1333 $arg =~ /^--stoponerror$/ and $stop_build_on_error = 1 and next;
1334 if ($arg =~ /^--$/) {
1335 push (@dmake_args, get_dmake_args
()) if (!$custom_job);
1338 push (@dmake_args, $arg);
1341 print_error
("\"--html_path\" switch is used only with \"--html\"") if ($html_path);
1342 print_error
("\"--dontgraboutput\" switch is used only with \"--html\"") if ($dont_grab_output);
1344 $grab_output = 0 if ($dont_grab_output);
1345 print_error
('Switches --with_branches and --all collision') if ($build_from && $build_all_cont);
1346 # print_error('Please prepare the workspace on one of UNIX platforms') if ($prepare && ($ENV{GUI} ne 'UNX'));
1347 print_error
('Switches --with_branches and --since collision') if ($build_from && $build_since);
1349 $QuantityToBuild = 0;
1352 print_error
('Switches --job and --deliver collision') if ($custom_job && $deliver);
1353 $custom_job = 'deliver' if $deliver;
1354 $post_job = 'deliver' if (!$custom_job);
1355 $incompatible = scalar keys %incompatibles;
1357 print_error
("--prepare is for use with --from switch only!\n") if (!$incompatible);
1359 if ($QuantityToBuild) {
1360 if ($ignore && !$html) {
1361 print_error
("Cannot ignore errors in multiprocessing build");
1363 if (!$enable_multiprocessing) {
1364 print_error
("Cannot load Win32::Process module for multiprocessing build");
1367 print_error
("Switches -P and --server collision");
1369 } elsif ($stop_build_on_error) {
1370 print_error
("Switche --stoponerror is only for multiprocessing builds");
1374 $client_timeout = 60 * 60 * 2 if (!$client_timeout);
1376 print_error
("--ports switch is for server mode only!!") if ($ports_string);
1377 print_error
("--setenvstring switch is for server mode only!!") if ($setenv_string);
1378 print_error
("--client_timeout switch is for server mode only!!") if ($client_timeout);
1381 if (!$generate_config) {
1382 my $error_message = ' switch(es) should be used only with "--genconf"';
1383 print_error
('"--removeall" ("--clear")' . $error_message) if ($clear_config);
1384 if ((scalar %add_to_config) || (scalar %remove_from_config)) {
1385 print_error
('"--add" or/and "--remove"' . $error_message);
1387 } elsif ((!scalar %add_to_config) && !$clear_config && (!scalar %remove_from_config)){
1388 print_error
('Please supply necessary switch for "--genconf" (--add|--remove|--removeall)');
1391 if ($only_platform) {
1392 $only_common = 'common';
1393 $only_common .= '.pro' if ($only_platform =~ /\.pro$/);
1395 # Default build modes(for OpenOffice.org)
1396 $ENV{BUILD_TYPE
} = 'OOo EXT' if (!defined $ENV{BUILD_TYPE
});
1397 @ARGV = @dmake_args;
1398 foreach $arg (@dmake_args) {
1399 $arg =~ /^verbose=(\S+)$/i and $verbose_mode = ($1 =~ /^t\S*$/i);
1403 sub get_module_and_buildlist_paths
{
1404 my $source_config = SourceConfig
-> new
($StandDir);
1405 my $source_config_file = $source_config->get_config_file_path();
1406 $active_modules{$_}++ foreach ($source_config->get_active_modules());
1407 my %active_modules_copy = %active_modules;
1408 foreach ($source_config->get_all_modules()) {
1409 delete $active_modules_copy{$_} if defined($active_modules_copy{$_});
1410 $module_paths{$_} = $source_config->get_module_path($_);
1411 $build_list_paths{$_} = $source_config->get_module_build_list($_)
1413 $dead_parents{$_}++ foreach (keys %active_modules_copy);
1417 sub get_dmake_args
{
1420 while ($arg = shift @ARGV) {
1421 next if ($arg =~ /^--$/);
1422 push (@job_args, $arg);
1428 # get all options without '-'
1430 sub get_switch_options
{
1433 while ($option = shift @ARGV) {
1434 if (!($option =~ /^-+/)) {
1435 $string .= '-' . $option;
1438 unshift(@ARGV, $option);
1447 # cancel build when one of children has error exit code
1450 # close_server_socket();
1451 $modules_number -= scalar keys %global_deps_hash;
1452 my $broken_modules_number = scalar @broken_modules_names;
1453 if ($broken_modules_number) {
1454 $modules_number -= $broken_modules_number;
1456 print $broken_modules_number;
1457 print " module(s): ";
1458 foreach (@broken_modules_names) {
1460 # RemoveFromDependencies($_, \%global_deps_hash);
1462 print "\nneed(s) to be rebuilt\n\nReason(s):\n\n";
1463 foreach (keys %broken_build) {
1464 print "ERROR: error " . $broken_build{$_} . " occurred while making $_\n";
1466 print "\nAttention: if you build and deliver the above module(s) you may prolongue your the build issuing command \"build --from @broken_modules_names\"\n";
1468 # if ($ENV{GUI} eq 'WNT') {
1469 while (children_number
()) {
1470 handle_dead_children
(1);
1472 foreach (keys %broken_build) {
1473 print "ERROR: error " . $broken_build{$_} . " occurred while making $_\n";
1484 # Function for storing error in multiprocessing AllParents build
1487 my ($pid, $error_code) = @_;
1488 return 0 if (!$error_code);
1489 my $child_nick = $processes_hash{$pid};
1490 if ($ENV{GUI
} eq 'WNT') {
1491 if (!defined $had_error{$child_nick}) {
1492 $had_error{$child_nick}++;
1496 $broken_modules_hashes{$folders_hashes{$child_nick}}++;
1497 $broken_build{$child_nick} = $error_code;
1498 if ($stop_build_on_error) {
1499 clear_from_child
($pid);
1500 # Let all children finish their work
1501 while (children_number
()) {
1502 handle_dead_children
(1);
1510 # child handler (clears (or stores info about) the terminated child)
1512 sub handle_dead_children
{
1513 my $running_children = children_number
();
1514 return if (!$running_children);
1515 my $force_wait = shift;
1516 my $try_once_more = 0;
1519 if ($ENV{GUI
} eq 'WNT' && !$cygwin) {
1520 foreach $pid (keys %processes_hash) {
1521 my $exit_code = undef;
1522 my $proc_obj = $windows_procs{$pid};
1523 $proc_obj->GetExitCode($exit_code);
1524 if ( $exit_code != 259 ) {
1525 $try_once_more = store_error
($pid, $exit_code);
1526 delete $windows_procs{$pid};
1527 if ($try_once_more) {
1528 give_second_chance
($pid);
1530 clear_from_child
($pid);
1534 sleep 1 if (children_number
() >= $QuantityToBuild || ($force_wait && ($running_children == children_number
())));
1536 if (children_number
() >= $QuantityToBuild ||
1537 ($force_wait && ($running_children == children_number
()))) {
1540 $pid = waitpid( -1, &WNOHANG
);
1543 $try_once_more = store_error
($pid, $?
);
1544 if ($try_once_more) {
1545 give_second_chance
($pid);
1547 clear_from_child
($pid);
1551 } while(children_number
() >= $QuantityToBuild);
1554 sub give_second_chance
{
1556 # A malicious hack for misterious windows problems - try 2 times
1557 # to run dmake in the same directory if errors occurs
1558 my $child_nick = $processes_hash{$pid};
1559 $running_children{$folders_hashes{$child_nick}}--;
1560 delete $processes_hash{$pid};
1561 start_child
($child_nick, $folders_hashes{$child_nick});
1564 sub clear_from_child
{
1566 my $child_nick = $processes_hash{$pid};
1568 if (defined $broken_build{$child_nick}) {
1569 $error_code = $broken_build{$child_nick};
1571 RemoveFromDependencies
($child_nick,
1572 $folders_hashes{$child_nick});
1574 my $module = $module_by_hash{$folders_hashes{$child_nick}};
1575 html_store_job_info
($folders_hashes{$child_nick}, $child_nick, $error_code);
1576 $running_children{$folders_hashes{$child_nick}}--;
1577 delete $processes_hash{$pid};
1578 $only_dependent = 0;
1579 $verbose_mode && print 'Running processes: ' . children_number
() . "\n";
1583 # Build the entire project according to queue of dependencies
1585 sub BuildDependent
{
1586 $dependencies_hash = shift;
1588 my $child_nick = '';
1589 $running_children{$dependencies_hash} = 0 if (!defined $running_children{$dependencies_hash});
1590 while ($child_nick = PickPrjToBuild
($dependencies_hash)) {
1591 if (($QuantityToBuild)) { # multiprocessing not for $BuildAllParents (-all etc)!!
1593 handle_dead_children
(0);
1594 if (defined $broken_modules_hashes{$dependencies_hash} && !$ignore) {
1595 return if ($BuildAllParents);
1598 # start current child & all
1599 # that could be started now
1600 start_child
($child_nick, $dependencies_hash) if ($child_nick);
1601 $child_nick = PickPrjToBuild
($dependencies_hash);
1603 return if ($BuildAllParents);
1604 handle_dead_children
(1) if (!$no_projects);
1606 } while (!$no_projects);
1607 return if ($BuildAllParents);
1608 while (children_number
()) {
1609 handle_dead_children
(1);
1611 # if (defined $last_module) {
1612 # $build_is_finished{$last_module}++ if (!defined $modules_with_errors{$last_module});
1615 if (defined $broken_modules_hashes{$dependencies_hash}) {
1620 dmake_dir
($child_nick);
1626 sub children_number
{
1627 return scalar keys %processes_hash;
1631 my ($job_dir, $dependencies_hash) = @_;
1632 $jobs_hash{$job_dir}->{START_TIME
} = time();
1633 $jobs_hash{$job_dir}->{STATUS
} = 'building';
1634 if ($job_dir =~ /(\s)/o) {
1635 my $error_code = undef;
1636 $error_code = do_custom_job
($job_dir, $dependencies_hash);
1639 html_store_job_info
($dependencies_hash, $job_dir);
1641 my $children_running;
1642 my $oldfh = select STDOUT
;
1644 if ($ENV{GUI
} eq 'WNT' && !$cygwin) {
1646 my $process_obj = undef;
1647 my $rc = Win32
::Process
::Create
($process_obj, $dmake_bin,
1649 0, 0, #NORMAL_PRIORITY_CLASS,
1651 # my $rc = Win32::Process::Create($process_obj, $_4nt_exe,
1652 # "/c $dmake_batch",
1653 # 0, NORMAL_PRIORITY_CLASS,
1655 print_error
("Cannot start child process") if (!$rc);
1656 $pid = $process_obj->GetProcessID();
1657 $windows_procs{$pid} = $process_obj;
1659 if ($pid = fork) { # parent
1660 } elsif (defined $pid) { # child
1663 dmake_dir
($job_dir);
1668 $processes_hash{$pid} = $job_dir;
1669 $children_running = children_number
();
1670 $verbose_mode && print 'Running processes: ', $children_running, "\n";
1671 $maximal_processes = $children_running if ($children_running > $maximal_processes);
1672 $folders_hashes{$job_dir} = $dependencies_hash;
1673 $running_children{$dependencies_hash}++;
1677 # Build everything that should be built multiprocessing version
1679 sub build_multiprocessing
{
1681 my @build_queue = (); # array, containing queue of projects
1684 while ($Prj = PickPrjToBuild
(\
%global_deps_hash)) {
1685 push @build_queue, $Prj;
1686 $projects_deps_hash{$Prj} = {};
1687 get_deps_hash
($Prj, $projects_deps_hash{$Prj});
1688 my $info_hash = $html_info{$Prj};
1689 $$info_hash{DIRS
} = check_deps_hash
($projects_deps_hash{$Prj}, $Prj);
1690 $module_by_hash{$projects_deps_hash{$Prj}} = $Prj;
1692 if (!$Prj || !defined $projects_deps_hash{$Prj}) {
1693 cancel_build
() if (!scalar @build_queue && !children_number
());
1694 handle_dead_children
(1);
1696 build_actual_queue
(\
@build_queue);
1697 } while (scalar (keys %global_deps_hash));
1698 # Let the last module be built till the end
1699 while (scalar @build_queue) {
1700 build_actual_queue
(\
@build_queue);
1701 handle_dead_children
(1);
1703 # Let all children finish their work
1704 while (children_number
()) {
1705 handle_dead_children
(1);
1707 cancel_build
() if (scalar keys %broken_build);
1711 sub mp_success_exit
{
1712 # close_server_socket();
1713 # if (!$custom_job && $post_custom_job) {
1714 # do_post_custom_job(CorrectPath($StandDir.$CurrentPrj));
1716 print "\nMultiprocessing build is finished\n";
1717 print "Maximal number of processes run: $maximal_processes\n";
1722 # Here the built queue is built as long as possible
1724 sub build_actual_queue
{
1725 my $build_queue = shift;
1728 while ($i <= (scalar(@
$build_queue) - 1)) {
1729 $Prj = $$build_queue[$i];
1730 if (defined $broken_modules_hashes{$projects_deps_hash{$Prj}} && !$ignore) {
1731 push (@broken_modules_names, $Prj);
1732 splice (@
$build_queue, $i, 1);
1735 $only_dependent = 0;
1737 BuildDependent
($projects_deps_hash{$Prj});
1738 handle_dead_children
(0);
1740 !$running_children{$projects_deps_hash{$Prj}}) {
1741 if (!defined $broken_modules_hashes{$projects_deps_hash{$Prj}} || $ignore)
1743 RemoveFromDependencies
($Prj, \
%global_deps_hash);
1744 $build_is_finished{$Prj}++;
1745 splice (@
$build_queue, $i, 1);
1752 } while (!are_all_dependent
($build_queue));
1756 my ($job, $path, $registered_name) = @_;
1757 my $job_to_do = $job;
1759 print "$job_to_do\n";
1762 $job_to_do = $deliver_command if ($job eq 'deliver');
1763 $registered_name = $path if (!defined $registered_name);
1768 my $log_file = $jobs_hash{$registered_name}->{LONG_LOG_PATH
};
1769 my $log_dir = File
::Basename
::dirname
($log_file);
1771 system("$perl $mkout");
1773 $error_code = system ("$job_to_do > $log_file 2>&1");
1774 if (!$grab_output && -f
$log_file) {
1775 system("cat $log_file");
1778 $error_code = system ("$job_to_do");
1784 my ($module_job, $dependencies_hash) = @_;
1785 $module_job =~ /(\s)/o;
1788 html_store_job_info($dependencies_hash, $module_job);
1790 if ($job eq $pre_job) {
1791 announce_module($module);
1792 # html_store_job_info($dependencies_hash, $job_dir);
1793 RemoveFromDependencies($module_job, $dependencies_hash);
1795 $error_code = run_job($job, $module_paths{$module}, $module_job);
1797 # give windows one more chance
1798 if ($ENV{GUI} eq 'WNT') {
1799 $error_code = run_job($job, $module_paths{$module}, $module_job);
1803 $broken_modules_hashes{$dependencies_hash}++;
1804 $broken_build{$module} = $error_code;
1806 RemoveFromDependencies($module_job, $dependencies_hash);
1809 html_store_job_info($dependencies_hash, $module_job, $error_code);
1814 # Print announcement for module just started
1816 sub announce_module {
1818 $build_in_progress{$Prj}++;
1819 print_announce($Prj);
1822 sub print_announce {
1825 $prj_type = $modules_types{$Prj} if (defined $modules_types{$Prj});
1827 if ($prj_type eq 'lnk') {
1828 if (scalar keys %active_modules && (!defined $active_modules{$Prj})) {
1829 $text = "Skipping module $Prj\n";
1831 $text = "Skipping link to $Prj\n";
1833 $build_is_finished{$Prj}++;
1834 } elsif ($prj_type eq 'img') {
1835 # return if (defined $module_announced{$`});
1836 $text = "Skipping incomplete $Prj\n";
1837 $build_is_finished{$Prj}++;
1838 } elsif ($custom_job) {
1839 $text = "Running custom job \"$custom_job\" in module $Prj\n";
1841 $text = "Building module $Prj\n";
1843 print $echo . "=============\n";
1844 print $echo . $text;
1847 sub are_all_dependent
{
1848 my $build_queue = shift;
1850 foreach my $prj (@
$build_queue) {
1851 $folder = FindIndepPrj
($projects_deps_hash{$prj});
1852 return '' if ($folder);
1859 # Procedure defines if the local directory is a
1860 # complete module, an image or a link
1861 # return values: lnk link
1862 # img incomplete (image)
1863 # mod complete (module)
1865 sub modules_classify
{
1867 foreach my $module (sort @modules) {
1868 if (!defined $module_paths{$module}) {
1869 $modules_types{$module} = 'img';
1872 if (( $module_paths{$module} =~ /\.lnk$/) || ($module_paths{$module} =~ /\.link$/)
1873 || (scalar keys %active_modules && (!defined $active_modules{$module}))) {
1874 $modules_types{$module} = 'lnk';
1877 $modules_types{$module} = 'mod';
1882 # This procedure provides consistency for cws
1883 # and optimized build (ie in case of -with_branches, -all:prj_name
1884 # and -since switches)
1886 sub provide_consistency
{
1888 foreach my $module_ref (\
$build_from, \
$build_all_cont, \
$build_since) {
1890 return if (defined $module_paths{$$module_ref});
1891 print_error
("Cannot find module '$$module_ref'", 9);
1898 # Get the workspace list ('stand.lst'), either from 'localini'
1899 # or, if this is not possible, from 'globalini.
1900 # (Heiner's proprietary :)
1902 sub get_workspace_lst
1905 if ( $^O
eq 'MSWin32' ) {
1911 my $inifile = "$home/localini/stand.lst";
1915 # $inifile = get_globalini() . "/stand.lst";
1916 # return $inifile if (-f $inifile);
1922 # Procedure clears up module for incompatible build
1924 sub ensure_clear_module
{
1926 if ($modules_types{$module} eq 'mod') {
1927 clear_module
($module);
1930 if ($modules_types{$module} eq 'lnk' && (File
::Basename
::basename
($module_paths{$module}) ne $module)) {
1931 if(rename($module_paths{$module}, File
::Basename
::dirname
($module_paths{$module}) ."/$module")) {
1932 $module_paths{$module} = File
::Basename
::dirname
($module_paths{$module}) ."/$module";
1933 clear_module
($module);
1935 print_error
("Cannot rename link to $module. Please rename it manually");
1941 # Procedure removes output tree from the module (without common trees)
1945 print "Removing module's $module output trees...\n";
1946 print "\n" and return if ($show);
1947 opendir DIRHANDLE
, $module_paths{$module};
1948 my @dir_content = readdir(DIRHANDLE
);
1949 closedir(DIRHANDLE
);
1950 foreach (@dir_content) {
1952 my $dir = CorrectPath
($module_paths{$module}.'/'.$_);
1953 if ((!-d
$dir.'/.svn') && is_output_tree
($dir)) {
1954 #print "I would delete $dir\n";
1955 rmtree
("$dir", 0, 1);
1957 system("$remove_command $dir");
1959 push(@warnings, "Cannot delete $dir");
1960 #print_error("Cannot delete $dir");
1962 print STDERR
(">>> Removed $dir by force\n");
1970 # Figure out if the directory is an output tree
1972 sub is_output_tree
{
1974 $dir =~ /([\w\d\.]+)$/;
1976 return '1' if (defined $platforms{$_});
1978 return '1' if ($_ eq $only_common);
1980 if (scalar keys %platforms < scalar keys %platforms_to_copy) {
1983 return '1' if (/^common$/);
1984 return '1' if (/^common\.pro$/);
1991 if( defined($ENV{TMPDIR
}) ) {
1992 $tmp_dir = $ENV{TMPDIR
} . '/';
1993 } elsif( defined($ENV{TMP
}) ) {
1994 $tmp_dir = $ENV{TMP
} . '/';
1999 return File
::Temp
::tempdir
(DIR
=>$tmp_dir);
2001 # $tmp_dir .= $$ while (-e $tmp_dir);
2002 # $tmp_dir = CorrectPath($tmp_dir);
2003 # eval {mkpath($tmp_dir)};
2004 # print_error("Cannot create temporary directory in $tmp_dir") if ($@);
2009 sub retrieve_build_list
{
2011 my $old_fh = select(STDOUT
);
2013 # Try to get global depencies from solver's build.lst if such exists
2014 my $solver_inc_dir = "$ENV{SOLARVER}/common";
2015 $solver_inc_dir .= $ENV{PROEXT
} if (defined $ENV{PROEXT
});
2016 $solver_inc_dir .= '/inc';
2017 $solver_inc_dir .= $ENV{UPDMINOREXT
} if (defined $ENV{UPDMINOREXT
});
2018 $solver_inc_dir .= "/$module";
2019 $solver_inc_dir = CorrectPath
($solver_inc_dir);
2020 $dead_parents{$module}++;
2021 print "Fetching dependencies for module $module from solver...";
2022 foreach (@possible_build_lists) {
2023 my $possible_build_lst = "$solver_inc_dir/$_";
2024 if (-e
$possible_build_lst) {
2027 return $possible_build_lst;
2032 if (!defined $dead_parents{$module}) {
2033 print "WARNING: Cannot figure out CWS for $module. Forgot to set CWS?\n";
2039 sub fix_permissions
{
2040 my $file = $File::Find
::name
;
2041 return unless -f
$file;
2042 chmod '0664', $file;
2046 # Removes projects which it is not necessary to build
2047 # in incompatible build
2049 sub prepare_incompatible_build
{
2050 my ($prj, $deps_hash, @missing_modules);
2052 foreach (keys %incompatibles) {
2053 my $incomp_prj = $_;
2054 if (!defined $$deps_hash{$_}) {
2055 $incomp_prj .= '.lnk' if ($module_paths{$module} =~ /\.lnk$/);
2056 $incomp_prj .= '.link' if ($module_paths{$module} =~ /\.link$/);
2058 delete $incompatibles{$_};
2059 $incompatibles{$incomp_prj} = $$deps_hash{$incomp_prj};
2060 delete $$deps_hash{$incomp_prj};
2062 while ($prj = PickPrjToBuild
($deps_hash)) {
2063 RemoveFromDependencies
($prj, $deps_hash);
2064 RemoveFromDependencies
($prj, \
%incompatibles);
2066 foreach (keys %incompatibles) {
2067 $$deps_hash{$_} = $incompatibles{$_};
2069 if ($build_all_cont) {
2070 prepare_build_all_cont
($deps_hash);
2071 delete $$deps_hash{$build_all_cont};
2073 @modules_built = keys %$deps_hash;
2074 clear_delivered
() if ($prepare);
2075 my $old_output_tree = '';
2076 foreach $prj (sort keys %$deps_hash) {
2078 ensure_clear_module
($prj);
2081 if ($modules_types{$prj} ne 'mod') {
2082 push(@missing_modules, $prj);
2083 } elsif (-d
$module_paths{$prj}. '/'. $ENV{INPATH
}) {
2088 if (scalar @missing_modules) {
2089 my $warning_string = 'Following modules are inconsistent/missing: ' . "@missing_modules";
2090 push(@warnings, $warning_string);
2092 if ($build_all_cont) {
2093 $$deps_hash{$build_all_cont} = ();
2094 $build_all_cont = '';
2096 if ($old_output_tree) {
2097 push(@warnings, 'Some module(s) contain old output tree(s)!');
2099 if (scalar @warnings) {
2100 print "WARNING(S):\n";
2101 print STDERR
"$_\n" foreach (@warnings);
2102 print "\nATTENTION: If you are performing an incompatible build, please break the build with Ctrl+C and prepare the workspace with \"--prepare\" switch!\n\n" if (!$prepare);
2106 print "\nPreparation finished";
2107 if (scalar @warnings) {
2108 print " with WARNINGS!!\n\n";
2109 } else {print " successfully\n\n";}
2111 do_exit
(0) if ($prepare);
2115 # Removes projects which it is not necessary to build
2116 # with -with_branches switch
2118 sub prepare_build_from
{
2119 my ($prj, $deps_hash);
2121 my %from_deps_hash = (); # hash of dependencies of the -from project
2122 GetParentDeps
($build_from, \
%from_deps_hash);
2123 foreach $prj (keys %from_deps_hash) {
2124 delete $$deps_hash{$prj};
2125 RemoveFromDependencies
($prj, $deps_hash);
2130 # Removes projects which it is not necessary to build
2131 # with --all:prj_name or --since switch
2133 sub prepare_build_all_cont
{
2134 my ($prj, $deps_hash, $border_prj);
2136 $border_prj = $build_all_cont if ($build_all_cont);
2137 $border_prj = $build_since if ($build_since);
2138 while ($prj = PickPrjToBuild
($deps_hash)) {
2140 $orig_prj = $` if ($prj =~ /\.lnk$/o);
2141 $orig_prj = $` if ($prj =~ /\.link$/o);
2142 if (($border_prj ne $prj) &&
2143 ($border_prj ne $orig_prj)) {
2144 RemoveFromDependencies
($prj, $deps_hash);
2147 if ($build_all_cont) {
2148 $$deps_hash{$prj} = ();
2150 RemoveFromDependencies
($prj, $deps_hash);
2159 while ($option = shift @ARGV) {
2160 if ($option =~ /^-+/) {
2161 unshift(@ARGV, $option);
2164 if ($option =~ /,/) {
2166 unshift(@ARGV, $') if ($');
2167 } else {$build_modes{$option}++;};
2170 $build_modes{$option}++;
2173 sub get_list_of_modules {
2175 my $hash_ref = shift;
2176 while ($option = shift @ARGV) {
2177 if ($option =~ /^-+/) {
2178 unshift(@ARGV, $option);
2181 if ($option =~ /,/) {
2182 foreach (split /,/, $option) {
2187 $$hash_ref{$option}++;
2191 if (!scalar %$hash_ref) {
2192 print_error('No module list supplied!!');
2196 sub get_incomp_projects {
2198 while ($option = shift @ARGV) {
2199 if ($option =~ /^-+/) {
2200 unshift(@ARGV, $option);
2203 if ($option =~ /(:)/) {
2205 print_error
("-from switch collision") if ($build_all_cont);
2206 $build_all_cont = $';
2208 $incompatibles{$option}++;
2215 my $platforms_ref = shift;
2216 if ($only_platform) {
2217 foreach (split(',', $only_platform)) {
2218 $$platforms_ref{$_}++;
2220 $platforms_ref = \%platforms_to_copy;
2223 my $workspace_lst = get_workspace_lst();
2224 if ($workspace_lst) {
2225 my $workspace_db = GenInfoParser->new();
2226 my $success = $workspace_db->load_list($workspace_lst);
2228 print_error("Can't load workspace list
'$workspace_lst'.", 4);
2230 my $access_path = $ENV{WORK_STAMP} . '/Environments';
2231 my @platforms_available = $workspace_db->get_keys($access_path);
2232 my $solver = $ENV{SOLARVERSION};
2233 foreach (@platforms_available) {
2234 my $s_path = $solver . '/' . $_;
2235 $$platforms_ref{$_}++ if (-d $s_path);
2239 if (!scalar keys %platforms) {
2240 # An Auses wish - fallback to INPATH for new platforms
2241 if (defined $ENV{INPATH}) {
2242 $$platforms_ref{$ENV{INPATH}}++;
2244 print_error("There is
no platform found
!!") ;
2250 # This procedure clears solver from delivered
2251 # by the modules to be build
2253 sub clear_delivered {
2254 my $message = 'Clearing up delivered';
2256 my $deliver_delete_switches = '-delete';
2257 if (scalar keys %platforms < scalar keys %platforms_to_copy) {
2258 $message .= ' without common trees';
2259 $deliver_delete_switches .= ' -dontdeletecommon';
2264 foreach my $platform (keys %platforms) {
2265 print "\nRemoving delivered
for $platform\n";
2266 my %solar_vars = ();
2267 read_ssolar_vars($platform, \%solar_vars);
2268 if (scalar keys %solar_vars) {
2269 foreach (keys %solar_vars) {
2270 if (!defined $backup_vars{$_}) {
2271 $backup_vars{$_} = $ENV{$_};
2273 $ENV{$_} = $solar_vars{$_};
2276 my $undeliver = "$deliver_command $deliver_delete_switches $nul";
2277 # my $current_dir = getcwd();
2278 foreach my $module (sort @modules_built) {
2279 if (chdir($module_paths{$module})) {
2280 push(@warnings, "Could
not remove delivered files from the module
$module. Your build can become inconsistent
.\n");
2282 print "Removing delivered from module
$module\n";
2284 if (system($undeliver)) {
2285 $ENV{$_} = $backup_vars{$_} foreach (keys %backup_vars);
2286 print_error("Cannot run
: $undeliver");
2290 # chdir $current_dir;
2293 $ENV{$_} = $backup_vars{$_} foreach (keys %backup_vars);
2297 # Run setsolar for given platform and
2298 # write all variables needed in %solar_vars hash
2300 sub read_ssolar_vars {
2301 my ($setsolar, $tmp_file);
2302 $setsolar = $ENV{ENV_ROOT} . '/etools/setsolar.pl';
2303 my ($platform, $solar_vars) = @_;
2304 if ( $^O eq 'MSWin32' ) {
2305 $tmp_file = $ENV{TEMP} . "\\solar
.env
.$$.tmp
";
2307 $setsolar = '/net/jumbo2.germany/buildenv/r/etools/setsolar.pl' if ! -e $setsolar;
2308 $tmp_file = $ENV{HOME} . "/.solar
.env
.$$.tmp
";
2310 if (!-e $setsolar) {
2311 print STDERR "There is
no setsolar found
. Falling back to current platform settings
\n";
2315 if ($platform =~ /\.pro$/) {
2320 my ($verswitch, $source_root, $cwsname);
2321 $verswitch = "-ver
$ENV{UPDMINOR
}" if (defined $ENV{UPDMINOR});
2322 $source_root = '-sourceroot' if (defined $ENV{SOURCE_ROOT_USED});
2323 $cws_name = "-cwsname
$ENV{CWS_WORK_STAMP
}" if (defined $ENV{CWS_WORK_STAMP});
2325 my $param = "-$ENV{WORK_STAMP
} $verswitch $source_root $cws_name $pro $platform";
2326 my $ss_command = "$perl $setsolar -file
$tmp_file $param $nul";
2327 if (system($ss_command)) {
2329 print_error("Cannot run command
:\n$ss_command");
2331 get_solar_vars($solar_vars, $tmp_file);
2335 # read variables to hash
2337 sub get_solar_vars {
2338 my ($solar_vars, $file) = @_;
2340 open SOLARTABLE, "<$file" or die "can´t
open solarfile
$file";
2341 while(<SOLARTABLE>) {
2343 next if(!/^\w+\s+(\w+)/o);
2344 next if (!defined $deliver_env{$1});
2346 if ( $^O eq 'MSWin32' ) {
2347 my $string_tail = $';
2348 $string_tail =~ /=(\S+)$/o;
2354 $$solar_vars{$var} = $value;
2361 # Procedure renames <module>.lnk (.link) into <module>
2363 sub get_current_module {
2364 my $module_name = shift;
2365 my $link_name = $module_name . '.lnk';
2366 $link_name .= '.link' if (-e $StandDir.$module_name . '.link');
2369 print "\nBreaking
link to module
$module_name";
2370 my $result = rename $link_name, $module_name;
2372 print_error("Cannot
rename $module_name: $!\n");
2374 if ( $CurrentPrj eq $link_name) {
2375 $CurrentPrj = $module_name;
2382 my $start_dir = getcwd();
2383 my @dir_entries = split(/[\\\/]/, $start_dir);
2384 my $current_module = $dir_entries[$#dir_entries];
2385 $current_module = $` if (($current_module =~ /(\.lnk)$/) || ($current_module =~ /(\.link)$/));
2386 my $link_name = $ENV{SOLARSRC}.'/'.$current_module.$1;
2387 if ( $^O eq 'MSWin32' ) {
2388 $start_dir =~ s/\\/\//go;
2389 $link_name =~ s/\\/\//go;
2390 if (lc($start_dir) eq lc($link_name)) {
2391 get_current_module($current_module);
2393 } elsif ((-l $link_name) && (chdir $link_name)) {
2394 if ($start_dir eq getcwd()) {
2395 # we're dealing with link => fallback to SOLARSRC under UNIX
2396 $StandDir = $ENV{SOLARSRC}.'/';
2397 get_current_module($current_module);
2407 # Store all available build modi in %build_modes
2409 sub get_build_modes {
2410 return if (scalar keys %build_modes);
2411 if (defined $ENV{BUILD_TYPE}) {
2412 if ($ENV{BUILD_TYPE} =~ /\s+/o) {
2413 my @build_modes = split (/\s+/, $ENV{BUILD_TYPE});
2414 $build_modes{$_}++ foreach (@build_modes);
2416 $build_modes{$ENV{BUILD_TYPE}}++;
2423 # pick only the modules, that should be built for
2424 # build types from %build_modes
2426 sub pick_for_build_type {
2427 my $modules = shift;
2428 my @mod_array = split(/\s+/, $modules);
2429 print_error("Wrongly written dependencies string
:\n $modules\n") if ($mod_array[$#mod_array] ne 'NULL');
2431 my @modules_to_build;
2432 foreach (@mod_array) {
2433 if (/(\w+):(\S+)/o) {
2434 push(@modules_to_build, $2) if (defined $build_modes{$1});
2437 push(@modules_to_build, $_);
2439 return @modules_to_build;
2443 # close_server_socket();
2444 my $exit_code = shift;
2446 generate_html_file(1);
2449 # perl 5.10 returns 'resource busy' for rmtree
2450 rmdir(CorrectPath($tmp_dir)) if ($tmp_dir);
2452 rmtree(CorrectPath($tmp_dir), 1, 0) if ($tmp_dir);
2457 # Procedure sorts module in user-frendly order
2459 sub sort_modules_appearance {
2460 foreach (keys %dead_parents) {
2461 delete $build_is_finished{$_} if (defined $build_is_finished{$_});
2462 delete $build_in_progress{$_} if (defined $build_in_progress{$_});
2464 foreach (keys %build_is_finished) {
2465 delete $build_in_progress{$_} if (defined $build_in_progress{$_});
2466 delete $build_in_progress_shown{$_} if (defined $build_in_progress_shown{$_});
2468 @modules_order = sort keys %modules_with_errors;
2469 foreach (keys %modules_with_errors) {
2470 delete $build_in_progress{$_} if (defined $build_in_progress{$_});
2471 delete $build_is_finished{$_} if (defined $build_is_finished{$_});
2472 delete $build_in_progress_shown{$_} if (defined $build_in_progress_shown{$_});
2474 $build_in_progress_shown{$_}++ foreach (keys %build_in_progress);
2475 push(@modules_order, $_) foreach (sort keys %build_in_progress_shown);
2476 push(@modules_order, $_) foreach (sort keys %build_is_finished);
2477 foreach(sort keys %html_info) {
2478 next if (defined $build_is_finished{$_} || defined $build_in_progress{$_} || defined $modules_with_errors{$_});
2479 push(@modules_order, $_);
2481 return @modules_order;
2484 sub generate_html_file {
2486 my $force_update = shift;
2487 $html_last_updated = time;
2488 my @modules_order = sort_modules_appearance();
2489 my ($successes_percent, $errors_percent) = get_progress_percentage(scalar keys %html_info, scalar keys %build_is_finished, scalar keys %modules_with_errors);
2490 my $build_duration = get_time_line(time - $build_time);
2491 my $temp_html_file = File::Temp::tmpnam($tmp_dir);
2493 $title = $ENV{CWS_WORK_STAMP} . ': ' if (defined $ENV{CWS_WORK_STAMP});
2494 $title .= $ENV{INPATH};
2495 die("Cannot
open $temp_html_file") if (!open(HTML, ">$temp_html_file"));
2496 print HTML '<html><head>';
2497 print HTML '<TITLE id=MainTitle>' . $title . '</TITLE>';
2498 print HTML '<script type="text
/javascript
">' . "\n";
2499 print HTML 'initFrames();' . "\n";
2500 print HTML 'var IntervalID;' . "\n";
2501 print HTML 'function loadFrame_0() {' . "\n";
2502 print HTML 'document.write("<html
>");' . "\n";
2503 print HTML 'document.write("<head
>");' . "\n";
2504 print HTML 'document.write("</head
>");' . "\n";
2505 print HTML 'document.write("<body
>");' . "\n";
2506 if ($build_finished) {
2507 print HTML 'document.write("<h3 align
=center style
=\"color
:red
\">Build process is finished
</h3
>");' . "\n";
2508 print HTML ' top.frames[0].clearInterval(top.frames[0].IntervalID);' . "\n";
2510 if ($BuildAllParents) {
2511 print HTML 'document.write("<table valign
=top cellpadding
=0 hspace
=0 vspace
=0 cellspacing
=0 border
=0>");' . "\n";
2512 print HTML 'document.write(" <tr
>");' . "\n";
2513 print HTML 'document.write(" <td
><a id
=ErroneousModules href
=\"javascript
:top
.Error
(\'\', \'';
2514 print HTML join('<br
>', sort keys %modules_with_errors);
2515 print HTML '\', \'\')\"); title
=\"';
2516 print HTML scalar keys %modules_with_errors;
2517 print HTML ' module
(s
) with errors
\">Total Progress
:</a></td
>");' . "\n";
2518 print HTML 'document.write(" <td
>");' . "\n";
2519 print HTML 'document.write(" <table width
=100px valign
=top cellpadding
=0 hspace
=0 vspace
=0 cellspacing
=0 border
=0>");' . "\n";
2520 print HTML 'document.write(" <tr
>");' . "\n";
2521 print HTML 'document.write(" <td height
=20px width
=';
2522 print HTML $successes_percent + $errors_percent;
2523 if (scalar keys %modules_with_errors) {
2524 print HTML '% bgcolor
=red valign
=top
></td
>");' . "\n";
2526 print HTML '% bgcolor=#25A528 valign=top></td>");' . "\n";
2528 print HTML 'document
.write(" <td width=';
2529 print HTML 100 - ($successes_percent + $errors_percent);
2530 print HTML '% bgcolor=lightgrey valign=top></td>");' . "\n";
2531 print HTML 'document
.write(" </tr>");' . "\n";
2532 print HTML 'document
.write(" </table>");' . "\n";
2533 print HTML 'document
.write(" </td>");' . "\n";
2534 print HTML 'document
.write(" <td align=right>  Build time: ' . $build_duration .'</td>");' . "\n";
2535 print HTML 'document
.write(" </tr>");' . "\n";
2536 print HTML 'document
.write("</table>");' . "\n";
2539 print HTML 'document
.write("<table width=100% bgcolor=white>");' . "\n";
2540 print HTML 'document
.write(" <tr>");' . "\n";
2541 print HTML 'document
.write(" <td width=30% align=\"center\"><strong style=\"color:blue\">Module</strong></td>");' . "\n";
2542 print HTML 'document
.write(" <td width=* align=\"center\"><strong style=\"color:blue\">Status</strong></td>");' . "\n";
2543 print HTML 'document
.write(" <td width=15% align=\"center\"><strong style=\"color:blue\">CPU Time</strong></td>");' . "\n";
2544 print HTML 'document
.write(" </tr>");' . "\n";
2546 foreach (@modules_order) {
2547 next if ($modules_types{$_} eq 'lnk
');
2548 next if (scalar keys %active_modules && (!defined $active_modules{$_}));
2549 my ($errors_info_line, $dirs_info_line, $errors_number, $successes_percent, $errors_percent, $time) = get_html_info($_);
2551 print HTML 'document
.write(" <tr>");' . "\n";
2552 print HTML 'document
.write(" <td width=*>");' . "\n";
2554 if (defined $dirs_info_line) {
2555 print HTML 'document
.write(" <a id=';
2557 print HTML ' href=\"javascript:top.Error(\'';
2558 print HTML $_ , '\', ' ;
2559 print HTML $errors_info_line;
2561 print HTML $dirs_info_line;
2562 print HTML ')\"); title=\"';
2563 print HTML $errors_number;
2564 print HTML ' error(s)\">', $_, '</a>");' . "\n";
2566 print HTML 'document
.write("<em style=color:gray>' . $_ . '</em>");';
2570 print HTML 'document
.write(" </td>");' . "\n";
2571 print HTML 'document
.write(" <td>");' . "\n";
2572 print HTML 'document
.write(" <table width=100% valign=top cellpadding=0 hspace=0 vspace=0 cellspacing=0 border=0>");' . "\n";
2573 print HTML 'document
.write(" <tr>");' . "\n";
2574 print HTML 'document
.write(" <td height=15* width=';
2576 print HTML $successes_percent + $errors_percent;
2577 if ($errors_number) {
2578 print HTML '% bgcolor=red valign=top></td>");' . "\n";
2580 print HTML '% bgcolor
=#25A528 valign=top></td>");' . "\n";
2582 print HTML
'document.write(" <td width=';
2584 print HTML
100 - ($successes_percent + $errors_percent);
2585 print HTML
'% bgcolor=lightgrey valign=top></td>");' . "\n";
2586 print HTML
'document.write(" </tr>");' . "\n";
2587 print HTML
'document.write(" </table>");' . "\n";
2588 print HTML
'document.write(" </td>");' . "\n";
2589 print HTML
'document.write(" <td align=\"center\">', $time, '</td>");' . "\n";
2590 print HTML
'document.write(" </tr>");' . "\n";
2593 print HTML
'document.write("</table>");' . "\n";
2594 print HTML
'document.write("</body>");' . "\n";
2595 print HTML
'document.write("</html>");' . "\n";
2596 print HTML
'document.close();' . "\n";
2597 print HTML
'refreshInfoFrames();' . "\n";
2598 print HTML
'}' . "\n";
2600 print HTML
'function refreshInfoFrames() { ' . "\n";
2601 print HTML
' var ModuleNameObj = top.innerFrame.frames[2].document.getElementById("ModuleErrors");' . "\n";
2602 print HTML
' if (ModuleNameObj != null) {' . "\n";
2603 print HTML
' var ModuleName = ModuleNameObj.getAttribute(\'name\');' . "\n";
2604 print HTML
' var ModuleHref = top.innerFrame.frames[0].document.getElementById(ModuleName).getAttribute(\'href\');' . "\n";
2605 print HTML
' eval(ModuleHref);' . "\n";
2606 print HTML
' } else if (top.innerFrame.frames[2].document.getElementById("ErroneousModules") != null) {' . "\n";
2607 print HTML
' var ModuleHref = top.innerFrame.frames[0].document.getElementById("ErroneousModules").getAttribute(\'href\');' . "\n";
2608 print HTML
' eval(ModuleHref);' . "\n";
2609 print HTML
' if (top.innerFrame.frames[1].document.getElementById("ModuleJobs") != null) {' . "\n";
2610 print HTML
' var ModuleName = top.innerFrame.frames[1].document.getElementById("ModuleJobs").getAttribute(\'name\');' . "\n";
2611 print HTML
' ModuleHref = top.innerFrame.frames[0].document.getElementById(ModuleName).getAttribute(\'href\');' . "\n";
2612 print HTML
' var HrefString = ModuleHref.toString();' . "\n";
2613 print HTML
' var RefEntries = HrefString.split(",");' . "\n";
2614 print HTML
' var RefreshParams = new Array();' . "\n";
2615 print HTML
' for (i = 0; i < RefEntries.length; i++) {' . "\n";
2616 print HTML
' RefreshParams[i] = RefEntries[i].substring(RefEntries[i].indexOf("\'") + 1, RefEntries[i].lastIndexOf("\'"));' . "\n";
2617 print HTML
' };' . "\n";
2618 print HTML
' FillFrame_1(RefreshParams[0], RefreshParams[1], RefreshParams[2]);' . "\n";
2619 print HTML
' }' . "\n";
2620 print HTML
' };' . "\n";
2621 print HTML
'}' . "\n";
2622 print HTML
'function loadFrame_1() {' . "\n";
2623 print HTML
' document.write("<h3 align=center>Jobs</h3>");' . "\n";
2624 print HTML
' document.write("Click on the project of interest");' . "\n";
2625 print HTML
' document.close();' . "\n";
2626 print HTML
'}' . "\n";
2627 print HTML
'function loadFrame_2() {' . "\n";
2628 print HTML
' document.write("<tr bgcolor=lightgrey<td><h3>Errors</h3></pre></td></tr>");' . "\n";
2629 print HTML
' document.write("Click on the project of interest");' . "\n";
2630 print HTML
' document.close();' . "\n";
2631 print HTML
'} function getStatusInnerHTML(Status) { var StatusInnerHtml;' . "\n";
2632 print HTML
' if (Status == "success") {' . "\n";
2633 print HTML
' StatusInnerHtml = "<em style=color:green>";' . "\n";
2634 print HTML
' } else if (Status == "building") {' . "\n";
2635 print HTML
' StatusInnerHtml = "<em style=color:blue>";' . "\n";
2636 print HTML
' } else if (Status == "error") {' . "\n";
2637 print HTML
' StatusInnerHtml = "<em style=color:red>";' . "\n";
2638 print HTML
' } else {' . "\n";
2639 print HTML
' StatusInnerHtml = "<em style=color:gray>";' . "\n";
2640 print HTML
' };' . "\n";
2641 print HTML
' StatusInnerHtml += Status + "</em>";' . "\n";
2642 print HTML
' return StatusInnerHtml;' . "\n";
2643 print HTML
'} ' . "\n";
2644 print HTML
'function ShowLog(LogFilePath) {' . "\n";
2645 if (defined $html_path) {
2646 print HTML
' top.innerFrame.frames[2].document.location.replace("file://"+LogFilePath);' . "\n";
2648 print HTML
' top.innerFrame.frames[2].document.location.replace(LogFilePath);' . "\n";
2650 print HTML
' top.innerFrame.frames[2].document.close();' . "\n";
2651 print HTML
'};' . "\n";
2652 print HTML
'function FillFrame_1(Module, Message1, Message2) {' . "\n";
2653 print HTML
' var FullUpdate = 1;' . "\n";
2654 print HTML
' if (top.innerFrame.frames[1].document.getElementById("ModuleJobs") != null) {' . "\n";
2655 print HTML
' var ModuleName = top.innerFrame.frames[1].document.getElementById("ModuleJobs").getAttribute(\'name\');' . "\n";
2656 print HTML
' if (Module == ModuleName) FullUpdate = 0;' . "\n";
2657 print HTML
' }' . "\n";
2658 print HTML
' if (FullUpdate) {' . "\n";
2659 print HTML
' top.innerFrame.frames[1].document.write("<h3 align=center>Jobs in module " + Module + ":</h3>");' . "\n";
2660 print HTML
' top.innerFrame.frames[1].document.write("<table id=ModuleJobs name=" + Module + " width=100% bgcolor=white>");' . "\n";
2661 print HTML
' top.innerFrame.frames[1].document.write(" <tr>");' . "\n";
2662 print HTML
' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Status</strong></td>");' . "\n";
2663 print HTML
' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Job</strong></td>");' . "\n";
2664 print HTML
' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Start Time</strong></td>");' . "\n";
2665 print HTML
' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Finish Time</strong></td>");' . "\n";
2666 print HTML
' top.innerFrame.frames[1].document.write(" <td width=* align=center><strong style=color:blue>Client</strong></td>");' . "\n" if ($server_mode);
2667 print HTML
' top.innerFrame.frames[1].document.write(" </tr>");' . "\n";
2668 print HTML
' var dir_info_strings = Message2.split("<br><br>");' . "\n";
2669 print HTML
' for (i = 0; i < dir_info_strings.length; i++) {' . "\n";
2670 print HTML
' var dir_info_array = dir_info_strings[i].split("<br>");' . "\n";
2671 print HTML
' top.innerFrame.frames[1].document.write(" <tr status=" + dir_info_array[0] + ">");' . "\n";
2672 print HTML
' top.innerFrame.frames[1].document.write(" <td align=center>");' . "\n";
2673 print HTML
' top.innerFrame.frames[1].document.write( getStatusInnerHTML(dir_info_array[0]) + " ");' . "\n";
2674 print HTML
' top.innerFrame.frames[1].document.write(" </td>");' . "\n";
2675 print HTML
' if (dir_info_array[4] == "@") {' . "\n";
2676 print HTML
' top.innerFrame.frames[1].document.write(" <td style=white-space:nowrap>" + dir_info_array[1] + "</td>");' . "\n";
2677 print HTML
' } else {' . "\n";
2678 print HTML
' top.innerFrame.frames[1].document.write(" <td><a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a></td>");' . "\n";
2679 print HTML
' };' . "\n";
2680 print HTML
' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[2] + "</td>");' . "\n";
2681 print HTML
' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[3] + "</td>");' . "\n";
2682 print HTML
' top.innerFrame.frames[1].document.write(" <td align=center>" + dir_info_array[5] + "</td>");' . "\n" if ($server_mode);
2683 print HTML
' top.innerFrame.frames[1].document.write(" </tr>");' . "\n";
2684 print HTML
' };' . "\n";
2685 print HTML
' top.innerFrame.frames[1].document.write("</table>");' . "\n";
2686 print HTML
' } else {' . "\n";
2687 print HTML
' var dir_info_strings = Message2.split("<br><br>");' . "\n";
2688 print HTML
' var ModuleRows = top.innerFrame.frames[1].document.getElementById("ModuleJobs").rows;' . "\n";
2689 print HTML
' for (i = 0; i < dir_info_strings.length; i++) {' . "\n";
2690 print HTML
' var dir_info_array = dir_info_strings[i].split("<br>");' . "\n";
2691 print HTML
' var OldStatus = ModuleRows[i + 1].getAttribute(\'status\');' . "\n";
2692 print HTML
' if(dir_info_array[0] != OldStatus) {' . "\n";
2693 print HTML
' var DirectoryInfos = ModuleRows[i + 1].cells;' . "\n";
2694 print HTML
' DirectoryInfos[0].innerHTML = getStatusInnerHTML(dir_info_array[0]) + " ";' . "\n";
2695 print HTML
' if (dir_info_array[4] != "@") {' . "\n";
2696 print HTML
' DirectoryInfos[1].innerHTML = "<a href=\"javascript:top.ShowLog(\'" + dir_info_array[4] + "\')\"); title=\"Show Log\">" + dir_info_array[1] + "</a>";' . "\n";
2697 print HTML
' };' . "\n";
2698 print HTML
' DirectoryInfos[2].innerHTML = dir_info_array[2];' . "\n";
2699 print HTML
' DirectoryInfos[3].innerHTML = dir_info_array[3];' . "\n";
2700 print HTML
' DirectoryInfos[4].innerHTML = dir_info_array[5];' . "\n" if ($server_mode);
2701 print HTML
' };' . "\n";
2702 print HTML
' };' . "\n";
2703 print HTML
' };' . "\n";
2704 print HTML
' top.innerFrame.frames[1].document.close();' . "\n";
2705 print HTML
'};' . "\n";
2706 print HTML
'function Error(Module, Message1, Message2) {' . "\n";
2707 print HTML
' if (Module == \'\') {' . "\n";
2708 print HTML
' if (Message1 != \'\') {' . "\n";
2709 print HTML
' var erroneous_modules = Message1.split("<br>");' . "\n";
2710 print HTML
' var ErrorNumber = erroneous_modules.length;' . "\n";
2712 print HTML
' top.innerFrame.frames[2].document.write("<h3 id=ErroneousModules errors=" + erroneous_modules.length + ">Modules with errors:</h3>");' . "\n";
2713 print HTML
' for (i = 0; i < ErrorNumber; i++) {' . "\n";
2714 print HTML
' var ModuleObj = top.innerFrame.frames[0].document.getElementById(erroneous_modules[i]);' . "\n";
2715 print HTML
' top.innerFrame.frames[2].document.write("<a href=\"");' . "\n";
2716 print HTML
' top.innerFrame.frames[2].document.write(ModuleObj.getAttribute(\'href\'));' . "\n";
2717 print HTML
' top.innerFrame.frames[2].document.write("\"); title=\"");' . "\n";
2718 print HTML
' top.innerFrame.frames[2].document.write("\">" + erroneous_modules[i] + "</a>  ");' . "\n";
2719 print HTML
' };' . "\n";
2720 print HTML
' top.innerFrame.frames[2].document.close();' . "\n";
2721 print HTML
' };' . "\n";
2722 print HTML
' } else {' . "\n";
2723 print HTML
' var ModuleNameObj = top.innerFrame.frames[2].document.getElementById("ModuleErrors");' . "\n";
2724 print HTML
' var OldErrors = null;' . "\n";
2725 print HTML
' var ErrorNumber = Message1.split("<br>").length;' . "\n";
2726 print HTML
' if ((ModuleNameObj != null) && (Module == ModuleNameObj.getAttribute(\'name\')) ) {' . "\n";
2727 print HTML
' OldErrors = ModuleNameObj.getAttribute(\'errors\');' . "\n";
2728 print HTML
' }' . "\n";
2729 print HTML
' if ((OldErrors == null) || (OldErrors != ErrorNumber)) {' . "\n";
2730 print HTML
' top.innerFrame.frames[2].document.write("<h3 id=ModuleErrors errors=" + ErrorNumber + " name=\"" + Module + "\">Errors in module " + Module + ":</h3>");' . "\n";
2731 print HTML
' top.innerFrame.frames[2].document.write(Message1);' . "\n";
2732 print HTML
' top.innerFrame.frames[2].document.close();' . "\n";
2733 print HTML
' }' . "\n";
2734 print HTML
' FillFrame_1(Module, Message1, Message2);' . "\n";
2735 print HTML
' }' . "\n";
2736 print HTML
'}' . "\n";
2737 print HTML
'function updateInnerFrame() {' . "\n";
2738 print HTML
' top.innerFrame.frames[0].document.location.reload();' . "\n";
2739 print HTML
' refreshInfoFrames();' . "\n";
2740 print HTML
'};' . "\n\n";
2742 print HTML
'function setRefreshRate() {' . "\n";
2743 print HTML
' RefreshRate = document.Formular.rate.value;' . "\n";
2744 print HTML
' if (!isNaN(RefreshRate * 1)) {' . "\n";
2745 print HTML
' top.frames[0].clearInterval(IntervalID);' . "\n";
2746 print HTML
' IntervalID = top.frames[0].setInterval("updateInnerFrame()", RefreshRate * 1000);' . "\n";
2747 print HTML
' };' . "\n";
2748 print HTML
'};' . "\n";
2750 print HTML
'function initFrames() {' . "\n";
2751 print HTML
' var urlquery = location.href.split("?");' . "\n";
2752 print HTML
' if (urlquery.length == 1) {' . "\n";
2753 print HTML
' document.write("<html><head><TITLE id=MainTitle>' . $ENV{INPATH
} .'</TITLE>");' . "\n";
2754 print HTML
' document.write(" <frameset rows=\"12%,88%\">");' . "\n";
2755 print HTML
' document.write(" <frame name=\"topFrame\" src=\"" + urlquery + "?initTop\"/>");' . "\n";
2756 print HTML
' document.write(" <frame name=\"innerFrame\" src=\"" + urlquery + "?initInnerPage\"/>");' . "\n";
2757 print HTML
' document.write(" </frameset>");' . "\n";
2758 print HTML
' document.write("</head></html>");' . "\n";
2759 print HTML
' } else if (urlquery[1].substring(0,7) == "initTop") {' . "\n";
2760 print HTML
' var urlquerycontent = urlquery[1].split("=");' . "\n";
2761 print HTML
' var UpdateRate = 10' . "\n";
2762 print HTML
' if (urlquerycontent.length > 2) {' . "\n";
2763 print HTML
' if (isNaN(urlquerycontent[2] * 1)) {' . "\n";
2764 print HTML
' alert(urlquerycontent[2] + " is not a number. Ignored.");' . "\n";
2765 print HTML
' } else {' . "\n";
2766 print HTML
' UpdateRate = urlquerycontent[2];' . "\n";
2767 print HTML
' };' . "\n";
2768 print HTML
' };' . "\n";
2769 print HTML
' document.write("<html><body>");' . "\n";
2770 print HTML
' document.write("<h3 align=center>Build process progress status</h3>");' . "\n";
2771 print HTML
' document.write("<div align=\"right\">");' . "\n";
2772 print HTML
' document.write(" <table border=\"0\"> <tr>");' . "\n";
2773 print HTML
' document.write("<td>Refresh rate(sec):</td>");' . "\n";
2774 print HTML
' document.write("<th>");' . "\n";
2775 print HTML
' document.write("<FORM name=\"Formular\" onsubmit=\"setRefreshRate()\">");' . "\n";
2776 print HTML
' document.write("<input type=\"hidden\" name=\"initTop\" value=\"\"/>");' . "\n";
2777 print HTML
' document.write("<input type=\"text\" id=\"RateValue\" name=\"rate\" autocomplete=\"off\" value=\"" + UpdateRate + "\" size=\"1\"/>");' . "\n";
2778 print HTML
' document.write("<input type=\"submit\" value=\"OK\">");' . "\n";
2779 print HTML
' document.write("</FORM>");' . "\n";
2780 print HTML
' document.write("</th></tr></table>");' . "\n";
2781 print HTML
' document.write("</div>");' . "\n";
2782 print HTML
' document.write(" </frameset>");' . "\n";
2783 print HTML
' document.write("</body></html>");' . "\n";
2784 print HTML
' top.frames[0].clearInterval(IntervalID);' . "\n";
2785 print HTML
' IntervalID = top.frames[0].setInterval("updateInnerFrame()", UpdateRate * 1000);' . "\n";
2786 print HTML
' } else if (urlquery[1] == "initInnerPage") {' . "\n";
2787 print HTML
' document.write("<html><head>");' . "\n";
2788 print HTML
' document.write(\' <frameset rows="80%,20%\">\');' . "\n";
2789 print HTML
' document.write(\' <frameset cols="70%,30%">\');' . "\n";
2790 print HTML
' document.write(\' <frame src="\');' . "\n";
2791 print HTML
' document.write(urlquery[0]);' . "\n";
2792 print HTML
' document.write(\'?initFrame0"/>\');' . "\n";
2793 print HTML
' document.write(\' <frame src="\');' . "\n";
2794 print HTML
' document.write(urlquery[0]);' . "\n";
2795 print HTML
' document.write(\'?initFrame1"/>\');' . "\n";
2796 print HTML
' document.write(\' </frameset>\');' . "\n";
2797 print HTML
' document.write(\' <frame src="\');' . "\n";
2798 print HTML
' document.write(urlquery[0]);' . "\n";
2799 print HTML
' document.write(\'?initFrame2"/>\');' . "\n";
2800 print HTML
' document.write(\' </frameset>\');' . "\n";
2801 print HTML
' document.write("</head></html>");' . "\n";
2802 print HTML
' } else {' . "\n";
2803 print HTML
' if (urlquery[1] == "initFrame0" ) {' . "\n";
2804 print HTML
' loadFrame_0();' . "\n";
2805 print HTML
' } else if (urlquery[1] == "initFrame1" ) { ' . "\n";
2806 print HTML
' loadFrame_1();' . "\n";
2807 print HTML
' } else if (urlquery[1] == "initFrame2" ) {' . "\n";
2808 print HTML
' loadFrame_2();' . "\n";
2809 print HTML
' }' . "\n";
2810 print HTML
' };' . "\n";
2811 print HTML
'};' . "\n";
2812 print HTML
'</script><noscript>Your browser doesn\'t support JavaScript!</noscript></head></html>' . "\n";
2814 rename_file
($temp_html_file, $html_file);
2817 sub get_local_time_line
{
2818 my $epoch_time = shift;
2819 my $local_time_line;
2822 @time_array = localtime($epoch_time);
2823 $local_time_line = sprintf("%02d:%02d:%02d", $time_array[2], $time_array[1], $time_array[0]);
2825 $local_time_line = '-';
2827 return $local_time_line;
2830 sub get_dirs_info_line
{
2832 my $dirs_info_line = $jobs_hash{$job}->{STATUS
} . '<br>';
2834 my $log_path_string;
2835 $dirs_info_line .= $jobs_hash{$job}->{SHORT_NAME
} . '<br>';
2836 $dirs_info_line .= get_local_time_line
($jobs_hash{$job}->{START_TIME
}) . '<br>';
2837 $dirs_info_line .= get_local_time_line
($jobs_hash{$job}->{FINISH_TIME
}) . '<br>';
2838 if ($jobs_hash{$job}->{STATUS
} eq 'waiting' || (!-f
$jobs_hash{$job}->{LONG_LOG_PATH
})) {
2839 $dirs_info_line .= '@';
2841 if (defined $html_path) {
2842 $log_path_string = $jobs_hash{$job}->{LONG_LOG_PATH
};
2844 $log_path_string = $jobs_hash{$job}->{LOG_PATH
};
2846 $log_path_string =~ s/\\/\//g
;
2847 $dirs_info_line .= $log_path_string;
2849 $dirs_info_line .= '<br>';
2850 $dirs_info_line .= $jobs_hash{$job}->{CLIENT
} . '<br>' if ($server_mode);
2851 return $dirs_info_line;
2856 my $module_info_hash = $html_info{$module};
2857 my $dirs = $$module_info_hash{DIRS
};
2858 my $dirs_number = scalar @
$dirs;
2859 my $dirs_info_line = '\'';
2861 my %dirs_sorted_by_order = ();
2863 $dirs_sorted_by_order{$jobs_hash{$_}->{BUILD_NUMBER
}} = $_;
2865 foreach (sort {$a <=> $b} keys %dirs_sorted_by_order) {
2866 $dirs_info_line .= get_dirs_info_line
($dirs_sorted_by_order{$_}) . '<br>';
2869 return(undef, undef, 0, 0, 0, '-');
2870 # $dirs_info_line .= 'No information available yet';
2872 $dirs_info_line =~ s/(<br>)*$//o;
2873 $dirs_info_line .= '\'';
2874 $dirs = $$module_info_hash{SUCCESSFUL
};
2875 my $successful_number = scalar @
$dirs;
2876 $dirs = $$module_info_hash{ERRORFUL
};
2877 my $errorful_number = scalar @
$dirs;
2878 my $errors_info_line = '\'';
2879 if ($errorful_number) {
2880 $errors_info_line .= $_ . '<br>' foreach (@
$dirs);
2882 $errors_info_line .= 'No errors';
2884 $errors_info_line .= '\'';
2885 # if (defined $full_info) {
2886 my $time_line = get_time_line
($$module_info_hash{BUILD_TIME
});
2887 my ($successes_percent, $errors_percent) = get_progress_percentage
($dirs_number, $successful_number, $errorful_number);
2888 return($errors_info_line, $dirs_info_line, $errorful_number, $successes_percent, $errors_percent, $time_line);
2890 # return($errors_info_line, $dirs_info_line, $errorful_number);
2896 my $seconds = shift;
2897 my $hours = $seconds/3600;
2898 my $minits = ($seconds/60)%60;
2899 $seconds -= ($hours*3600 + $minits*60);
2900 return(sprintf("%02d\:%02d\:%02d" , $hours, $minits, $seconds));
2903 sub get_progress_percentage
{
2905 my ($dirs_number, $successful_number, $errorful_number) = @_;
2906 return (0 ,0) if (!$dirs_number);
2907 my $errors_percent = ($errorful_number * 100)/ $dirs_number;
2908 my $successes_percent;
2909 if ($dirs_number == ($successful_number + $errorful_number)) {
2910 $successes_percent = 100 - $errors_percent;
2912 $successes_percent = ($successful_number * 100)/ $dirs_number;
2914 return ($successes_percent, $errors_percent);
2918 # This procedure stores the dmake result in %html_info
2920 sub html_store_job_info
{
2922 my ($deps_hash, $build_dir, $error_code) = @_;
2923 my $force_update = 0;
2924 if ($build_dir =~ /(\s)/o && (defined $error_code)) {
2925 $force_update++ if (!children_number
());
2927 my $module = $module_by_hash{$deps_hash};
2928 my $module_info_hash = $html_info{$module};
2930 if (defined $error_code) {
2931 $jobs_hash{$build_dir}->{FINISH_TIME
} = time();
2932 $$module_info_hash{BUILD_TIME
} += $jobs_hash{$build_dir}->{FINISH_TIME
} - $jobs_hash{$build_dir}->{START_TIME
};
2934 $jobs_hash{$build_dir}->{STATUS
} = 'error';
2935 $dmake_array = $$module_info_hash{ERRORFUL
};
2936 $build_dir =~ s/\\/\//g
;
2937 $modules_with_errors{$module}++;
2939 $jobs_hash{$build_dir}->{STATUS
} = 'success';
2940 $dmake_array = $$module_info_hash{SUCCESSFUL
};
2942 push (@
$dmake_array, $build_dir);
2946 sub start_server_on_port
{
2948 if ($ENV{GUI
} eq 'WNT') {
2949 $socket_obj = new IO
::Socket
::INET
(#LocalAddr => hostname(),
2952 Listen
=> 100); # 100 clients can be on queue, I think it is enough
2954 $socket_obj = new IO
::Socket
::INET
(#LocalAddr => hostname(),
2958 Listen
=> 100); # 100 clients can be on queue, I think it is enough
2960 return('Cannot create socket object') if (!defined $socket_obj);
2961 my $timeout = $socket_obj->timeout($client_timeout);
2962 $socket_obj->autoflush(1);
2963 print "SERVER started on port $port\n";
2967 sub accept_connection
{
2968 my $new_socket_obj = undef;
2970 $new_socket_obj = $socket_obj->accept();
2971 if (!$new_socket_obj) {
2972 print "Timeout on incoming connection\n";
2973 check_client_jobs
();
2975 } while (!$new_socket_obj);
2976 return $new_socket_obj;
2979 sub check_client_jobs
{
2980 foreach (keys %clients_times) {
2981 if (time - $clients_times{$_} > $client_timeout) {
2982 print "Client's $_ Job: \"$clients_jobs{$_}\" apparently got lost...\n";
2983 print "Scheduling for rebuild...\n";
2984 print "You might need to check the $_\n";
2985 $lost_client_jobs{$clients_jobs{$_}}++;
2986 delete $processes_hash{$_};
2987 delete $clients_jobs{$_};
2988 delete $clients_times{$_};
2990 # print time - $clients_times{$_} . "\n";
2996 my @build_queue = (); # array, containing queue of projects
2998 # use port 7890 as default
2999 my $default_port = 7890;
3000 if ($ports_string) {
3001 @server_ports = split( /:/, $ports_string);
3003 @server_ports = ($default_port .. $default_port + 4);
3006 if (scalar @server_ports) {
3007 foreach (@server_ports) {
3008 $error = start_server_on_port
($_);
3010 print STDERR
"port $_: $error\n";
3012 # $SIG{KILL} = \&stop_server;
3013 # $SIG{INT} = \&stop_server;
3014 # $SIG{TERM} = \&stop_server;
3015 # $SIG{QUIT} = \&stop_server;
3020 print_error
('It is impossible to start server on port(s): ' . "@server_ports\n") if ($error);
3023 my $job_string_base = get_job_string_base
();
3025 while ($new_socket_obj = accept_connection
()) {
3026 check_client_jobs
();
3027 # find out who connected
3028 my $client_ipnum = $new_socket_obj->peerhost();
3029 my $client_host = gethostbyaddr(inet_aton
($client_ipnum), AF_INET
);
3030 # print who is connected
3031 # send them a message, close connection
3032 my $client_message = <$new_socket_obj>;
3033 chomp $client_message;
3034 my @client_data = split(/ /, $client_message);
3035 my %client_hash = ();
3036 foreach (@client_data) {
3038 $client_hash{$`} = $';
3040 my $pid = $client_hash{pid} . '@' . $client_host;
3041 if (defined $client_hash{platform}) {
3042 if ($client_hash{platform} ne $ENV{OUTPATH} || (defined $client_hash{osname} && ($^O ne $client_hash{osname}))) {
3043 print $new_socket_obj "Wrong platform";
3044 close($new_socket_obj);
3048 if ($client_hash{result} eq "0") {
3049 # print "$clients_jobs{$pid} succedded on $pid\n";
3051 print "Error $client_hash{result}\n";
3052 if (store_error($pid, $client_hash{result})) {
3053 print $new_socket_obj $job_string_base . $clients_jobs{$pid};
3054 close($new_socket_obj);
3055 $clients_times{$pid} = time;
3059 delete $clients_times{$pid};
3060 clear_from_child($pid);
3061 delete $clients_jobs{$pid};
3062 $verbose_mode && print 'Running processes: ', children_number(), "\n";
3063 # Actually, next 3 strings are only for even distribution
3064 # of clients if there are more than one build server running
3065 print $new_socket_obj 'No job';
3066 close($new_socket_obj);
3070 my @lost_jobs = keys %lost_client_jobs;
3071 if (scalar @lost_jobs) {
3072 $job_string = $lost_jobs[0];
3073 delete $lost_client_jobs{$lost_jobs[0]};
3075 # $job_string = get_job_string(\@build_queue, $pid);
3076 $job_string = get_job_string(\@build_queue);
3079 my $job_dir = $job_jobdir{$job_string};
3080 $processes_hash{$pid} = $job_dir;
3081 $jobs_hash{$job_dir}->{CLIENT} = $pid;
3082 print "$pid got $job_dir\n";
3083 print $new_socket_obj $job_string_base . $job_string;
3084 $clients_jobs{$pid} = $job_string;
3085 $clients_times{$pid} = time;
3086 $children_running = children_number();
3087 $verbose_mode && print 'Running processes: ', $children_running, "\n";
3088 $maximal_processes = $children_running if ($children_running > $maximal_processes);
3090 print $new_socket_obj 'No job';
3092 close($new_socket_obj);
3097 # Procedure returns the part of the job string that is similar for all clients
3099 sub get_job_string_base {
3100 if ($setenv_string) {
3101 return "setenv_string=$setenv_string ";
3103 my $job_string_base = "server_pid=$$ setsolar_cmd=$ENV{SETSOLAR_CMD} ";
3104 $job_string_base .= "source_root=$ENV{SOURCE_ROOT} " if (defined $ENV{SOURCE_ROOT});
3105 $job_string_base .= "updater=$ENV{UPDATER} " if (defined $ENV{UPDATER});
3106 return $job_string_base;
3109 sub get_job_string {
3110 my $build_queue = shift;
3112 my ($job_dir, $dependencies_hash);
3113 if ($BuildAllParents) {
3114 fill_modules_queue($build_queue);
3116 ($job_dir, $dependencies_hash) = pick_jobdir($build_queue);
3117 return '' if (!$job_dir);
3118 $jobs_hash{$job_dir}->{START_TIME} = time();
3119 $jobs_hash{$job_dir}->{STATUS} = 'building';
3120 if ($job_dir =~ /(\s)$pre_job/o) {
3121 do_custom_job($job_dir, $dependencies_hash);
3124 } while (!$job_dir);
3126 $dependencies_hash = \%LocalDepsHash;
3128 $job_dir = PickPrjToBuild(\%LocalDepsHash);
3129 if (!$job_dir && !children_number()) {
3130 cancel_build() if (scalar keys %broken_build);
3133 return '' if (!$job_dir);
3134 $jobs_hash{$job_dir}->{START_TIME} = time();
3135 $jobs_hash{$job_dir}->{STATUS} = 'building';
3136 if ($job_dir =~ /(\s)$pre_job/o) {
3137 # if ($' eq $pre_job) {
3138 do_custom_job($job_dir, $dependencies_hash);
3142 } while (!$job_dir);
3144 $running_children{$dependencies_hash}++;
3145 $folders_hashes{$job_dir} = $dependencies_hash;
3146 my $log_file = $jobs_hash{$job_dir}->{LONG_LOG_PATH};
3147 my $full_job_dir = $job_dir;
3148 if ($job_dir =~ /(\s)/o) {
3150 $job = $deliver_command if ($job eq $post_job);
3151 $full_job_dir = $module_paths{$`};
3153 my $log_dir = File
::Basename
::dirname
($log_file);
3155 chdir $full_job_dir;
3157 system("$perl $mkout");
3159 my $job_string = "job_dir=$full_job_dir job=$job log=$log_file";
3160 $job_jobdir{$job_string} = $job_dir;
3165 my $build_queue = shift;
3167 foreach (@
$build_queue) {
3168 $Prj = $$build_queue[$i];
3169 my $prj_deps_hash = $projects_deps_hash{$Prj};
3170 if (defined $broken_modules_hashes{$prj_deps_hash} && !$ignore) {
3171 push (@broken_modules_names, $Prj);
3172 splice (@
$build_queue, $i, 1);
3175 $only_dependent = 0;
3177 $running_children{$prj_deps_hash} = 0 if (!defined $running_children{$prj_deps_hash});
3178 $child_nick = PickPrjToBuild
($prj_deps_hash);
3180 return ($child_nick, $prj_deps_hash);
3182 if ($no_projects && !$running_children{$prj_deps_hash}) {
3183 if (!defined $broken_modules_hashes{$prj_deps_hash} || $ignore)
3185 RemoveFromDependencies
($Prj, \
%global_deps_hash);
3186 $build_is_finished{$Prj}++;
3187 splice (@
$build_queue, $i, 1);
3195 sub fill_modules_queue
{
3196 my $build_queue = shift;
3198 while ($Prj = PickPrjToBuild
(\
%global_deps_hash)) {
3199 push @
$build_queue, $Prj;
3200 $projects_deps_hash{$Prj} = {};
3201 get_deps_hash
($Prj, $projects_deps_hash{$Prj});
3202 my $info_hash = $html_info{$Prj};
3203 $$info_hash{DIRS
} = check_deps_hash
($projects_deps_hash{$Prj}, $Prj);
3204 $module_by_hash{$projects_deps_hash{$Prj}} = $Prj;
3206 if (!$Prj && !children_number
() && (!scalar @
$build_queue)) {
3207 cancel_build
() if (scalar keys %broken_build);