Removed extraneous print statment.
[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/alpha/){
85   $alpha = 1;
86 }
87
88
89
90 # default to net
91 $converse_network_type = "net";
92
93
94 print << "EOF";
95 How do you want to handle SMP/Multicore: [1-4]
96          1) single-threaded [default]
97          2) multicore(single node only)
98          3) SMP
99          4) POSIX Shared Memory
100
101 EOF
102
103 while($line = <>){
104         chomp $line;
105         if($line eq "1" || $line eq ""){
106             last;
107         } elsif($line eq "2"){
108             $converse_network_type = "multicore";
109             last;
110         } elsif($line eq "3"){
111             $options = "$options smp ";
112             last;
113         } elsif($line eq "4"){
114             $options = "$options pxshm ";
115             last;
116         }
117 }
118
119 # check for MPI
120
121 $mpi_found = "false";
122 $m = system("which mpicc mpiCC > /dev/null 2>/dev/null") / 256;
123 if($m == 0){
124     $mpi_found = "true";
125     $mpioption = "";
126 }
127 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
128 if($m == 0){
129     $mpi_found = "true";
130     $mpioption = "mpicxx";
131 }
132
133 # Give option of just using the mpi version if mpicc and mpiCC are found
134 if($mpi_found eq "true"){
135   print "\nI found that you have an mpicc available in your path.\nDo you want to build Charm++ on this MPI? [y/N]: ";
136   $p = promptUserYN();
137   if($p eq "yes"){
138         $converse_network_type = "mpi";
139         $skip_choosing = "true";
140         $options = "$options $mpioption";
141   }     
142 }
143
144 if($skip_choosing eq "false") { 
145   
146   print "\nDo you have a special network interconnect? [y/N]: ";
147   $p = promptUserYN();
148   if($p eq "yes"){
149         print << "EOF";
150         
151 Choose an interconnect from below: [1-11]
152          1) MPI
153          2) Infiniband (native ibverbs alpha version)
154          3) Myrinet GM
155          4) Myrinet MX
156          5) LAPI
157          6) Cray XT3, XT4 (not yet tested on CNL)
158          7) Bluegene/L Native (only at T. J. Watson)
159          8) Bluegene/L MPI
160          9) Bluegene/P Native (only at T. J. Watson)
161         10) Bluegene/P MPI
162         11) VMI
163
164 EOF
165         
166         while($line = <>){
167           chomp $line;
168           if($line eq "1"){
169                 $converse_network_type = "mpi";
170                 last;
171           } elsif($line eq "2"){
172                 $converse_network_type = "net";
173                 $options = "$options ibverbs ";
174                 last;
175           } elsif($line eq "3"){
176                 $converse_network_type = "net";
177                 $options = $options . "gm ";
178                 last;
179           } elsif($line eq "4"){
180                 $converse_network_type = "net";
181                 $options = $options . "mx ";
182                 last;
183           } elsif($line eq "5"){
184                 $arch = "lapi";
185                 last;
186           } elsif($line eq "6"){
187                 $arch = "mpi-crayxt3";
188                 last;
189           } elsif($line eq "7"){
190                 $arch = "bluegenel";
191                 $compilers = "xlc ";
192                 $nobs = "--no-build-shared";
193                 last;
194           } elsif($line eq "8"){
195                 $arch = "mpi-bluegenel";
196                 $compilers = "xlc ";
197                 $nobs = "--no-build-shared";
198                 last;
199           } elsif($line eq "9"){
200                 $arch = "bluegenep";
201                 $compilers = "xlc ";
202                 last;
203           } elsif($line eq "10"){
204                 $arch = "mpi-bluegenep";
205                 $compilers = "xlc ";
206                 last;
207           } elsif($line eq "11"){
208                 $converse_network_type = "vmi";
209                 last;
210           } else {
211                 print "Invalid option, please try again :P\n"
212           }
213         }       
214   }
215 }
216
217
218 # construct an $arch string if we did not explicitly set one above
219 if($arch eq ""){
220   $arch = "${converse_network_type}-${arch_os}";
221           if($amd64) {
222                 $arch = $arch . "-amd64";
223           } elsif($ia64){
224                 $arch = $arch . "-ia64";
225           } elsif($ppc){
226                 $arch = $arch . "-ppc";
227           } elsif($alpha){
228                 $arch = $arch . "-axp";
229           }
230 }
231   
232 # Fixup $arch to match the inconsistent directories in src/archs
233
234 if($arch eq "net-darwin"){
235         $arch = "net-darwin-x86";
236 } elsif($arch eq "net-darwin-ppc"){
237         $arch = "net-ppc-darwin";
238 } elsif($arch eq "mpi-darwin-ppc"){
239         $arch = "mpi-ppc-darwin";
240
241
242
243
244
245
246 #================ Choose Compiler =================================
247
248 # Lookup list of compilers
249 $cs = `./build charm++ $arch help 2>&1 | grep "Supported compilers"`;
250 # prune away beginning of the line
251 $cs =~ m/Supported compilers: (.*)/;
252 $cs = $1;
253 # split the line into an array
254 @c_list = split(" ", $cs);
255
256 # print list of compilers
257 $numc = @c_list;
258
259 if ($numc > 0) {
260     print "\nDo you want to specify a compiler? [y/N]";
261     $p = promptUserYN();
262     if($p eq "yes" ){
263         print "Choose a compiler: [1-$numc] \n";
264
265         $i = 1;
266         foreach $c (@c_list){
267             print "\t$i)\t$c\n";
268             $i++;
269         }
270
271         # Choose compiler
272         while($line = <>){
273             chomp $line;
274             if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
275                 $compilers = $c_list[$1-1];
276                 last;
277             } else {
278                 print "Invalid option, please try again :P\n"
279             }
280         }
281     }
282 }
283
284
285
286 #================ Choose Options =================================
287
288 #Create a hash table containing descriptions of various options
289 %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{"ifort"} = "Use Intel's ifort fortran compiler";
293 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
294 $explanations{"g95"} = "Use g95 compiler";
295 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
296 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
297 $explanations{"ifc"} = "Use Intel's ifc compiler";
298 $explanations{"ammasso"} = "Use native RDMA support on Ammasso interconnect";
299 $explanations{"syncft"} = "Use initial fault tolerance support";
300
301
302
303
304
305   # Produce list of options
306
307   $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
308   # prune away beginning of line
309   $opts =~ m/Supported options: (.*)/;
310   $opts = $1;
311
312   @option_list = split(" ", $opts);
313   
314
315   # Prune out entries that would already have been chosen above, such as smp
316   @option_list_pruned = ();
317   foreach $o (@option_list){
318         if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
319           @option_list_pruned = (@option_list_pruned , $o);
320         }
321   }
322
323   # sort the list
324   @option_list_pruned = sort @option_list_pruned;
325   if (@option_list_pruned > 0) {
326
327       print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
328       $special_options = promptUserYN();
329
330       if($special_options eq "yes"){
331
332           # print out list for user to select from
333           print "Please enter one or more numbers separated by spaces\n";
334           print "Choices:\n";
335           $i = 1;
336           foreach $o (@option_list_pruned){
337               $exp = $explanations{$o};
338               print "\t$i)\t$o";
339               # pad whitespace before options
340               for($j=0;$j<20-length($o);$j++){
341                   print " ";
342               }
343               print ": $exp";
344               print "\n";
345               $i++;
346           }
347           print "\t$i)\tNone Of The Above\n";
348
349           $num_options = @option_list_pruned;
350
351           while($line = <>){
352               chomp $line;
353               $line =~ m/([0-9 ]*)/;
354               @entries = split(" ",$1);
355               @entries = sort(@entries);
356
357               $additional_options = "";
358               foreach $e (@entries) {
359                   if($e>=1 && $e<= $num_options){
360                       $estring = $option_list_pruned[$e-1];
361                       $additional_options = "$additional_options $estring";
362                   } elsif ($e == $num_options+1){
363                       # user chose "None of the above"
364                       # clear the options we may have seen before
365                       $additional_options = " ";
366                   }
367               }
368
369               # if the user input something reasonable, we can break out of this loop
370               if($additional_options ne ""){
371                   $options = "$options ${additional_options} ";
372                   last;
373               }
374
375           }
376       }
377   }
378
379
380
381 # Choose compiler flags
382 print << "EOF";
383         
384 Choose a set of compiler flags [1-5]
385         1) none
386         2) debug                      -g -O0
387         3) optimized + projections    -O2
388         4) optimized [default]        -O2 -DCMK_OPTIMIZE
389         5) custom
390         
391 EOF
392
393 $compiler_flags = "";
394
395 while($line = <>){
396         chomp $line;
397         if($line eq "1"){
398                 last;
399         } elsif($line eq "2"){
400                 $compiler_flags = "-g -O0";
401                 last;
402         } elsif($line eq "4" || $line eq ""){
403                 $compiler_flags = "-O2 -DCMK_OPTIMIZE";
404                 last;
405         } elsif($line eq "3"){ 
406                 $compiler_flags = "-O2"; 
407                 last; 
408         }  elsif($line eq "5"){
409
410                 print "Enter compiler options: ";
411                 $input_line = <>;
412                 chomp($input_line);
413                 $compiler_flags = $input_line;
414                 
415                 last;
416         } else {
417                 print "Invalid option, please try again :P\n"
418         }
419 }
420
421
422
423
424 # Determine the target to build.
425 # We want this simple so we just give 2 options
426 $target = "";
427
428 print << "EOF";
429
430 What do you want to build?
431         1) Charm++ [default] (choose this if you are building NAMD)
432         2) Charm++, AMPI, ParFUM, FEM and other libraries
433
434 EOF
435
436 while($line = <>){
437         chomp $line;
438         if($line eq "1" || $line eq ""){
439                 $target = "charm++";
440                 last;
441         } elsif($line eq "2"){
442                 $target = "LIBS";
443                 last;
444         } else {
445                 print "Invalid option, please try again :P\n"
446         }
447         
448 }
449
450 # Determine whether to use a -j4 flag for faster building
451 # Currently LIBS cannot be safely built with -j4
452 $j = "";
453 if($target eq "charm++"){
454         print "\nDo you want to do a parallel build (-j4)?[Y/n]";
455         $p = promptUserYN();
456         if($p eq "yes" || $p eq "default"){
457           $j = "-j4";
458         }
459 }
460
461
462 # Compose the build line
463 $build_line = "./build $target $arch $compilers $options $smp $j ${compiler_flags}\n";
464
465
466 # Save the build line in the log
467 open(BUILDLINE, ">>smart-build.log");
468 print BUILDLINE `date`;
469 print BUILDLINE "Using the following build command:\n";
470 print BUILDLINE "$build_line\n";
471 close(BUILDLINE);
472
473
474 print "We have determined a suitable build line is:\n";
475 print "\t$build_line\n\n";
476
477
478 # Execute the build line if the appropriate architecture directory exists
479 print "Do you want to start the build now? [Y/n]";
480 $p = promptUserYN();
481 if($p eq "yes" || $p eq "default"){
482   if(-e "src/arch/$arch"){
483         print "Building with: ${build_line}\n"; 
484         # Execute the build line
485         system($build_line);
486   } else {
487         print "We could not figure out how to build charm with those options on this platform, please manually build\n";
488         print "Try something similar to: ${build_line}\n";
489   }
490 }
491
492
493