a few minor bug fixed
[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 an Cygwin kernel\n";
79   print "This by default uses gnu compiler!\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
243 print "\nDo you want to specify a compiler? [y/N]";
244 $p = promptUserYN();
245 if($p eq "yes" ){
246
247   # Lookup list of compilers
248   $cs = `./build charm++ $arch help | 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   @c_list = split(" ", $cs);
254
255   # print list of compilers
256   $numc = @c_list;
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 #================ Choose Options =================================
280
281 #Create a hash table containing descriptions of various options
282 %explanations = ();
283 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
284 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
285 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
286 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
287 $explanations{"g95"} = "Use g95 compiler";
288 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
289 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
290 $explanations{"ifc"} = "Use Intel's ifc compiler";
291 $explanations{"ammasso"} = "Use native RDMA support on Ammasso interconnect";
292 $explanations{"syncft"} = "Use initial fault tolerance support";
293
294
295
296 print "\nDo you want to specify any Charm++ build options such as fortran compilers? [y/N]";
297 $special_options = promptUserYN();
298
299 if($special_options eq "yes"){
300
301   # Produce list of options
302
303   $opts = `./build charm++ $arch help | grep "Supported options"`;
304   # prune away beginning of line
305   $opts =~ m/Supported options: (.*)/;
306   $opts = $1;
307
308   @option_list = split(" ", $opts);
309   
310   print "Please enter one or more numbers separated by spaces\n";
311   print "Choices:\n";
312
313   # Prune out entries that would already have been chosen above, such as smp
314   @option_list_pruned = ();
315   foreach $o (@option_list){
316         if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
317           @option_list_pruned = (@option_list_pruned , $o);
318         }
319   }
320
321   # sort the list
322   @option_list_pruned = sort @option_list_pruned;
323
324   # print out list for user to select from
325   $i = 1;
326   foreach $o (@option_list_pruned){
327         $exp = $explanations{$o};
328         print "\t$i)\t$o";
329         # pad whitespace before options
330         for($j=0;$j<20-length($o);$j++){
331           print " ";
332         }
333     print ": $exp";
334         print "\n";
335         $i++;
336   }
337   print "\t$i)\tNone Of The Above\n";
338
339   $num_options = @option_list_pruned;
340
341   while($line = <>){
342         chomp $line;
343     $line =~ m/([0-9 ]*)/;
344     @entries = split(" ",$1);
345     @entries = sort(@entries);
346
347         $additional_options = "";
348         foreach $e (@entries) {
349           if($e>=1 && $e<= $num_options){
350                 $estring = $option_list_pruned[$e-1];
351                 $additional_options = "$additional_options $estring";
352           } elsif ($e == $num_options+1){
353                 # user chose "None of the above"
354                 # clear the options we may have seen before
355                 $additional_options = " ";
356           }
357         }
358
359         # if the user input something reasonable, we can break out of this loop
360         if($additional_options ne ""){
361           $options = "$options ${additional_options} ";
362           last;
363         }
364
365   }
366
367 }
368
369
370
371
372 # Choose compiler flags
373 print << "EOF";
374         
375 Choose a set of compiler flags [1-5]
376         1) none
377         2) debug
378         3) optimized [default]
379         4) optimized + projections
380         5) custom
381         
382 EOF
383
384 $compiler_flags = "";
385
386 while($line = <>){
387         chomp $line;
388         if($line eq "1"){
389                 last;
390         } elsif($line eq "2"){
391                 $compiler_flags = "-g -O0";
392                 last;
393         } elsif($line eq "3" || $line eq ""){
394                 $compiler_flags = "-O2 -DCMK_OPTIMIZE";
395                 last;
396         } elsif($line eq "4"){ 
397                 $compiler_flags = "-O2"; 
398                 last; 
399         }  elsif($line eq "5"){
400
401                 print "Enter compiler options: ";
402                 $input_line = <>;
403                 chomp($input_line);
404                 $compiler_flags = $input_line;
405                 
406                 last;
407         } else {
408                 print "Invalid option, please try again :P\n"
409         }
410 }
411
412
413
414
415 # Determine the target to build.
416 # We want this simple so we just give 2 options
417 $target = "";
418
419 print << "EOF";
420
421 What do you want to build?
422         1) Charm++ [default] (choose this if you are building NAMD)
423         2) Charm++, AMPI, ParFUM, FEM and other libraries
424
425 EOF
426
427 while($line = <>){
428         chomp $line;
429         if($line eq "1" || $line eq ""){
430                 $target = "charm++";
431                 last;
432         } elsif($line eq "2"){
433                 $target = "LIBS";
434                 last;
435         } else {
436                 print "Invalid option, please try again :P\n"
437         }
438         
439 }
440
441 # Determine whether to use a -j4 flag for faster building
442 # Currently LIBS cannot be safely built with -j4
443 $j = "";
444 if($target eq "charm++"){
445         print "\nDo you want to do a parallel build (-j4)?[Y/n]";
446         $p = promptUserYN();
447         if($p eq "yes" || $p eq "default"){
448           $j = "-j4";
449         }
450 }
451
452
453 # Compose the build line
454 $build_line = "./build $target $arch $compilers $options $smp $j ${compiler_flags}\n";
455
456
457 # Save the build line in the log
458 open(BUILDLINE, ">>smart-build.log");
459 print BUILDLINE `date`;
460 print BUILDLINE "Using the following build command:\n";
461 print BUILDLINE "$build_line\n";
462 close(BUILDLINE);
463
464
465 print "We have determined a suitable build line is:\n";
466 print "\t$build_line\n\n";
467
468
469 # Execute the build line if the appropriate architecture directory exists
470 print "Do you want to start the build now? [Y/n]";
471 $p = promptUserYN();
472 if($p eq "yes" || $p eq "default"){
473   if(-e "src/arch/$arch"){
474         print "Building with: ${build_line}\n"; 
475         # Execute the build line
476         system($build_line);
477   } else {
478         print "We could not figure out how to build charm with those options on this platform, please manually build\n";
479         print "Try something similar to: ${build_line}\n";
480   }
481 }
482
483
484