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