Fix breakages caused by commit 48ed568c6
[charm.git] / smart-build.pl
blob836bf2f8d37bde19c5fbd6b604f71e8fdf9e9828
1 #!/usr/bin/env perl
4 # This is an interactive script that knows
5 # common ways to build Charm++ and AMPI.
7 # Authors: dooley, becker
9 use strict;
10 use warnings;
12 # Get location of script
13 use File::Basename;
14 my $dirname = dirname(__FILE__);
16 # Turn off I/O buffering
17 $| = 1;
21 # A subroutine that reads from input and returns a yes/no/default
22 sub promptUserYN {
23 while(my $line = <>){
24 chomp $line;
25 if(lc($line) eq "y" || lc($line) eq "yes" ){
26 return "yes";
27 } elsif(lc($line) eq "n" || lc($line) eq "no" ){
28 return "no";
29 } elsif( $line eq "" ){
30 return "default";
36 # The beginning of the good stuff:
37 print "\n============================================================\n";
38 print "\nBegin interactive charm configuration ...\n";
39 print "If you are a poweruser expecting a list of options, please use ./build --help\n";
40 print "\n============================================================\n\n\n";
43 # Use uname to get the cpu type and OS information
44 my $os = `uname -s`;
45 my $cpu = `uname -m`;
47 #Variables to hold the portions of the configuration:
48 my $nobs = "";
49 my $arch = "";
50 my $compilers = "";
51 my $options = "";
53 #remove newlines from these strings:
54 chomp($os);
55 chomp ($cpu);
57 my $arch_os;
58 # Determine OS kernel
59 if ($os eq "Linux") {
60 $arch_os = "linux";
61 } elsif ($os eq "Darwin") {
62 $arch_os = "darwin";
63 } elsif ($os =~ m/BSD/ ) {
64 $arch_os = "linux";
65 } elsif ($os =~ m/OSF1/ ) {
66 $arch_os = "linux";
70 my $x86;
71 my $amd64;
72 my $ppc;
73 my $arm7;
74 # Determine architecture (x86, ppc, ...)
75 if($cpu =~ m/i[0-9]86/){
76 $x86 = 1;
77 } elsif($cpu =~ m/x86\_64/){
78 $amd64 = 1;
79 } elsif($cpu =~ m/powerpc/){
80 $ppc = 1;
81 } elsif($cpu =~ m/ppc*/){
82 $ppc = 1;
83 } elsif($cpu =~ m/arm7/){
84 $arm7 = 1;
88 # default to netlrts
89 my $converse_network_type = "netlrts";
90 my $skip_choosing = "false";
92 print "Are you building to run just on the local machine, and not across multiple nodes? [";
93 if($arch_os eq "darwin") {
94 print "Y/n]\n";
95 } else {
96 print "y/N]\n";
99 my $p = promptUserYN();
100 if($p eq "yes" || ($arch_os eq "darwin" && $p eq "default")){
101 $converse_network_type = "multicore";
102 $skip_choosing = "true";
106 # check for MPI
108 my $mpi_found = "false";
109 my $m = system("which mpicc mpiCC > /dev/null 2>/dev/null") / 256;
110 my $mpioption;
111 if($m == 0){
112 $mpi_found = "true";
113 $mpioption = "";
115 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
116 if($m == 0){
117 $mpi_found = "true";
118 $mpioption = "mpicxx";
121 # Give option of just using the mpi version if mpicc and mpiCC are found
122 if($skip_choosing eq "false" && $mpi_found eq "true"){
123 print "\nI found that you have an mpicc available in your path.\nDo you want to build Charm++ on this MPI? [y/N]: ";
124 my $p = promptUserYN();
125 if($p eq "yes"){
126 $converse_network_type = "mpi";
127 $skip_choosing = "true";
128 $options = "$options $mpioption";
132 if($skip_choosing eq "false") {
134 print "\nDo you have a special network interconnect? [y/N]: ";
135 my $p = promptUserYN();
136 if($p eq "yes"){
137 print << "EOF";
139 Choose an interconnect from below: [1-10]
140 1) MPI
141 2) Infiniband (ibverbs)
142 3) Cray XE, XK
143 4) Cray XC
144 5) Blue Gene/Q
145 6) Intel Omni-Path (ofi)
149 while(my $line = <>){
150 chomp $line;
151 if($line eq "1"){
152 $converse_network_type = "mpi";
153 last;
154 } elsif($line eq "2"){
155 $converse_network_type = "verbs";
156 last;
157 } elsif($line eq "3"){
158 $arch = "gni-crayxe";
159 last;
160 } elsif($line eq "4"){
161 $arch = "gni-crayxc";
162 last;
163 } elsif($line eq "5"){
164 $arch = "pamilrts-bluegeneq";
165 last;
166 } elsif($line eq "6"){
167 $converse_network_type = "ofi";
168 last;
169 } else {
170 print "Invalid option, please try again :P\n"
177 # construct an $arch string if we did not explicitly set one above
178 if($arch eq ""){
179 $arch = "${converse_network_type}-${arch_os}";
180 if($amd64) {
181 $arch = $arch . "-x86_64";
182 } elsif($ppc){
183 $arch = $arch . "-ppc";
184 } elsif($arm7){
185 $arch = $arch . "-arm7";
189 # Fixup $arch to match the inconsistent directories in src/archs
191 if($arch eq "netlrts-darwin"){
192 $arch = "netlrts-darwin-x86_64";
193 } elsif($arch eq "multicore-linux-arm7"){
194 $arch = "multicore-arm7";
198 #================ Choose SMP/PXSHM =================================
200 # find what options are available
201 my $opts = `$dirname/build charm++ $arch help 2>&1 | grep "Supported options"`;
202 $opts =~ m/Supported options: (.*)/;
203 $opts = $1;
205 my $smp_opts = <<EOF;
206 1) single-threaded [default]
209 # only add the smp or pxshm options if they are available
210 my $counter = 1; # the last index used in the list
212 my $smpIndex = -1;
213 if($opts =~ m/smp/){
214 $counter ++;
215 $smp_opts = $smp_opts . " $counter) SMP\n";
216 $smpIndex = $counter;
219 my $pxshmIndex = -1;
220 if($opts =~ m/pxshm/){
221 $counter ++;
222 $smp_opts = $smp_opts . " $counter) POSIX Shared Memory\n";
223 $pxshmIndex = $counter;
226 if ($counter != 1) {
227 print "How do you want to handle SMP/Multicore: [1-$counter]\n";
228 print $smp_opts;
230 while(my $line = <>){
231 chomp $line;
232 if($line eq "" || $line eq "1"){
233 last;
234 } elsif($line eq $smpIndex){
235 $options = "$options smp ";
236 last;
237 } elsif($line eq $pxshmIndex){
238 $options = "$options pxshm ";
239 last;
245 #================ Choose Compiler =================================
247 # Lookup list of compilers
248 my $cs = `$dirname/build charm++ $arch help 2>&1 | grep "Supported compilers"`;
249 # prune away beginning of the line
250 $cs =~ m/Supported compilers: (.*)/;
251 $cs = $1;
252 # split the line into an array
253 my @c_list = split(" ", $cs);
255 # print list of compilers
256 my $numc = @c_list;
258 if ($numc > 0) {
259 print "\nDo you want to specify a compiler? [y/N]";
260 my $p = promptUserYN();
261 if($p eq "yes" ){
262 print "Choose a compiler: [1-$numc] \n";
264 my $i = 1;
265 foreach my $c (@c_list){
266 print "\t$i)\t$c\n";
267 $i++;
270 # Choose compiler
271 while(my $line = <>){
272 chomp $line;
273 if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
274 $compilers = $c_list[$1-1];
275 last;
276 } else {
277 print "Invalid option, please try again :P\n"
286 #================ Choose Options =================================
288 #Create a hash table containing descriptions of various options
289 my %explanations = ();
290 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
291 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
292 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
293 $explanations{"flang"} = "Use flang compiler for fortran";
294 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
295 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
296 $explanations{"syncft"} = "Use fault tolerance support";
297 $explanations{"mlogft"} = "Use message logging fault tolerance support";
298 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
304 # Produce list of options
306 $opts = `$dirname/build charm++ $arch help 2>&1 | grep "Supported options"`;
307 # prune away beginning of line
308 $opts =~ m/Supported options: (.*)/;
309 $opts = $1;
311 my @option_list = split(" ", $opts);
314 # Prune out entries that would already have been chosen above, such as smp
315 my @option_list_pruned = ();
316 foreach my $o (@option_list){
317 if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
318 @option_list_pruned = (@option_list_pruned , $o);
322 # sort the list
323 @option_list_pruned = sort @option_list_pruned;
324 if (@option_list_pruned > 0) {
326 print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
327 my $special_options = promptUserYN();
329 if($special_options eq "yes"){
331 # print out list for user to select from
332 print "Please enter one or more numbers separated by spaces\n";
333 print "Choices:\n";
334 my $i = 1;
335 foreach my $o (@option_list_pruned){
336 my $exp = $explanations{$o};
337 print "\t$i)\t$o";
338 # pad whitespace before options
339 for(my $j=0;$j<20-length($o);$j++){
340 print " ";
342 print ": $exp";
343 print "\n";
344 $i++;
346 print "\t$i)\tNone Of The Above\n";
348 my $num_options = @option_list_pruned;
350 while(my $line = <>){
351 chomp $line;
352 $line =~ m/([0-9 ]*)/;
353 my @entries = split(" ",$1);
354 @entries = sort(@entries);
356 my $additional_options = "";
357 foreach my $e (@entries) {
358 if($e>=1 && $e<= $num_options){
359 my $estring = $option_list_pruned[$e-1];
360 $additional_options = "$additional_options $estring";
361 } elsif ($e == $num_options+1){
362 # user chose "None of the above"
363 # clear the options we may have seen before
364 $additional_options = " ";
368 # if the user input something reasonable, we can break out of this loop
369 if($additional_options ne ""){
370 $options = "$options ${additional_options} ";
371 last;
379 # Choose compiler flags
380 print << "EOF";
382 Choose a set of compiler flags [1-5]
383 1) none
384 2) debug mode -g -O0
385 3) production build [default] --with-production
386 4) production build w/ projections --with-production --enable-tracing
387 5) custom
391 my $compiler_flags = "";
393 while(my $line = <>){
394 chomp $line;
395 if($line eq "1"){
396 last;
397 } elsif($line eq "2"){
398 $compiler_flags = "-g -O0";
399 last;
400 } elsif($line eq "4" ){
401 $compiler_flags = "--with-production --enable-tracing";
402 last;
403 } elsif($line eq "3" || $line eq ""){
404 $compiler_flags = "--with-production";
405 last;
406 } elsif($line eq "5"){
408 print "Enter compiler options: ";
409 my $input_line = <>;
410 chomp($input_line);
411 $compiler_flags = $input_line;
413 last;
414 } else {
415 print "Invalid option, please try again :P\n"
422 # Determine the target to build.
423 # We want this simple so we just give 2 options
424 my $target = "";
426 print << "EOF";
428 What do you want to build?
429 1) Charm++ [default] (choose this if you are building NAMD)
430 2) Charm++ and AMPI
431 3) Charm++, AMPI, ParFUM, FEM and other libraries
435 while(my $line = <>){
436 chomp $line;
437 if($line eq "1" || $line eq ""){
438 $target = "charm++";
439 last;
440 } elsif($line eq "2"){
441 $target = "AMPI";
442 last;
443 } elsif($line eq "3"){
444 $target = "LIBS";
445 last;
446 } else {
447 print "Invalid option, please try again :P\n"
452 # Determine whether to use a -j flag for faster building
453 my $j = "";
454 print << "EOF";
456 Do you want to compile in parallel?
457 1) No
458 2) Build with -j2
459 3) Build with -j4
460 4) Build with -j8
461 5) Build with -j16 [default]
462 6) Build with -j32
463 7) Build with -j
467 while(my $line = <>) {
468 chomp $line;
469 if($line eq "1"){
470 $j = "";
471 last;
472 } elsif($line eq "2") {
473 $j = "-j2";
474 last;
475 } elsif($line eq "3") {
476 $j = "-j4";
477 last;
478 } elsif($line eq "4") {
479 $j = "-j8";
480 last;
481 } elsif($line eq "5" || $line eq "") {
482 $j = "-j16";
483 last;
484 } elsif($line eq "6") {
485 $j = "-j32";
486 last;
487 } elsif($line eq "7") {
488 $j = "-j";
489 last;
490 } else {
491 print "Invalid option, please try again :P\n";
496 # Compose the build line
497 my $build_line = "$dirname/build $target $arch $compilers $options $j $nobs ${compiler_flags}\n";
500 # Save the build line in the log
501 open(BUILDLINE, ">>smart-build.log");
502 print BUILDLINE `date`;
503 print BUILDLINE "Using the following build command:\n";
504 print BUILDLINE "$build_line\n";
505 close(BUILDLINE);
508 print "We have determined a suitable build line is:\n";
509 print "\t$build_line\n\n";
512 # Execute the build line if the appropriate architecture directory exists
513 print "Do you want to start the build now? [Y/n]";
514 my $p = promptUserYN();
515 if($p eq "yes" || $p eq "default"){
516 if(-e "$dirname/src/arch/$arch"){
517 print "Building with: ${build_line}\n";
518 # Execute the build line
519 system($build_line);
520 } else {
521 print "We could not figure out how to build charm with those options on this platform, please manually build\n";
522 print "Try something similar to: ${build_line}\n";