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