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