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