Merge branch 'emenese2/liveVizBoundArray' into charm
[charm.git] / smart-build.pl
1 #!/usr/bin/perl
2
3
4 # This is an interactive script that knows
5 # common ways to build Charm++ and AMPI.
6 #
7 # Authors: dooley, becker
8
9
10 # Turn off I/O buffering
11 $| = 1;
12
13
14
15 # A subroutine that reads from input and returns a yes/no/default
16 sub promptUserYN {
17   while($line = <>){
18         chomp $line;
19         if(lc($line) eq "y" || lc($line) eq "yes" ){
20           return "yes";
21         } elsif(lc($line) eq "n" || lc($line) eq "no" ){
22           return "no";
23         } elsif( $line eq "" ){
24           return "default";
25         }
26   }
27 }
28   
29
30 # The beginning of the good stuff:
31 print "\n============================================================\n";
32 print "\nBegin interactive charm configuration ...\n";
33 print "If you are a poweruser expecting a list of options, please use ./build --help\n";
34 print "\n============================================================\n\n\n";
35
36
37 # Use uname to get the cpu type and OS information
38 $os = `uname -s`;
39 $cpu = `uname -m`;
40
41 #Variables to hold the portions of the configuration:
42 $nobs = "";
43 $arch = "";
44 $compilers = "";
45 $options = "";
46
47 #remove newlines from these strings:
48 chomp($os);
49 chomp ($cpu);
50
51
52 # Determine OS kernel
53 if ($os eq "Linux") {
54   $arch_os = "linux";
55 } elsif ($os eq "Darwin") {
56   $arch_os = "darwin";
57 } elsif ($os =~ m/BSD/ ) {
58   $arch_os = "linux";
59 } elsif ($os =~ m/OSF1/ ) {
60   $arch_os = "linux";
61 } elsif ($os =~ m/AIX/ ) {
62   $arch = "mpi-sp";
63 } elsif ($os =~ m/CYGWIN/ ) {
64   print "Detected a Cygwin system\n";
65   print "This uses the gnu compiler by default,\n";
66   print "To build with Microsoft Visual C++ compiler, use net-win32. Please refer to README.win32 for the details on setting up VC++ under cygwin.\n\n";
67   $arch_os = "cygwin";
68 }
69
70
71
72 # Determine architecture (x86, ppc, ...)
73 if($cpu =~ m/i[0-9]86/){
74   $x86 = 1;
75 } elsif($cpu =~ m/x86\_64/){
76   $amd64 = 1;
77 } elsif($cpu =~ m/ia64/){
78   $ia64 = 1;
79   $nobs = "--no-build-shared";
80 } elsif($cpu =~ m/powerpc/){
81   $ppc = 1;
82 } elsif($cpu =~ m/Power Mac/){
83   $ppc = 1;
84 } elsif($cpu =~ m/ppc*/){
85   $ppc = 1;
86 } elsif($cpu =~ m/alpha/){
87   $alpha = 1;
88 }
89
90
91
92 # default to net
93 $converse_network_type = "net";
94
95
96 # check for MPI
97
98 $skip_choosing = "false";
99
100 $mpi_found = "false";
101 $m = system("which mpicc mpiCC > /dev/null 2>/dev/null") / 256;
102 if($m == 0){
103     $mpi_found = "true";
104     $mpioption = "";
105 }
106 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
107 if($m == 0){
108     $mpi_found = "true";
109     $mpioption = "mpicxx";
110 }
111
112 # Give option of just using the mpi version if mpicc and mpiCC are found
113 if($mpi_found eq "true"){
114   print "\nI found that you have an mpicc available in your path.\nDo you want to build Charm++ on this MPI? [y/N]: ";
115   $p = promptUserYN();
116   if($p eq "yes"){
117         $converse_network_type = "mpi";
118         $skip_choosing = "true";
119         $options = "$options $mpioption";
120   }     
121 }
122
123 if($skip_choosing eq "false") { 
124   
125   print "\nDo you have a special network interconnect? [y/N]: ";
126   $p = promptUserYN();
127   if($p eq "yes"){
128         print << "EOF";
129         
130 Choose an interconnect from below: [1-11]
131          1) MPI
132          2) Infiniband (native ibverbs alpha version)
133          3) Myrinet GM
134          4) Myrinet MX
135          5) LAPI
136          6) Cray XT3, XT4
137          7) Cray XT5
138          8) Bluegene/L Native (only at T. J. Watson)
139          9) Bluegene/L MPI
140         10) Bluegene/P Native
141         11) Bluegene/P MPI
142         12) VMI
143
144 EOF
145         
146         while($line = <>){
147           chomp $line;
148           if($line eq "1"){
149                 $converse_network_type = "mpi";
150                 last;
151           } elsif($line eq "2"){
152                 $converse_network_type = "net";
153                 $options = "$options ibverbs ";
154                 last;
155           } elsif($line eq "3"){
156                 $converse_network_type = "net";
157                 $options = $options . "gm ";
158                 last;
159           } elsif($line eq "4"){
160                 $converse_network_type = "net";
161                 $options = $options . "mx ";
162                 last;
163           } elsif($line eq "5"){
164                 $arch = "lapi";
165                 last;
166           } elsif($line eq "6"){
167                 $arch = "mpi-crayxt3";
168                 last;
169           } elsif($line eq "7"){
170                 $arch = "mpi-crayxt";
171                 last;
172           } elsif($line eq "8"){
173                 $arch = "bluegenel";
174                 $compilers = "xlc ";
175                 $nobs = "--no-build-shared";
176                 last;
177           } elsif($line eq "9"){
178                 $arch = "mpi-bluegenel";
179                 $compilers = "xlc ";
180                 $nobs = "--no-build-shared";
181                 last;
182           } elsif($line eq "10"){
183                 $arch = "bluegenep";
184                 $compilers = "xlc ";
185                 last;
186           } elsif($line eq "11"){
187                 $arch = "mpi-bluegenep";
188                 $compilers = "xlc ";
189                 last;
190           } elsif($line eq "12"){
191                 $converse_network_type = "vmi";
192                 last;
193           } else {
194                 print "Invalid option, please try again :P\n"
195           }
196         }       
197   }
198 }
199
200
201 # construct an $arch string if we did not explicitly set one above
202 if($arch eq ""){
203   $arch = "${converse_network_type}-${arch_os}";
204           if($amd64) {
205                 $arch = $arch . "-x86_64";
206           } elsif($ia64){
207                 $arch = $arch . "-ia64";
208           } elsif($ppc){
209                 $arch = $arch . "-ppc";
210           } elsif($alpha){
211                 $arch = $arch . "-axp";
212           }
213 }
214   
215 # Fixup $arch to match the inconsistent directories in src/archs
216
217 if($arch eq "net-darwin"){
218         $arch = "net-darwin-x86";
219 } elsif($arch eq "net-ppc-darwin"){
220         $arch = "net-darwin-ppc";
221 } elsif($arch eq "mpi-ppc-darwin"){
222         $arch = "mpi-darwin-ppc";
223 } elsif($arch eq "multicore-linux-x86_64"){
224         $arch = "multicore-linux64";
225
226
227
228
229
230
231 #================ Choose SMP/PXSHM =================================
232
233 # find what options are available
234 $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
235 $opts =~ m/Supported options: (.*)/;
236 $opts = $1;
237
238
239 #always provide multicore and single-threaded versions
240 print << "EOF";
241 How do you want to handle SMP/Multicore: [1-4]
242          1) single-threaded [default]
243          2) multicore(single node only)
244 EOF
245
246 # only add the smp or pxshm options if they are available
247 $counter = 3; # the next index used in the list
248
249 $smpIndex = -1;
250 if($opts =~ m/smp/){
251   print "         $counter) SMP\n";
252   $smpIndex = $counter; 
253   $counter ++;
254 }
255
256 $pxshmIndex = -1;
257 if($opts =~ m/pxshm/){
258   print "         $counter) POSIX Shared Memory\n";
259   $pxshmIndex = $counter; 
260   $counter ++;
261 }
262
263 while($line = <>){
264         chomp $line;
265         if($line eq "1" || $line eq ""){
266             last;
267         } elsif($line eq "2"){
268             $converse_network_type = "multicore";
269             last;
270         } elsif($line eq $smpIndex){
271             $options = "$options smp ";
272             last;
273         } elsif($line eq $pxshmIndex){
274             $options = "$options pxshm ";
275             last;
276         }
277 }
278
279
280
281
282
283
284
285 #================ Choose Compiler =================================
286
287 # Lookup list of compilers
288 $cs = `./build charm++ $arch help 2>&1 | grep "Supported compilers"`;
289 # prune away beginning of the line
290 $cs =~ m/Supported compilers: (.*)/;
291 $cs = $1;
292 # split the line into an array
293 @c_list = split(" ", $cs);
294
295 # print list of compilers
296 $numc = @c_list;
297
298 if ($numc > 0) {
299     print "\nDo you want to specify a compiler? [y/N]";
300     $p = promptUserYN();
301     if($p eq "yes" ){
302         print "Choose a compiler: [1-$numc] \n";
303
304         $i = 1;
305         foreach $c (@c_list){
306             print "\t$i)\t$c\n";
307             $i++;
308         }
309
310         # Choose compiler
311         while($line = <>){
312             chomp $line;
313             if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
314                 $compilers = $c_list[$1-1];
315                 last;
316             } else {
317                 print "Invalid option, please try again :P\n"
318             }
319         }
320     }
321 }
322
323
324
325
326 #================ Choose Options =================================
327
328 #Create a hash table containing descriptions of various options
329 %explanations = ();
330 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
331 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
332 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
333 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
334 $explanations{"g95"} = "Use g95 compiler";
335 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
336 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
337 $explanations{"ifc"} = "Use Intel's ifc compiler";
338 $explanations{"ammasso"} = "Use native RDMA support on Ammasso interconnect";
339 $explanations{"syncft"} = "Use initial fault tolerance support";
340 $explanations{"mlogft"} = "Use message logging fault tolerance support";
341 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
342
343
344
345
346
347   # Produce list of options
348
349   $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
350   # prune away beginning of line
351   $opts =~ m/Supported options: (.*)/;
352   $opts = $1;
353
354   @option_list = split(" ", $opts);
355   
356
357   # Prune out entries that would already have been chosen above, such as smp
358   @option_list_pruned = ();
359   foreach $o (@option_list){
360         if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
361           @option_list_pruned = (@option_list_pruned , $o);
362         }
363   }
364
365   # sort the list
366   @option_list_pruned = sort @option_list_pruned;
367   if (@option_list_pruned > 0) {
368
369       print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
370       $special_options = promptUserYN();
371
372       if($special_options eq "yes"){
373
374           # print out list for user to select from
375           print "Please enter one or more numbers separated by spaces\n";
376           print "Choices:\n";
377           $i = 1;
378           foreach $o (@option_list_pruned){
379               $exp = $explanations{$o};
380               print "\t$i)\t$o";
381               # pad whitespace before options
382               for($j=0;$j<20-length($o);$j++){
383                   print " ";
384               }
385               print ": $exp";
386               print "\n";
387               $i++;
388           }
389           print "\t$i)\tNone Of The Above\n";
390
391           $num_options = @option_list_pruned;
392
393           while($line = <>){
394               chomp $line;
395               $line =~ m/([0-9 ]*)/;
396               @entries = split(" ",$1);
397               @entries = sort(@entries);
398
399               $additional_options = "";
400               foreach $e (@entries) {
401                   if($e>=1 && $e<= $num_options){
402                       $estring = $option_list_pruned[$e-1];
403                       $additional_options = "$additional_options $estring";
404                   } elsif ($e == $num_options+1){
405                       # user chose "None of the above"
406                       # clear the options we may have seen before
407                       $additional_options = " ";
408                   }
409               }
410
411               # if the user input something reasonable, we can break out of this loop
412               if($additional_options ne ""){
413                   $options = "$options ${additional_options} ";
414                   last;
415               }
416
417           }
418       }
419   }
420
421
422
423
424
425
426
427
428
429 # Choose compiler flags
430 print << "EOF";
431         
432 Choose a set of compiler flags [1-5]
433         1) none
434         2) debug mode                        -g -O0
435         3) production build [default]        --with-production
436         4) production build w/ projections   --with-production --enable-tracing
437         5) custom
438         
439 EOF
440
441 $compiler_flags = "";
442
443 while($line = <>){
444         chomp $line;
445         if($line eq "1"){
446                 last;
447         } elsif($line eq "2"){
448                 $compiler_flags = "-g -O0";
449                 last;
450         } elsif($line eq "4" ){
451                 $compiler_flags = "--with-production --enable-tracing";
452                 last;
453         } elsif($line eq "3" || $line eq ""){ 
454                 $compiler_flags = "--with-production";
455                 last; 
456         }  elsif($line eq "5"){
457
458                 print "Enter compiler options: ";
459                 $input_line = <>;
460                 chomp($input_line);
461                 $compiler_flags = $input_line;
462                 
463                 last;
464         } else {
465                 print "Invalid option, please try again :P\n"
466         }
467 }
468
469
470
471
472 # Determine the target to build.
473 # We want this simple so we just give 2 options
474 $target = "";
475
476 print << "EOF";
477
478 What do you want to build?
479         1) Charm++ [default] (choose this if you are building NAMD)
480         2) Charm++, AMPI, ParFUM, FEM and other libraries
481
482 EOF
483
484 while($line = <>){
485         chomp $line;
486         if($line eq "1" || $line eq ""){
487                 $target = "charm++";
488                 last;
489         } elsif($line eq "2"){
490                 $target = "LIBS";
491                 last;
492         } else {
493                 print "Invalid option, please try again :P\n"
494         }
495         
496 }
497
498 # Determine whether to use a -j flag for faster building
499 $j = "";
500     print << "EOF";
501     
502 Do you want to compile in parallel?
503         1) No
504         2) Build with -j2
505         3) Build with -j4
506         4) Build with -j8 
507         5) Build with -j16 [default]
508         6) Build with -j32
509         7) Build with -j
510
511 EOF
512
513     while($line = <>) {
514         chomp $line;
515         if($line eq "1"){
516             $j = "";
517             last;
518         } elsif($line eq "2") {
519             $j = "-j2";
520             last; 
521         } elsif($line eq "3") {
522             $j = "-j4";
523             last;
524         }  elsif($line eq "4") {
525             $j = "-j8";
526             last;
527         }  elsif($line eq "5" || $line eq "") {
528             $j = "-j16";
529             last;
530         }  elsif($line eq "6") {
531             $j = "-j32";
532             last;
533         }  elsif($line eq "7") {
534             $j = "-j";
535             last;
536         }   else {
537             print "Invalid option, please try again :P\n";
538         }
539 }
540
541
542 # Compose the build line
543 $build_line = "./build $target $arch $compilers $options $smp $j $nobs ${compiler_flags}\n";
544
545
546 # Save the build line in the log
547 open(BUILDLINE, ">>smart-build.log");
548 print BUILDLINE `date`;
549 print BUILDLINE "Using the following build command:\n";
550 print BUILDLINE "$build_line\n";
551 close(BUILDLINE);
552
553
554 print "We have determined a suitable build line is:\n";
555 print "\t$build_line\n\n";
556
557
558 # Execute the build line if the appropriate architecture directory exists
559 print "Do you want to start the build now? [Y/n]";
560 $p = promptUserYN();
561 if($p eq "yes" || $p eq "default"){
562   if(-e "src/arch/$arch"){
563         print "Building with: ${build_line}\n"; 
564         # Execute the build line
565         system($build_line);
566   } else {
567         print "We could not figure out how to build charm with those options on this platform, please manually build\n";
568         print "Try something similar to: ${build_line}\n";
569   }
570 }
571
572
573