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