fixing a debug print
[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) Cray XE, XK
139          9) Bluegene/L Native (only at T. J. Watson)
140         10) Bluegene/L MPI
141         11) Bluegene/P Native
142         12) Bluegene/P MPI
143         13) VMI
144
145 EOF
146         
147         while($line = <>){
148           chomp $line;
149           if($line eq "1"){
150                 $converse_network_type = "mpi";
151                 last;
152           } elsif($line eq "2"){
153                 $converse_network_type = "net";
154                 $options = "$options ibverbs ";
155                 last;
156           } elsif($line eq "3"){
157                 $converse_network_type = "net";
158                 $options = $options . "gm ";
159                 last;
160           } elsif($line eq "4"){
161                 $converse_network_type = "net";
162                 $options = $options . "mx ";
163                 last;
164           } elsif($line eq "5"){
165                 $arch = "lapi";
166                 last;
167           } elsif($line eq "6"){
168                 $arch = "mpi-crayxt3";
169                 last;
170           } elsif($line eq "7"){
171                 $arch = "mpi-crayxt";
172                 last;
173           } elsif($line eq "8"){
174                 $arch = "gemini_gni-crayxe";
175                 last;
176           } elsif($line eq "9"){
177                 $arch = "bluegenel";
178                 $compilers = "xlc ";
179                 $nobs = "--no-build-shared";
180                 last;
181           } elsif($line eq "10"){
182                 $arch = "mpi-bluegenel";
183                 $compilers = "xlc ";
184                 $nobs = "--no-build-shared";
185                 last;
186           } elsif($line eq "11"){
187                 $arch = "bluegenep";
188                 $compilers = "xlc ";
189                 last;
190           } elsif($line eq "12"){
191                 $arch = "mpi-bluegenep";
192                 $compilers = "xlc ";
193                 last;
194           } elsif($line eq "13"){
195                 $converse_network_type = "vmi";
196                 last;
197           } else {
198                 print "Invalid option, please try again :P\n"
199           }
200         }       
201   }
202 }
203
204
205 # construct an $arch string if we did not explicitly set one above
206 if($arch eq ""){
207   $arch = "${converse_network_type}-${arch_os}";
208           if($amd64) {
209                 $arch = $arch . "-x86_64";
210           } elsif($ia64){
211                 $arch = $arch . "-ia64";
212           } elsif($ppc){
213                 $arch = $arch . "-ppc";
214           } elsif($alpha){
215                 $arch = $arch . "-axp";
216           }
217 }
218   
219 # Fixup $arch to match the inconsistent directories in src/archs
220
221 if($arch eq "net-darwin"){
222         $arch = "net-darwin-x86";
223 } elsif($arch eq "net-ppc-darwin"){
224         $arch = "net-darwin-ppc";
225 } elsif($arch eq "mpi-ppc-darwin"){
226         $arch = "mpi-darwin-ppc";
227 } elsif($arch eq "multicore-linux-x86_64"){
228         $arch = "multicore-linux64";
229
230
231
232
233
234
235 #================ Choose SMP/PXSHM =================================
236
237 # find what options are available
238 $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
239 $opts =~ m/Supported options: (.*)/;
240 $opts = $1;
241
242
243 #always provide multicore and single-threaded versions
244 print << "EOF";
245 How do you want to handle SMP/Multicore: [1-4]
246          1) single-threaded [default]
247          2) multicore(single node only)
248 EOF
249
250 # only add the smp or pxshm options if they are available
251 $counter = 3; # the next index used in the list
252
253 $smpIndex = -1;
254 if($opts =~ m/smp/){
255   print "         $counter) SMP\n";
256   $smpIndex = $counter; 
257   $counter ++;
258 }
259
260 $pxshmIndex = -1;
261 if($opts =~ m/pxshm/){
262   print "         $counter) POSIX Shared Memory\n";
263   $pxshmIndex = $counter; 
264   $counter ++;
265 }
266
267 while($line = <>){
268         chomp $line;
269         if($line eq "1" || $line eq ""){
270             last;
271         } elsif($line eq "2"){
272             $converse_network_type = "multicore";
273             last;
274         } elsif($line eq $smpIndex){
275             $options = "$options smp ";
276             last;
277         } elsif($line eq $pxshmIndex){
278             $options = "$options pxshm ";
279             last;
280         }
281 }
282
283
284
285
286
287
288
289 #================ Choose Compiler =================================
290
291 # Lookup list of compilers
292 $cs = `./build charm++ $arch help 2>&1 | grep "Supported compilers"`;
293 # prune away beginning of the line
294 $cs =~ m/Supported compilers: (.*)/;
295 $cs = $1;
296 # split the line into an array
297 @c_list = split(" ", $cs);
298
299 # print list of compilers
300 $numc = @c_list;
301
302 if ($numc > 0) {
303     print "\nDo you want to specify a compiler? [y/N]";
304     $p = promptUserYN();
305     if($p eq "yes" ){
306         print "Choose a compiler: [1-$numc] \n";
307
308         $i = 1;
309         foreach $c (@c_list){
310             print "\t$i)\t$c\n";
311             $i++;
312         }
313
314         # Choose compiler
315         while($line = <>){
316             chomp $line;
317             if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
318                 $compilers = $c_list[$1-1];
319                 last;
320             } else {
321                 print "Invalid option, please try again :P\n"
322             }
323         }
324     }
325 }
326
327
328
329
330 #================ Choose Options =================================
331
332 #Create a hash table containing descriptions of various options
333 %explanations = ();
334 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
335 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
336 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
337 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
338 $explanations{"g95"} = "Use g95 compiler";
339 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
340 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
341 $explanations{"ifc"} = "Use Intel's ifc compiler";
342 $explanations{"ammasso"} = "Use native RDMA support on Ammasso interconnect";
343 $explanations{"syncft"} = "Use initial fault tolerance support";
344 $explanations{"mlogft"} = "Use message logging fault tolerance support";
345 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
346
347
348
349
350
351   # Produce list of options
352
353   $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
354   # prune away beginning of line
355   $opts =~ m/Supported options: (.*)/;
356   $opts = $1;
357
358   @option_list = split(" ", $opts);
359   
360
361   # Prune out entries that would already have been chosen above, such as smp
362   @option_list_pruned = ();
363   foreach $o (@option_list){
364         if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
365           @option_list_pruned = (@option_list_pruned , $o);
366         }
367   }
368
369   # sort the list
370   @option_list_pruned = sort @option_list_pruned;
371   if (@option_list_pruned > 0) {
372
373       print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
374       $special_options = promptUserYN();
375
376       if($special_options eq "yes"){
377
378           # print out list for user to select from
379           print "Please enter one or more numbers separated by spaces\n";
380           print "Choices:\n";
381           $i = 1;
382           foreach $o (@option_list_pruned){
383               $exp = $explanations{$o};
384               print "\t$i)\t$o";
385               # pad whitespace before options
386               for($j=0;$j<20-length($o);$j++){
387                   print " ";
388               }
389               print ": $exp";
390               print "\n";
391               $i++;
392           }
393           print "\t$i)\tNone Of The Above\n";
394
395           $num_options = @option_list_pruned;
396
397           while($line = <>){
398               chomp $line;
399               $line =~ m/([0-9 ]*)/;
400               @entries = split(" ",$1);
401               @entries = sort(@entries);
402
403               $additional_options = "";
404               foreach $e (@entries) {
405                   if($e>=1 && $e<= $num_options){
406                       $estring = $option_list_pruned[$e-1];
407                       $additional_options = "$additional_options $estring";
408                   } elsif ($e == $num_options+1){
409                       # user chose "None of the above"
410                       # clear the options we may have seen before
411                       $additional_options = " ";
412                   }
413               }
414
415               # if the user input something reasonable, we can break out of this loop
416               if($additional_options ne ""){
417                   $options = "$options ${additional_options} ";
418                   last;
419               }
420
421           }
422       }
423   }
424
425
426
427
428
429
430
431
432
433 # Choose compiler flags
434 print << "EOF";
435         
436 Choose a set of compiler flags [1-5]
437         1) none
438         2) debug mode                        -g -O0
439         3) production build [default]        --with-production
440         4) production build w/ projections   --with-production --enable-tracing
441         5) custom
442         
443 EOF
444
445 $compiler_flags = "";
446
447 while($line = <>){
448         chomp $line;
449         if($line eq "1"){
450                 last;
451         } elsif($line eq "2"){
452                 $compiler_flags = "-g -O0";
453                 last;
454         } elsif($line eq "4" ){
455                 $compiler_flags = "--with-production --enable-tracing";
456                 last;
457         } elsif($line eq "3" || $line eq ""){ 
458                 $compiler_flags = "--with-production";
459                 last; 
460         }  elsif($line eq "5"){
461
462                 print "Enter compiler options: ";
463                 $input_line = <>;
464                 chomp($input_line);
465                 $compiler_flags = $input_line;
466                 
467                 last;
468         } else {
469                 print "Invalid option, please try again :P\n"
470         }
471 }
472
473
474
475
476 # Determine the target to build.
477 # We want this simple so we just give 2 options
478 $target = "";
479
480 print << "EOF";
481
482 What do you want to build?
483         1) Charm++ [default] (choose this if you are building NAMD)
484         2) Charm++, AMPI, ParFUM, FEM and other libraries
485
486 EOF
487
488 while($line = <>){
489         chomp $line;
490         if($line eq "1" || $line eq ""){
491                 $target = "charm++";
492                 last;
493         } elsif($line eq "2"){
494                 $target = "LIBS";
495                 last;
496         } else {
497                 print "Invalid option, please try again :P\n"
498         }
499         
500 }
501
502 # Determine whether to use a -j flag for faster building
503 $j = "";
504     print << "EOF";
505     
506 Do you want to compile in parallel?
507         1) No
508         2) Build with -j2
509         3) Build with -j4
510         4) Build with -j8 
511         5) Build with -j16 [default]
512         6) Build with -j32
513         7) Build with -j
514
515 EOF
516
517     while($line = <>) {
518         chomp $line;
519         if($line eq "1"){
520             $j = "";
521             last;
522         } elsif($line eq "2") {
523             $j = "-j2";
524             last; 
525         } elsif($line eq "3") {
526             $j = "-j4";
527             last;
528         }  elsif($line eq "4") {
529             $j = "-j8";
530             last;
531         }  elsif($line eq "5" || $line eq "") {
532             $j = "-j16";
533             last;
534         }  elsif($line eq "6") {
535             $j = "-j32";
536             last;
537         }  elsif($line eq "7") {
538             $j = "-j";
539             last;
540         }   else {
541             print "Invalid option, please try again :P\n";
542         }
543 }
544
545
546 # Compose the build line
547 $build_line = "./build $target $arch $compilers $options $smp $j $nobs ${compiler_flags}\n";
548
549
550 # Save the build line in the log
551 open(BUILDLINE, ">>smart-build.log");
552 print BUILDLINE `date`;
553 print BUILDLINE "Using the following build command:\n";
554 print BUILDLINE "$build_line\n";
555 close(BUILDLINE);
556
557
558 print "We have determined a suitable build line is:\n";
559 print "\t$build_line\n\n";
560
561
562 # Execute the build line if the appropriate architecture directory exists
563 print "Do you want to start the build now? [Y/n]";
564 $p = promptUserYN();
565 if($p eq "yes" || $p eq "default"){
566   if(-e "src/arch/$arch"){
567         print "Building with: ${build_line}\n"; 
568         # Execute the build line
569         system($build_line);
570   } else {
571         print "We could not figure out how to build charm with those options on this platform, please manually build\n";
572         print "Try something similar to: ${build_line}\n";
573   }
574 }
575
576
577