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