PageRenderTime 95ms CodeModel.GetById 54ms RepoModel.GetById 0ms app.codeStats 1ms

/solenv/bin/build.pl

https://bitbucket.org/markjenkins/libreoffice_ubuntu-debian-fixes
Perl | 2926 lines | 2632 code | 129 blank | 165 comment | 363 complexity | a972cdb647879201cbcc94c1d08a6000 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause-No-Nuclear-License-2014

Large files files are truncated, but you can click here to view the full file

  1. :
  2. eval 'exec perl -S $0 ${1+"$@"}'
  3. if 0;
  4. #*************************************************************************
  5. #
  6. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  7. #
  8. # Copyright 2000, 2010 Oracle and/or its affiliates.
  9. #
  10. # OpenOffice.org - a multi-platform office productivity suite
  11. #
  12. # This file is part of OpenOffice.org.
  13. #
  14. # OpenOffice.org is free software: you can redistribute it and/or modify
  15. # it under the terms of the GNU Lesser General Public License version 3
  16. # only, as published by the Free Software Foundation.
  17. #
  18. # OpenOffice.org is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. # GNU Lesser General Public License version 3 for more details
  22. # (a copy is included in the LICENSE file that accompanied this code).
  23. #
  24. # You should have received a copy of the GNU Lesser General Public License
  25. # version 3 along with OpenOffice.org. If not, see
  26. # <http://www.openoffice.org/license.html>
  27. # for a copy of the LGPLv3 License.
  28. #
  29. #*************************************************************************
  30. #
  31. # build - build entire project
  32. #
  33. use strict;
  34. use Config;
  35. use POSIX;
  36. use Cwd qw (cwd);
  37. use File::Path;
  38. use File::Temp qw(tmpnam tempdir);
  39. use File::Find;
  40. use Socket;
  41. use IO::Socket::INET;
  42. use IO::Select;
  43. use Fcntl;
  44. use POSIX qw(:errno_h);
  45. use Sys::Hostname;
  46. use IPC::Open3;
  47. use lib ("$ENV{SOLARENV}/bin/modules");
  48. use SourceConfig;
  49. use RepositoryHelper;
  50. use Cwd 'chdir';
  51. my $in_so_env = 0;
  52. if (defined $ENV{COMMON_ENV_TOOLS}) {
  53. unshift(@INC, "$ENV{COMMON_ENV_TOOLS}/modules");
  54. $in_so_env++;
  55. };
  56. my $verbose_mode = 0;
  57. if (defined $ENV{verbose} || defined $ENV{VERBOSE}) {
  58. $verbose_mode = ($ENV{verbose} =~ /^t\S*$/i);
  59. }
  60. ### for XML file format
  61. eval { require XMLBuildListParser; import XMLBuildListParser; };
  62. my $enable_xml = 0;
  63. my @modes_array = ();
  64. if (!$@) {
  65. $enable_xml = 1;
  66. @modes_array = split('\s' , $ENV{BUILD_TYPE});
  67. };
  68. #### script id #####
  69. #########################
  70. # #
  71. # Global Variables #
  72. # #
  73. #########################
  74. my $modules_number++;
  75. my $perl = 'perl';
  76. my $remove_command = 'rm -rf';
  77. my $nul = '> /dev/null';
  78. my $processes_to_run = 0;
  79. # delete $pid when not needed
  80. my %projects_deps_hash = (); # hash of projects with no dependencies,
  81. # that could be built now
  82. my %broken_build = (); # hash of hashes of the modules,
  83. # where build was broken (error occurred)
  84. my %folders_hashes = ();
  85. my %running_children = ();
  86. my $dependencies_hash = 0;
  87. my $cmd_file = '';
  88. my $build_all_parents = 0;
  89. my $show = 0;
  90. my $checkparents = 0;
  91. my $deliver = 0;
  92. my $pre_custom_job = '';
  93. my $custom_job = '';
  94. my $post_custom_job = '';
  95. my %local_deps_hash = ();
  96. my %path_hash = ();
  97. my %platform_hash = ();
  98. my %alive_dependencies = ();
  99. my %global_deps_hash = (); # hash of dependencies of the all modules
  100. my %global_deps_hash_backup = (); # backup hash of external dependencies of the all modules
  101. my %module_deps_hash_backup = (); # backup hash of internal dependencies for each module
  102. my @broken_modules_names = (); # array of modules, which cannot be built further
  103. my @dmake_args = ();
  104. my %dead_parents = ();
  105. my $initial_module = '';
  106. my $all_dependent = 1; # a flag indicating if the hash has independent keys
  107. my $build_from_with_branches = '';
  108. my $build_all_cont = '';
  109. my $build_since = '';
  110. my $dlv_switch = '';
  111. my $child = 0;
  112. my %processes_hash = ();
  113. my %module_announced = ();
  114. my $ignore = '';
  115. my $html = '';
  116. my @ignored_errors = ();
  117. my %incompatibles = ();
  118. my %skip_modules = ();
  119. my %exclude_branches = ();
  120. my $only_platform = ''; # the only platform to prepare
  121. my $only_common = ''; # the only common output tree to delete when preparing
  122. my %build_modes = ();
  123. my $maximal_processes = 0; # the max number of the processes run
  124. my %modules_types = (); # modules types ('mod', 'img', 'lnk') hash
  125. my %platforms = (); # platforms available or being working with
  126. my %platforms_to_copy = (); # copy output trees for the platforms when --prepare
  127. my $tmp_dir = get_tmp_dir(); # temp directory for checkout and other actions
  128. my %build_list_paths = (); # build lists names
  129. my %build_lists_hash = (); # hash of arrays $build_lists_hash{$module} = \($path, $xml_list_object)
  130. my $pre_job = 'announce'; # job to add for not-single module build
  131. my $post_job = ''; # -"-
  132. my @warnings = (); # array of warnings to be shown at the end of the process
  133. my @errors = (); # array of errors to be shown at the end of the process
  134. my %html_info = (); # hash containing all necessary info for generating of html page
  135. my %module_by_hash = (); # hash containing all modules names as values and correspondent hashes as keys
  136. my %build_in_progress = (); # hash of modules currently being built
  137. my %build_is_finished = (); # hash of already built modules
  138. my %modules_with_errors = (); # hash of modules with build errors
  139. my %build_in_progress_shown = (); # hash of modules being built,
  140. # and shown last time (to keep order)
  141. my $build_time = time;
  142. my %jobs_hash = ();
  143. my $html_path = undef;
  144. my $build_finished = 0;
  145. my $html_file = '';
  146. my %had_error = (); # hack for mysterious windows problems - try run dmake 2 times if first time there was an error
  147. my $mkout = correct_path("$ENV{SOLARENV}/bin/mkout.pl");
  148. my %weights_hash = (); # hash contains info about how many modules are dependent from one module
  149. my $stop_build_on_error = 0; # for multiprocessing mode: do not build further module if there is an error
  150. my $interactive = 0; # for interactive mode... (for testing purpose enabled by default)
  151. my $parent_process = 1;
  152. my @server_ports = ();
  153. my $html_port = 0;
  154. my $html_socket_obj = undef; # socket object for server
  155. my $client_timeout = 0; # time for client to build (in sec)...
  156. # The longest time period after that
  157. # the server considered as an error/client crash
  158. my $reschedule_queue = 0;
  159. my %module_build_queue = ();
  160. my %reversed_dependencies = ();
  161. my %module_paths = (); # hash with absolute module paths
  162. my %active_modules = ();
  163. my $finished_children = 0;
  164. my $debug = 0;
  165. my %module_deps_hash_pids = ();
  166. my @argv = @ARGV;
  167. my $zenity_pid = 0;
  168. my $zenity_in = '';
  169. my $zenity_out = '';
  170. my $zenity_err = '';
  171. my $last_message_time = 0;
  172. my $verbose = 0;
  173. my @modules_built = ();
  174. my $deliver_command = "deliver.pl";
  175. my %prj_platform = ();
  176. my $check_error_string = '';
  177. my $dmake = '';
  178. my $dmake_args = '';
  179. my $echo = '';
  180. my $new_line = "\n";
  181. my $incompatible = 0;
  182. my $local_host_ip = 'localhost';
  183. my $tail_build_modules_mk = "$ENV{SOLARENV}/gbuild/tail_build_modules.mk";
  184. my $tail_build_module_dir = $ENV{"SRCDIR"};
  185. my $tail_build_prj = "tail_build";
  186. my $cross_tail_build_prj = "cross_tail_build";
  187. my $total_modules = 0;
  188. ### main ###
  189. get_options();
  190. zenity_open();
  191. zenity_tooltip("Starting build.");
  192. get_build_modes();
  193. my %deliver_env = ();
  194. my $workspace_path = get_workspace_path(); # This also sets $initial_module
  195. my $build_error_log = Cwd::realpath(correct_path($workspace_path)) ."/build_error.log";
  196. my $workdir = $ENV{WORKDIR};
  197. my $source_config = SourceConfig -> new($workspace_path);
  198. check_partial_gnumake_build($initial_module);
  199. system("rm -f $build_error_log");
  200. if ($html) {
  201. if (defined $html_path) {
  202. $html_file = correct_path($html_path . '/' . $ENV{INPATH}. '.build.html');
  203. } else {
  204. my $log_directory = Cwd::realpath(correct_path($workspace_path . '/..')) . '/log';
  205. if ((!-d $log_directory) && (!mkdir($log_directory))) {
  206. print_error("Cannot create $log_directory for writing html file\n");
  207. };
  208. $html_file = $log_directory . '/' . $ENV{INPATH}. '.build.html';
  209. print "\nPath to html status page: $html_file\n";
  210. };
  211. };
  212. get_module_and_buildlist_paths();
  213. $deliver_command .= ' -verbose' if ($html || $verbose);
  214. $deliver_command .= ' '. $dlv_switch if ($dlv_switch);
  215. $ENV{mk_tmp}++;
  216. get_commands();
  217. unlink ($cmd_file);
  218. if ($cmd_file) {
  219. if (open (CMD_FILE, ">>$cmd_file")) {
  220. select CMD_FILE;
  221. $echo = 'echo ';
  222. if ($ENV{GUI_FOR_BUILD} ne 'UNX') {
  223. $new_line = "echo.\n";
  224. print "\@$echo off\npushd\n";
  225. } else {
  226. $new_line = $echo."\"\"\n";
  227. };
  228. } else {
  229. print_error ("Cannot open file $cmd_file");
  230. };
  231. };
  232. print $new_line;
  233. get_server_ports();
  234. start_interactive() if ($interactive);
  235. if ($checkparents) {
  236. get_parent_deps( $initial_module, \%global_deps_hash );
  237. } else {
  238. build_all();
  239. }
  240. if (scalar keys %broken_build) {
  241. cancel_build();
  242. };
  243. print_warnings();
  244. if (scalar keys %active_modules) {
  245. foreach (keys %dead_parents) {
  246. delete $dead_parents{$_} if (!defined $active_modules{$_});
  247. };
  248. };
  249. if (scalar keys %dead_parents) {
  250. print $new_line.$new_line;
  251. print $echo."WARNING! Project(s):\n";
  252. foreach (keys %dead_parents) {
  253. print $echo."$_\n";
  254. };
  255. print $new_line;
  256. print $echo."not found and couldn't be built. dependencies on that module(s) ignored. Maybe you should correct build lists.\n";
  257. print $new_line;
  258. do_exit(1) if ($checkparents);
  259. };
  260. if (($ENV{GUI_FOR_BUILD} ne 'UNX') && $cmd_file) {
  261. print "popd\n";
  262. };
  263. $ENV{mk_tmp} = '';
  264. if ($cmd_file) {
  265. close CMD_FILE;
  266. print STDOUT "Script $cmd_file generated\n";
  267. };
  268. if ($ignore && scalar @ignored_errors) {
  269. print STDERR "\nERROR: next directories could not be built:\n";
  270. foreach (@ignored_errors) {
  271. print STDERR "\t$_\n";
  272. };
  273. print STDERR "\nERROR: please check these directories and build the corresponding module(s) anew!!\n\n";
  274. do_exit(1);
  275. };
  276. do_exit(0);
  277. #########################
  278. # #
  279. # Procedures #
  280. # #
  281. #########################
  282. sub print_warnings {
  283. if (scalar @warnings) {
  284. print STDERR "\nWARNING(S):\n";
  285. print STDERR $_ foreach (@warnings);
  286. };
  287. };
  288. sub rename_file {
  289. my ($old_file_name, $new_file_name, $throw_error) = @_;
  290. if(-e $old_file_name) {
  291. rename($old_file_name, $new_file_name) or system("mv", $old_file_name, $new_file_name);
  292. if (-e $old_file_name) {
  293. system("rm -rf $old_file_name") if (!unlink $old_file_name);
  294. };
  295. } elsif ($throw_error) {
  296. print_error("No such file $old_file_name");
  297. };
  298. };
  299. sub start_interactive {
  300. my $pid = open(HTML_PIPE, "-|");
  301. print "Pipe is open\n";
  302. if ($pid) { # parent
  303. # make file handle non-blocking
  304. my $flags = '';
  305. fcntl(HTML_PIPE, F_GETFL, $flags);
  306. $flags |= O_NONBLOCK;
  307. fcntl(HTML_PIPE, F_SETFL, $flags);
  308. } else { # child
  309. $parent_process = 0;
  310. start_html_listener();
  311. };
  312. };
  313. sub start_html_listener {
  314. $html_port = $server_ports[$#server_ports];
  315. do {
  316. $html_port++
  317. } while (start_server_on_port($html_port, \$html_socket_obj));
  318. print "html_port:$html_port html_socket_obj: $html_socket_obj\n";
  319. my $new_socket_obj;
  320. do {
  321. $new_socket_obj = accept_html_connection();
  322. if (defined $new_socket_obj) {
  323. my $html_message;
  324. $html_message = <$new_socket_obj>;
  325. chomp $html_message;
  326. print $html_message . "\n";
  327. my $socket_message = '';
  328. for my $action ('rebuild', 'delete') {
  329. if ($html_message =~ /$action=(\S+)/) {
  330. print $new_socket_obj "Module $1 is scheduled for $action";
  331. };
  332. };
  333. close($new_socket_obj);
  334. } else {
  335. sleep(10);
  336. };
  337. } while(1);
  338. };
  339. sub get_html_orders {
  340. return if (!$interactive);
  341. my $buffer_size = 1024;
  342. my $buffer;
  343. my $rv;
  344. my $full_buffer = '';
  345. my %modules_to_rebuild = ();
  346. my %modules_to_delete = ();
  347. while ($rv = sysread(HTML_PIPE, $buffer, $buffer_size)) {
  348. $full_buffer .= $buffer;
  349. };
  350. my @html_messages = split(/\n/, $full_buffer);
  351. foreach (@html_messages) {
  352. if (/^html_port:(\d+)/) {
  353. $html_port = $1;
  354. print "Html port is: $html_port\n";
  355. next;
  356. };# GET /rebuild=officenames HTTP/1.0
  357. print "Message: $_\n";
  358. chomp;
  359. if (/GET\s+\/delete=(\S+)[:(\S+)]*\s*HTTP/) {
  360. $modules_to_delete{$1} = $2;
  361. print "$1 scheduled for removal from build for \n";
  362. }
  363. if (/GET\s+\/rebuild=(\S+)[:(\S+)]*\s*HTTP/) {
  364. if (defined $global_deps_hash{$1}) {
  365. print "!!! /tarModule $1 has not been built. Html order ignored\n";
  366. } else {
  367. $modules_to_rebuild{$1} = $2;
  368. print "Scheduled $1 for rebuild\n";
  369. }
  370. }
  371. };
  372. if (scalar keys %modules_to_delete) {
  373. $reschedule_queue++;
  374. schedule_delete(\%modules_to_delete);
  375. generate_html_file();
  376. };
  377. if (scalar keys %modules_to_rebuild) {
  378. $reschedule_queue++;
  379. schedule_rebuild(\%modules_to_rebuild);
  380. generate_html_file();
  381. };
  382. };
  383. sub schedule_delete {
  384. my $modules_to_delete = shift;
  385. foreach (keys %$modules_to_delete) {
  386. print "Schedule module $_ for delete\n";
  387. delete ($global_deps_hash{$_});
  388. delete ($global_deps_hash_backup{$_});
  389. if (scalar keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}}) {
  390. kill 9, keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}};
  391. handle_dead_children(0);
  392. };
  393. remove_from_dependencies($_, \%global_deps_hash);
  394. remove_from_dependencies($_, \%global_deps_hash_backup);
  395. delete $reversed_dependencies{$_};
  396. delete $build_is_finished{$_} if defined $build_is_finished{$_};
  397. delete $modules_with_errors{$_} if defined $modules_with_errors{$_};
  398. delete $module_announced{$_} if defined $module_announced{$_};
  399. delete $html_info{$_} if defined $html_info{$_};
  400. delete $projects_deps_hash{$_} if defined $projects_deps_hash{$_};
  401. };
  402. };
  403. sub schedule_rebuild {
  404. my $modules_to_rebuild = shift;
  405. foreach (keys %$modules_to_rebuild) {
  406. if (defined $$modules_to_rebuild{$_}) {
  407. print "Schedule directory for rebuild";
  408. } else {
  409. print "Schedule complete $_ module for rebuild\n";
  410. if (scalar keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}}) {
  411. kill 9, keys %{$module_deps_hash_pids{$projects_deps_hash{$_}}};
  412. handle_dead_children(0);
  413. };
  414. delete $build_is_finished{$_} if defined $build_is_finished{$_};
  415. delete $modules_with_errors{$_} if defined $modules_with_errors{$_};
  416. delete $module_announced{$_};
  417. initialize_html_info($_);
  418. foreach my $waiter (keys %{$reversed_dependencies{$_}}) {
  419. # for rebuild_all_dependent - refacture "if" condition
  420. ${$global_deps_hash{$waiter}}{$_}++ if (!defined $build_is_finished{$waiter});
  421. };
  422. delete $projects_deps_hash{$_} if defined $projects_deps_hash{$_};
  423. my %single_module_dep_hash = ();
  424. foreach my $module (keys %{$global_deps_hash_backup{$_}}) {
  425. if (defined ${$global_deps_hash_backup{$_}}{$module} && (!defined $build_is_finished{$module})) {
  426. $single_module_dep_hash{$module}++;
  427. };
  428. };
  429. $global_deps_hash{$_} = \%single_module_dep_hash;
  430. };
  431. };
  432. };
  433. #
  434. # procedure retrieves build list path
  435. # (all possibilities are taken into account)
  436. #
  437. sub get_build_list_path {
  438. my $module = shift;
  439. return $build_list_paths{$module} if (defined $build_list_paths{$module});
  440. return $build_list_paths{$module} if (defined $build_list_paths{$module});
  441. my $possible_dir_path = $module_paths{$module}.'/prj/';
  442. if (-d $possible_dir_path)
  443. {
  444. my $possible_build_list_path = correct_path($possible_dir_path . "build.lst");
  445. if (-f $possible_build_list_path)
  446. {
  447. $build_list_paths{$module} = $possible_build_list_path;
  448. return $possible_build_list_path;
  449. };
  450. print_error("There's no build.lst for $module");
  451. };
  452. $dead_parents{$module}++;
  453. return $build_list_paths{$module};
  454. };
  455. #
  456. # Get dependencies hash of the current and all parent projects
  457. #
  458. sub get_parent_deps {
  459. my $prj_dir = shift;
  460. my $deps_hash = shift;
  461. my @unresolved_parents = ($prj_dir);
  462. my %skipped_branches = ();
  463. while (my $module = pop(@unresolved_parents)) {
  464. next if (defined $$deps_hash{$module});
  465. my %parents_deps_hash = ();
  466. foreach (get_parents_array($module)) {
  467. if (defined $exclude_branches{$_}) {
  468. $skipped_branches{$_}++;
  469. next;
  470. };
  471. $parents_deps_hash{$_}++;
  472. }
  473. $$deps_hash{$module} = \%parents_deps_hash;
  474. foreach my $parent (keys %parents_deps_hash) {
  475. if (!defined($$deps_hash{$parent}) && (!defined $exclude_branches{$module})) {
  476. push (@unresolved_parents, $parent);
  477. };
  478. };
  479. };
  480. check_deps_hash($deps_hash);
  481. foreach (keys %skipped_branches) {
  482. print $echo . "Skipping module's $_ branch\n";
  483. delete $exclude_branches{$_};
  484. };
  485. my @missing_branches = keys %exclude_branches;
  486. if (scalar @missing_branches) {
  487. print_error("For $prj_dir branche(s): \"@missing_branches\" not found\n");
  488. };
  489. };
  490. sub store_weights {
  491. my $deps_hash = shift;
  492. foreach (keys %$deps_hash) {
  493. foreach my $module_deps_hash ($$deps_hash{$_}) {
  494. foreach my $dependency (keys %$module_deps_hash) {
  495. $weights_hash{$dependency}++;
  496. };
  497. };
  498. };
  499. };
  500. #
  501. # This procedure builds comlete dependency for each module, ie if the deps look like:
  502. # mod1 -> mod2 -> mod3 -> mod4,mod5,
  503. # than mod1 get mod3,mod4,mod5 as eplicit list of deps, not only mod2 as earlier
  504. #
  505. sub expand_dependencies {
  506. my $deps_hash = shift;
  507. foreach my $module1 (keys %$deps_hash) {
  508. foreach my $module2 (keys %$deps_hash) {
  509. next if ($module1 eq $module2);
  510. if (defined ${$$deps_hash{$module2}}{$module1}) {
  511. ${$$deps_hash{$module2}}{$_}++ foreach (keys %{$$deps_hash{$module1}})
  512. };
  513. };
  514. };
  515. };
  516. #
  517. # Gets list of tail_build modules.
  518. #
  519. sub get_tail_build_modules {
  520. my $tail_build_prj = shift;
  521. my $make = $ENV{'GNUMAKE'};
  522. my $build_type = $ENV{'BUILD_TYPE'};
  523. my $tail_build_mk = "$tail_build_module_dir/Module_$tail_build_prj.mk";
  524. my $modules_str = `$make --no-print-directory -r -f $tail_build_modules_mk get_modules TAIL_BUILD_MK=$tail_build_mk BUILD_TYPE='$build_type'`;
  525. chomp $modules_str;
  526. my %modules = ();
  527. foreach my $module (split /\s+/, $modules_str) {
  528. $modules{$module} = 1;
  529. }
  530. return %modules;
  531. }
  532. sub _filter_tail_build_dependencies {
  533. my $deps_hash = shift;
  534. my $tail_build_prj = shift;
  535. if (!defined $$deps_hash{$tail_build_prj}) {
  536. # nothing to do
  537. return;
  538. }
  539. my %tail_build_modules = get_tail_build_modules($tail_build_prj);
  540. # first remove tail_build modules from deps.
  541. foreach my $prj (keys %tail_build_modules) {
  542. if (defined $$deps_hash{$prj}) {
  543. delete $$deps_hash{$prj};
  544. }
  545. }
  546. # do the actual replacement
  547. foreach my $prj (keys %$deps_hash) {
  548. my @tail_build_deps = ();
  549. my $deps = $$deps_hash{$prj};
  550. # remove deps. that are in tail_build
  551. foreach my $dep (keys %$deps) {
  552. if (defined $tail_build_modules{$dep}) {
  553. print "$prj depends on $tail_build_prj\[$dep\]\n";
  554. push @tail_build_deps, $dep;
  555. delete $$deps{$dep};
  556. }
  557. }
  558. # insert dep. on tail_build, if necessary
  559. if (@tail_build_deps && !defined $$deps{$tail_build_prj}) {
  560. $$deps{$tail_build_prj} = 1;
  561. }
  562. }
  563. }
  564. #
  565. # Replaces all deps on modules from tail_build by dep on tail_build
  566. # itself. I.e., if a module foo depends on (sal, sfx2, svx) and (sfx2,
  567. # svx) are in tail_build, foo will be depending on (sal, tail_build).
  568. #
  569. # Works on cross_tail_build too, in case of cross-compilation.
  570. #
  571. sub filter_tail_build_dependencies {
  572. my $deps_hash = shift;
  573. _filter_tail_build_dependencies($deps_hash, $tail_build_prj);
  574. _filter_tail_build_dependencies($deps_hash, $cross_tail_build_prj);
  575. }
  576. #
  577. # This procedure fills the second hash with reversed dependencies,
  578. # ie, with info about modules "waiting" for the module
  579. #
  580. sub reverse_dependencies {
  581. my ($deps_hash, $reversed) = @_;
  582. foreach my $module (keys %$deps_hash) {
  583. foreach (keys %{$$deps_hash{$module}}) {
  584. if (defined $$reversed{$_}) {
  585. ${$$reversed{$_}}{$module}++
  586. } else {
  587. my %single_module_dep_hash = ($module => 1);
  588. $$reversed{$_} = \%single_module_dep_hash;
  589. };
  590. };
  591. };
  592. };
  593. #
  594. # Build everything that should be built
  595. #
  596. sub build_all {
  597. if ($build_all_parents) {
  598. my ($prj, $prj_dir, $orig_prj);
  599. get_parent_deps( $initial_module, \%global_deps_hash);
  600. filter_tail_build_dependencies(\%global_deps_hash);
  601. if (scalar keys %active_modules) {
  602. $active_modules{$initial_module}++;
  603. $modules_types{$initial_module} = 'mod';
  604. };
  605. expand_dependencies (\%global_deps_hash);
  606. prepare_incompatible_build(\%global_deps_hash) if ($incompatible && (!$build_from_with_branches));
  607. if ($build_from_with_branches) {
  608. my %reversed_full_deps_hash = ();
  609. reverse_dependencies(\%global_deps_hash, \%reversed_full_deps_hash);
  610. prepare_build_from_with_branches(\%global_deps_hash, \%reversed_full_deps_hash);
  611. }
  612. if ($build_all_cont || $build_since) {
  613. store_weights(\%global_deps_hash);
  614. prepare_build_all_cont(\%global_deps_hash);
  615. %weights_hash = ();
  616. };
  617. if ($incompatible) {
  618. my @missing_modules = ();
  619. foreach (sort keys %global_deps_hash) {
  620. push(@missing_modules, $_) if (!defined $active_modules{$_});
  621. };
  622. };
  623. foreach my $module (keys %dead_parents, keys %skip_modules) {
  624. remove_from_dependencies($module, \%global_deps_hash);
  625. delete ($global_deps_hash{$module}) if (defined $global_deps_hash{$module});
  626. };
  627. store_weights(\%global_deps_hash);
  628. backup_deps_hash(\%global_deps_hash, \%global_deps_hash_backup);
  629. reverse_dependencies(\%global_deps_hash_backup, \%reversed_dependencies);
  630. $modules_number = scalar keys %global_deps_hash;
  631. initialize_html_info($_) foreach (keys %global_deps_hash);
  632. if ($processes_to_run) {
  633. build_multiprocessing();
  634. return;
  635. };
  636. while ($prj = pick_prj_to_build(\%global_deps_hash)) {
  637. if (!defined $dead_parents{$prj}) {
  638. if (scalar keys %broken_build) {
  639. print $echo . "Skipping project $prj because of error(s)\n";
  640. remove_from_dependencies($prj, \%global_deps_hash);
  641. $build_is_finished{$prj}++;
  642. next;
  643. };
  644. $prj_dir = $module_paths{$prj};
  645. get_module_dep_hash($prj, \%local_deps_hash);
  646. my $info_hash = $html_info{$prj};
  647. $$info_hash{DIRS} = check_deps_hash(\%local_deps_hash, $prj);
  648. $module_by_hash{\%local_deps_hash} = $prj;
  649. build_dependent(\%local_deps_hash);
  650. print $check_error_string;
  651. };
  652. remove_from_dependencies($prj, \%global_deps_hash);
  653. $build_is_finished{$prj}++;
  654. };
  655. } else {
  656. store_build_list_content($initial_module);
  657. get_module_dep_hash($initial_module, \%local_deps_hash);
  658. initialize_html_info($initial_module);
  659. my $info_hash = $html_info{$initial_module};
  660. $$info_hash{DIRS} = check_deps_hash(\%local_deps_hash, $initial_module);
  661. $module_by_hash{\%local_deps_hash} = $initial_module;
  662. build_dependent(\%local_deps_hash);
  663. };
  664. };
  665. sub backup_deps_hash {
  666. my $source_hash = shift;
  667. my $backup_hash = shift;
  668. foreach my $key (keys %$source_hash) {
  669. my %values_hash = %{$$source_hash{$key}};
  670. $$backup_hash{$key} = \%values_hash;
  671. };
  672. };
  673. sub initialize_html_info {
  674. my $module = shift;
  675. return if (defined $dead_parents{$module});
  676. $html_info{$module} = { 'DIRS' => [],
  677. 'ERRORFUL' => [],
  678. 'SUCCESSFUL' => [],
  679. 'BUILD_TIME' => 0};
  680. }
  681. #
  682. # Do job
  683. #
  684. sub dmake_dir {
  685. my ($new_job_name, $error_code);
  686. my $job_name = shift;
  687. $jobs_hash{$job_name}->{START_TIME} = time();
  688. $jobs_hash{$job_name}->{STATUS} = 'building';
  689. if ($job_name =~ /(\s)/o && (!-d $job_name)) {
  690. $error_code = do_custom_job($job_name, \%local_deps_hash);
  691. } else {
  692. html_store_job_info(\%local_deps_hash, $job_name);
  693. print_error("$job_name not found!!\n") if (!-d $job_name);
  694. if (!-d $job_name) {
  695. $new_job_name = $job_name;
  696. $new_job_name =~ s/_simple//g;
  697. if ((-d $new_job_name)) {
  698. print("\nTrying $new_job_name, $job_name not found!!\n");
  699. $job_name = $new_job_name;
  700. } else {
  701. print_error("\n$job_name not found!!\n");
  702. }
  703. }
  704. if ($cmd_file) {
  705. print "cd $job_name\n";
  706. print $check_error_string;
  707. print $echo.$job_name."\n";
  708. print "$dmake\n";
  709. print $check_error_string;
  710. } else {
  711. print "Entering $job_name\n";
  712. };
  713. remove_from_dependencies($job_name, \%local_deps_hash) if (!$child);
  714. return if ($cmd_file || $show);
  715. $error_code = run_job($dmake, $job_name);
  716. #if dmake fails, have a go at regenerating the dependencies
  717. #and try again. dmakes normal failure is 255, while death on signal is 254
  718. my $real_exit_code = $error_code >> 8;
  719. if (($ENV{GUI_FOR_BUILD} eq 'WNT') && ($real_exit_code == 255) && ($ENV{nodep} eq '') && ($ENV{depend} eq '')) {
  720. print "Retrying $job_name\n";
  721. $error_code = run_job($dmake, $job_name);
  722. }
  723. html_store_job_info(\%local_deps_hash, $job_name, $error_code) if (!$child);
  724. };
  725. if ($error_code && $ignore) {
  726. push(@ignored_errors, $job_name);
  727. $error_code = 0;
  728. };
  729. if ($child) {
  730. my $oldfh = select STDERR;
  731. $| = 1;
  732. select $oldfh;
  733. $| =1;
  734. if ($error_code) {
  735. _exit($error_code >> 8);
  736. } else {
  737. _exit($? >> 8) if ($? && ($? != -1));
  738. };
  739. _exit(0);
  740. } elsif ($error_code && ($error_code != -1)) {
  741. $broken_build{$job_name} = $error_code;
  742. return $error_code;
  743. };
  744. };
  745. #
  746. # Procedure stores information about build list (and)
  747. # build list object in build_lists_hash
  748. #
  749. sub store_build_list_content {
  750. my $module = shift;
  751. my $build_list_path = get_build_list_path($module);
  752. return undef if (!defined $build_list_path);
  753. return if (!$build_list_path);
  754. if (open (BUILD_LST, $build_list_path))
  755. {
  756. my @build_lst = <BUILD_LST>;
  757. $build_lists_hash{$module} = \@build_lst;
  758. close BUILD_LST;
  759. return;
  760. };
  761. $dead_parents{$module}++;
  762. }
  763. #
  764. # Get string (list) of parent projects to build
  765. #
  766. sub get_parents_array {
  767. my $module = shift;
  768. store_build_list_content($module);
  769. my $build_list_ref = $build_lists_hash{$module};
  770. if (ref($build_list_ref) eq 'XMLBuildListParser') {
  771. return $build_list_ref->getModuleDependencies(\@modes_array);
  772. };
  773. foreach (@$build_list_ref) {
  774. if ($_ =~ /#/) {
  775. if ($`) {
  776. $_ = $`;
  777. } else {
  778. next;
  779. };
  780. };
  781. s/\r\n//;
  782. if ($_ =~ /\:+\s+/) {
  783. return pick_for_build_type($');
  784. };
  785. };
  786. return ();
  787. };
  788. #
  789. # get folders' platform infos
  790. #
  791. sub get_prj_platform {
  792. my $build_list_ref = shift;
  793. my ($prj_alias, $line);
  794. foreach(@$build_list_ref) {
  795. s/\r\n//;
  796. $line++;
  797. if ($_ =~ /\snmake\s/) {
  798. if ($' =~ /\s*-\s+(\w+)[,\S+]*\s+(\S+)/ ) { #'
  799. my $platform = $1;
  800. my $alias = $2;
  801. print_error ("There is no correct alias set in the line $line!") if ($alias eq 'NULL');
  802. mark_platform($alias, $platform);
  803. } else {
  804. print_error("Misspelling in line: \n$_");
  805. };
  806. };
  807. };
  808. };
  809. #
  810. # Procedure populate the dependencies hash with
  811. # information from XML build list object
  812. #
  813. sub get_deps_from_object {
  814. my ($module, $build_list_object, $dependencies_hash) = @_;
  815. foreach my $dir ($build_list_object->getJobDirectories("make", $ENV{GUI})) {
  816. $path_hash{$dir} = $module_paths{$module};
  817. $path_hash{$dir} .= $dir if ($dir ne '/');
  818. my %deps_hash = ();
  819. foreach my $dep ($build_list_object->getJobDependencies($dir, "make", $ENV{GUI})) {
  820. $deps_hash{$dep}++;
  821. };
  822. $$dependencies_hash{$dir} = \%deps_hash;
  823. };
  824. };
  825. #
  826. # this function wraps the get_module_dep_hash and backups the resultung hash
  827. #
  828. sub get_module_dep_hash {
  829. my ($module, $module_dep_hash) = @_;
  830. if (defined $module_deps_hash_backup{$module}) {
  831. backup_deps_hash($module_deps_hash_backup{$module}, $module_dep_hash);
  832. } else {
  833. get_deps_hash($module, $module_dep_hash);
  834. my %values_hash = ();
  835. backup_deps_hash($module_dep_hash, \%values_hash);
  836. $module_deps_hash_backup{$module} = \%values_hash;
  837. }
  838. };
  839. #
  840. # Getting hashes of all internal dependencies and additional
  841. # information for given project
  842. #
  843. sub get_deps_hash {
  844. my ($dummy, $module_to_build);
  845. my %dead_dependencies = ();
  846. $module_to_build = shift;
  847. my $dependencies_hash = shift;
  848. if ($custom_job)
  849. {
  850. add_prerequisite_job($dependencies_hash, $module_to_build, $pre_custom_job);
  851. add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job);
  852. add_dependent_job($dependencies_hash, $module_to_build, $custom_job);
  853. add_dependent_job($dependencies_hash, $module_to_build, $post_job);
  854. add_dependent_job($dependencies_hash, $module_to_build, $post_custom_job);
  855. return;
  856. };
  857. my $build_list_ref = $build_lists_hash{$module_to_build};
  858. if (ref($build_list_ref) eq 'XMLBuildListParser') {
  859. get_deps_from_object($module_to_build, $build_list_ref, $dependencies_hash);
  860. } else {
  861. get_prj_platform($build_list_ref);
  862. foreach (@$build_list_ref) {
  863. if ($_ =~ /#/o) {
  864. next if (!$`);
  865. $_ = $`;
  866. };
  867. s/\r\n//;
  868. if ($_ =~ /\s+nmake\s+/o) {
  869. my ($platform, $dependencies, $dir, $dir_alias);
  870. my %deps_hash = ();
  871. $dependencies = $';
  872. $dummy = $`;
  873. $dummy =~ /(\S+)\s+(\S*)/o;
  874. $dir = $2;
  875. $dependencies =~ /(\w+)/o;
  876. $platform = $1;
  877. $dependencies = $';
  878. while ($dependencies =~ /,(\w+)/o) {
  879. $dependencies = $'; #'
  880. };
  881. $dependencies =~ /\s+(\S+)\s+/o;
  882. $dir_alias = $1;
  883. if (!check_platform($platform)) {
  884. next if (defined $platform_hash{$dir_alias});
  885. $dead_dependencies{$dir_alias}++;
  886. next;
  887. };
  888. delete $dead_dependencies{$dir_alias} if (defined $dead_dependencies{$dir_alias});
  889. print_error("Directory alias $dir_alias is defined at least twice!! Please, correct build.lst in module $module_to_build") if (defined $$dependencies_hash{$dir_alias});
  890. $platform_hash{$dir_alias}++;
  891. $dependencies = $'; #'
  892. print_error("$module_to_build/prj/build.lst has wrongly written dependencies string:\n$_\n") if (!$dependencies);
  893. $deps_hash{$_}++ foreach (get_dependency_array($dependencies));
  894. $$dependencies_hash{$dir_alias} = \%deps_hash;
  895. my $local_dir = '';
  896. if ($dir =~ /(\\|\/)/o) {
  897. $local_dir = "/$'";
  898. };
  899. $path_hash{$dir_alias} = correct_path($module_paths{$module_to_build} . $local_dir);
  900. } elsif ($_ !~ /^\s*$/ && $_ !~ /^\w*\s/o) {
  901. chomp;
  902. push(@errors, $_);
  903. };
  904. };
  905. if (scalar @errors) {
  906. my $message = "$module_to_build/prj/build.lst has wrongly written string(s):\n";
  907. $message .= "$_\n" foreach(@errors);
  908. if ($processes_to_run) {
  909. $broken_build{$module_to_build} = $message;
  910. $dependencies_hash = undef;
  911. return;
  912. } else {
  913. print_error($message);
  914. };
  915. };
  916. foreach my $alias (keys %dead_dependencies) {
  917. next if defined $alive_dependencies{$alias};
  918. # if (!IsHashNative($alias)) {
  919. remove_from_dependencies($alias, $dependencies_hash);
  920. delete $dead_dependencies{$alias};
  921. # };
  922. };
  923. };
  924. resolve_aliases($dependencies_hash, \%path_hash);
  925. add_prerequisite_job($dependencies_hash, $module_to_build, $pre_custom_job);
  926. add_prerequisite_job($dependencies_hash, $module_to_build, $pre_job);
  927. add_dependent_job($dependencies_hash, $module_to_build, $custom_job);
  928. add_dependent_job($dependencies_hash, $module_to_build, $post_job) if ($module_to_build ne $initial_module);
  929. add_dependent_job($dependencies_hash, $module_to_build, $post_custom_job);
  930. store_weights($dependencies_hash);
  931. };
  932. #
  933. # procedure adds which is independent from anothers, but anothers are dependent from it
  934. #
  935. sub add_prerequisite_job {
  936. my ($dependencies_hash, $module, $job) = @_;
  937. return if (!$job);
  938. $job = "$module $job";
  939. foreach (keys %$dependencies_hash) {
  940. my $deps_hash = $$dependencies_hash{$_};
  941. $$deps_hash{$job}++;
  942. };
  943. $$dependencies_hash{$job} = {};
  944. };
  945. #
  946. # procedure adds a job wich is dependent from all already registered jobs
  947. #
  948. sub add_dependent_job {
  949. # $post_job is dependent from all jobs
  950. my ($dependencies_hash, $module, $job) = @_;
  951. return if (!$job);
  952. my %deps_hash = ();
  953. $deps_hash{$_}++ foreach (keys %$dependencies_hash);
  954. $$dependencies_hash{"$module $job"} = \%deps_hash;
  955. };
  956. #
  957. # this procedure converts aliases to absolute paths
  958. #
  959. sub resolve_aliases {
  960. my ($dependencies_hash, $path_hash) = @_;
  961. foreach my $dir_alias (keys %$dependencies_hash) {
  962. my $aliases_hash_ref = $$dependencies_hash{$dir_alias};
  963. my %paths_hash = ();
  964. foreach (keys %$aliases_hash_ref) {
  965. $paths_hash{$$path_hash{$_}}++;
  966. };
  967. delete $$dependencies_hash{$dir_alias};
  968. $$dependencies_hash{$$path_hash{$dir_alias}} = \%paths_hash;
  969. };
  970. };
  971. #
  972. # mark platform in order to prove if alias has been used according to specs
  973. #
  974. sub mark_platform {
  975. my $prj_alias = shift;
  976. if (exists $prj_platform{$prj_alias}) {
  977. $prj_platform{$prj_alias} = 'all';
  978. } else {
  979. $prj_platform{$prj_alias} = shift;
  980. };
  981. };
  982. #
  983. # Convert path from abstract (with '\' and/or '/' delimiters)
  984. # to system-independent
  985. #
  986. sub correct_path {
  987. $_ = shift;
  988. s/\\/\//g;
  989. return $_;
  990. };
  991. sub check_dmake {
  992. if (open(DMAKEVERSION, "dmake -V |")) {
  993. my @dmake_version = <DMAKEVERSION>;
  994. close DMAKEVERSION;
  995. return;
  996. };
  997. my $error_message = 'dmake: Command not found.';
  998. $error_message .= ' Please rerun bootstrap' if (!defined $ENV{COMMON_ENV_TOOLS});
  999. print_error($error_message);
  1000. };
  1001. #
  1002. # Get platform-dependent commands
  1003. #
  1004. sub get_commands {
  1005. my $arg = '';
  1006. # Setting alias for dmake
  1007. $dmake = 'dmake';
  1008. check_dmake();
  1009. if ($cmd_file) {
  1010. if ($ENV{GUI_FOR_BUILD} eq 'UNX') {
  1011. $check_error_string = "if \"\$?\" != \"0\" exit\n";
  1012. } else {
  1013. $check_error_string = "if \"\%?\" != \"0\" quit\n";
  1014. };
  1015. };
  1016. $dmake_args = join(' ', 'dmake', @dmake_args);
  1017. while ($arg = pop(@dmake_args)) {
  1018. $dmake .= ' '.$arg;
  1019. };
  1020. $dmake .= ' verbose=true' if ($html || $verbose);
  1021. };
  1022. #
  1023. # Procedure retrieves list of projects to be built from build.lst
  1024. #
  1025. sub get_workspace_path {
  1026. if (!defined $ENV{GUI}) {
  1027. $ENV{mk_tmp} = '';
  1028. die "No environment set\n";
  1029. };
  1030. my $repository_helper = RepositoryHelper->new();
  1031. my $workspace_path = $repository_helper->get_repository_root();
  1032. my $initial_dir = $repository_helper->get_initial_directory();
  1033. if ($workspace_path eq $initial_dir) {
  1034. print_error('Found no project to build');
  1035. };
  1036. $initial_module = substr($initial_dir, length($workspace_path) + 1);
  1037. if ($initial_module =~ /(\\|\/)/) {
  1038. $initial_module = $`;
  1039. };
  1040. $module_paths{$initial_module} = $workspace_path . "/$initial_module";
  1041. return $workspace_path;
  1042. };
  1043. #
  1044. # Picks project which can be built now from hash and then deletes it from hash
  1045. #
  1046. sub pick_prj_to_build {
  1047. my $deps_hash = shift;
  1048. get_html_orders();
  1049. my $prj = find_indep_prj($deps_hash);
  1050. if ($prj) {
  1051. delete $$deps_hash{$prj};
  1052. generate_html_file();
  1053. };
  1054. return $prj;
  1055. };
  1056. #
  1057. # Make a decision if the project should be built on this platform
  1058. #
  1059. sub check_platform {
  1060. my $platform = shift;
  1061. return 1 if ($platform eq 'all');
  1062. return 1 if (($ENV{GUI} eq 'UNX') && ($platform eq 'u'));
  1063. return 1 if (($ENV{GUI} eq 'WNT') &&
  1064. (($platform eq 'w') || ($platform eq 'n')));
  1065. return 0;
  1066. };
  1067. #
  1068. # Remove project to build ahead from dependencies and make an array
  1069. # of all from given project dependent projects
  1070. #
  1071. sub remove_from_dependencies {
  1072. my ($exclude_prj, $i, $prj, $dependencies);
  1073. $exclude_prj = shift;
  1074. $dependencies = shift;
  1075. foreach $prj (keys %$dependencies) {
  1076. my $prj_deps_hash = $$dependencies{$prj};
  1077. delete $$prj_deps_hash{$exclude_prj} if (defined $$prj_deps_hash{$exclude_prj});
  1078. };
  1079. };
  1080. #
  1081. # Check the hash for consistency
  1082. #
  1083. sub check_deps_hash {
  1084. my ($deps_hash_ref, $module) = @_;
  1085. my @possible_order;
  1086. my $module_path = $module_paths{$module} if (defined $module);
  1087. return if (!scalar keys %$deps_hash_ref);
  1088. my %deps_hash = ();
  1089. my $consistent;
  1090. backup_deps_hash($deps_hash_ref, \%deps_hash);
  1091. my $string;
  1092. my $log_name;
  1093. my $log_path;
  1094. my $long_log_path;
  1095. my $build_number = 0;
  1096. do {
  1097. $consistent = '';
  1098. foreach my $key (sort keys %deps_hash) {
  1099. my $local_deps_ref = $deps_hash{$key};
  1100. if (!scalar keys %$local_deps_ref) {
  1101. if (defined $module) {
  1102. $build_number++;
  1103. $string = undef;
  1104. if ($key =~ /(\s)/o) {
  1105. $string = $key;
  1106. } else {
  1107. if (length($key) == length($module_path)) {
  1108. $string = './';
  1109. } else {
  1110. $string = substr($key, length($module_path) + 1);
  1111. $string =~ s/\\/\//go;
  1112. };
  1113. };
  1114. $log_name = $string;
  1115. if ($log_name eq "$module $custom_job") {
  1116. $log_name = "custom_job";
  1117. };
  1118. if ($log_name eq "$module $pre_custom_job") {
  1119. $log_name = "pre_custom_job";
  1120. };
  1121. if ($log_name eq "$module $post_custom_job") {
  1122. $log_name = "post_custom_job";
  1123. };
  1124. $log_name =~ s/\\|\//\./g;
  1125. $log_name =~ s/\s/_/g;
  1126. $log_name = $module if ($log_name =~ /^\.+$/);
  1127. $log_name .= '.txt';
  1128. if ( $source_config->is_gbuild($module) )
  1129. {
  1130. $log_path = correct_path("$workdir/Logs/${module}_${log_name}");
  1131. $long_log_path = correct_path("$workdir/Logs/${module}_${log_name}");
  1132. }
  1133. else
  1134. {
  1135. $log_path = '../' . $source_config->get_module_repository($module) . "/$module/$ENV{INPATH}/misc/logs/$log_name",
  1136. $long_log_path = correct_path($module_paths{$module} . "/$ENV{INPATH}/misc/logs/$log_name"),
  1137. }
  1138. push(@possible_order, $key);
  1139. $jobs_hash{$key} = { SHORT_NAME => $string,
  1140. BUILD_NUMBER => $build_number,
  1141. STATUS => 'waiting',
  1142. LOG_PATH => $log_path,
  1143. LONG_LOG_PATH => $long_log_path,
  1144. MODULE => $module,
  1145. START_TIME => 0,
  1146. FINISH_TIME => 0,
  1147. CLIENT => '-'
  1148. };
  1149. };
  1150. remove_from_dependencies($key, \%deps_hash);
  1151. delete $deps_hash{$key};
  1152. $consistent++;
  1153. };
  1154. };
  1155. } while ($consistent && (scalar keys %deps_hash));
  1156. return \@possible_order if ($consistent);
  1157. print STDERR "Fatal error:";
  1158. foreach (keys %deps_hash) {
  1159. print STDERR "\n\t$_ depends on: ";
  1160. foreach my $i (keys %{$deps_hash{$_}}) {
  1161. print STDERR (' ', $i);
  1162. };
  1163. };
  1164. if ($child) {
  1165. my $oldfh = select STDERR;
  1166. $| = 1;
  1167. _do_exit(1);
  1168. } else {
  1169. print_error("There are dead or circular dependencies\n");
  1170. };
  1171. };
  1172. #
  1173. # Find project with no dependencies left.
  1174. #
  1175. sub find_indep_prj {
  1176. my ($dependencies, $i);
  1177. my @candidates = ();
  1178. $all_dependent = 1;
  1179. handle_dead_children(0) if ($processes_to_run);
  1180. my $children = children_number();
  1181. return '' if ($children && ($children >= $processes_to_run));
  1182. $dependencies = shift;
  1183. if (scalar keys %$dependencies) {
  1184. foreach my $job (keys %$dependencies) {
  1185. if (!scalar keys %{$$dependencies{$job}}) {
  1186. push(@candidates, $job);
  1187. last if (!$processes_to_run);
  1188. };
  1189. };
  1190. if (scalar @candidates) {
  1191. $all_dependent = 0;
  1192. my $best_candidate = undef;
  1193. my $best_weight = 0;
  1194. if (scalar @candidates > 1) {
  1195. foreach my $candidate (@candidates) {
  1196. my $candidate_weight = get_waiters_number($candidate);
  1197. if ($candidate_weight > $best_weight) {
  1198. $best_candidate = $candidate;
  1199. $best_weight = $candidate_weight;
  1200. };
  1201. };
  1202. if (defined $best_candidate) {
  1203. return $best_candidate;
  1204. }
  1205. }
  1206. my @sorted_candidates = sort(@candidates);
  1207. return $sorted_candidates[0];
  1208. };
  1209. };
  1210. return '';
  1211. };
  1212. sub get_waiters_number {
  1213. my $module = shift;
  1214. if (defined $weights_hash{$module}) {
  1215. return $weights_hash{$module};
  1216. };
  1217. if (defined $reversed_dependencies{$module}) {
  1218. return scalar keys %{$reversed_dependencies{$module}};
  1219. };
  1220. return 0;
  1221. };
  1222. #
  1223. # Check if given entry is HASH-native, that is not a user-defined data
  1224. #
  1225. #sub IsHashNative {
  1226. # my $prj = shift;
  1227. # return 1 if ($prj =~ /^HASH\(0x[\d | a | b | c | d | e | f]{6,}\)/);
  1228. # return 0;
  1229. #};
  1230. #
  1231. # Getting array of dependencies from the string given
  1232. #
  1233. sub get_dependency_array {
  1234. my ($dep_string, @dependencies, $parent_prj, $prj, $string);
  1235. @dependencies = ();
  1236. $dep_string = shift;
  1237. $string = $dep_string;
  1238. $prj = shift;
  1239. while ($dep_string !~ /^NULL/o) {
  1240. print_error("Project $prj has wrongly written dependencies string:\n $string") if (!$dep_string);
  1241. $dep_string =~ /(\S+)\s*/o;
  1242. $parent_prj = $1;
  1243. $dep_string = $'; #'
  1244. if ($parent_prj =~ /\.(\w+)$/o) {
  1245. $parent_prj = $`;
  1246. if (($prj_platform{$parent_prj} ne $1) &&
  1247. ($prj_platform{$parent_prj} ne 'all')) {
  1248. print_error ("$parent_prj\.$1 is a wrongly dependency identifier!\nCheck if it is platform dependent");
  1249. };
  1250. $alive_dependencies{$parent_prj}++ if (check_platform($1));
  1251. push(@dependencies, $parent_prj);
  1252. } else {
  1253. if ((exists($prj_platform{$parent_prj})) &&
  1254. ($prj_platform{$parent_prj} ne 'all') ) {
  1255. print_error("$parent_prj is a wrongly used dependency identifier!\nCheck if it is platform dependent");
  1256. };
  1257. push(@dependencies, $parent_prj);
  1258. };
  1259. };
  1260. return @dependencies;
  1261. };
  1262. sub print_error {
  1263. my $message = shift;
  1264. my $force = shift;
  1265. $modules_number -= scalar keys %global_deps_hash;
  1266. $modules_number -= 1;
  1267. print STDERR "\nERROR: $message\n";
  1268. $ENV{mk_tmp} = '';
  1269. if ($cmd_file) {
  1270. close CMD_FILE;
  1271. unlink ($cmd_file);
  1272. };
  1273. if (!$child) {
  1274. $ENV{mk_tmp} = '';
  1275. close CMD_FILE if ($cmd_file);
  1276. unlink ($cmd_file);
  1277. do_exit(1);
  1278. };
  1279. do_exit(1) if (defined $force);
  1280. };
  1281. sub usage {
  1282. print STDERR "\nbuild\n";
  1283. print STDERR "Syntax: build [--all|-a[:prj_name]]|[--from|-f prj_name1[:prj_name2] [prj_name3 [...]]]|[--since|-c prj_name] [--with_branches prj_name1[:prj_name2] [--skip prj_name1[:prj_name2] [prj_name3 [...]] [prj_name3 [...]|-b] [--deliver|-d [--dlv_switch deliver_switch]]] [-P processes] [--show|-s] [--help|-h] [--file|-F] [--ignore|-i] [--version|-V] [--mode|-m OOo[,SO[,EXT]] [--html [--html_path html_file_path]] [--pre_job=pre_job_sring] [--job=job_string|-j] [--post_job=post_job_sring] [--stoponerror] [--exclude_branch_from prj_name1[:prj_name2] [prj_name3 [...]]] [--interactive] [--verbose]\n";
  1284. print STDERR "Example1: build --from sfx2\n";
  1285. print STDERR " - build all projects dependent from sfx2, starting with sfx2, finishing with the current module\n";
  1286. print STDERR "Example2: build --all:sfx2\n";
  1287. print STDERR " - the same as --all, but skip all projects that have been already built when using \"--all\" switch before sfx2\n";
  1288. print STDERR "Example3(for unixes):\n";
  1289. print STDERR " build --all --pre_job=echo\\ Starting\\ job\\ in\\ \\\$PWD --job=some_script.sh --post_job=echo\\ Job\\ in\\ \\\$PWD\\ is\\ made\n";
  1290. 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";
  1291. print STDERR "\nSwitches:\n";
  1292. print STDERR " --all - build all projects from very beginning till current one\n";
  1293. print STDERR " --from - build all projects dependent from the specified (including it) till current one\n";
  1294. print STDERR " --exclude_branch_from - exclude module(s) and its branch from the build\n";
  1295. print STDERR " --mode OOo - build only projects needed for OpenOffice.org\n";
  1296. print STDERR " --with_branches- the same as \"--from\" but with build all projects in neighbour branches\n";
  1297. print STDERR " --skip - do not build certain module(s)\n";
  1298. print STDERR " --since - build all projects beginning from the specified till current one (the same as \"--all:prj_name\", but skipping prj_name)\n";
  1299. print STDERR " --checkmodules - check if all required parent projects are availlable\n";
  1300. print STDERR " --show - show what is going to be built\n";
  1301. print STDERR " --file - generate command file file_name\n";
  1302. print STDERR " --deliver - only deliver, no build (usable for \'-all\' and \'-from\' keys)\n";
  1303. print STDERR " -P - start multiprocessing build, with number of processes passed\n";
  1304. print STDERR " --dlv_switch - use deliver with the switch specified\n";
  1305. print STDERR " --help - print help info\n";
  1306. print STDERR " --ignore - force tool to ignore errors\n";
  1307. print STDERR " --html - generate html page wit…

Large files files are truncated, but you can click here to view the full file