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