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