Docs: Correct misspelling in cmi documentation
[charm.git] / smart-build.pl
bloba7d054c2f611547634ffc3ea5dcd2fac952250c1
1 #!/usr/bin/perl
4 # This is an interactive script that knows
5 # common ways to build Charm++ and AMPI.
7 # Authors: dooley, becker
9 use strict;
10 use warnings;
12 # Turn off I/O buffering
13 $| = 1;
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";
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";
39 # Use uname to get the cpu type and OS information
40 my $os = `uname -s`;
41 my $cpu = `uname -m`;
43 #Variables to hold the portions of the configuration:
44 my $nobs = "";
45 my $arch = "";
46 my $compilers = "";
47 my $options = "";
49 #remove newlines from these strings:
50 chomp($os);
51 chomp ($cpu);
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";
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;
98 # default to net
99 my $converse_network_type = "net";
100 my $skip_choosing = "false";
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";
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";
116 # check for MPI
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 = "";
125 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
126 if($m == 0){
127 $mpi_found = "true";
128 $mpioption = "mpicxx";
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";
142 if($skip_choosing eq "false") {
144 print "\nDo you have a special network interconnect? [y/N]: ";
145 my $p = promptUserYN();
146 if($p eq "yes"){
147 print << "EOF";
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
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"
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";
226 # Fixup $arch to match the inconsistent directories in src/archs
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";
239 #================ Choose SMP/PXSHM =================================
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;
246 my $smp_opts = <<EOF;
247 1) single-threaded [default]
250 # only add the smp or pxshm options if they are available
251 my $counter = 1; # the last index used in the list
253 my $smpIndex = -1;
254 if($opts =~ m/smp/){
255 $counter ++;
256 $smp_opts = $smp_opts . " $counter) SMP\n";
257 $smpIndex = $counter;
260 my $pxshmIndex = -1;
261 if($opts =~ m/pxshm/){
262 $counter ++;
263 $smp_opts = $smp_opts . " $counter) POSIX Shared Memory\n";
264 $pxshmIndex = $counter;
267 if ($counter != 1) {
268 print "How do you want to handle SMP/Multicore: [1-$counter]\n";
269 print $smp_opts;
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;
286 #================ Choose Compiler =================================
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);
296 # print list of compilers
297 my $numc = @c_list;
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";
305 my $i = 1;
306 foreach my $c (@c_list){
307 print "\t$i)\t$c\n";
308 $i++;
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"
327 #================ Choose Options =================================
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";
348 # Produce list of options
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;
355 my @option_list = split(" ", $opts);
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);
366 # sort the list
367 @option_list_pruned = sort @option_list_pruned;
368 if (@option_list_pruned > 0) {
370 print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
371 my $special_options = promptUserYN();
373 if($special_options eq "yes"){
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 " ";
386 print ": $exp";
387 print "\n";
388 $i++;
390 print "\t$i)\tNone Of The Above\n";
392 my $num_options = @option_list_pruned;
394 while(my $line = <>){
395 chomp $line;
396 $line =~ m/([0-9 ]*)/;
397 my @entries = split(" ",$1);
398 @entries = sort(@entries);
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 = " ";
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;
423 # Choose compiler flags
424 print << "EOF";
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
435 my $compiler_flags = "";
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"){
452 print "Enter compiler options: ";
453 my $input_line = <>;
454 chomp($input_line);
455 $compiler_flags = $input_line;
457 last;
458 } else {
459 print "Invalid option, please try again :P\n"
466 # Determine the target to build.
467 # We want this simple so we just give 2 options
468 my $target = "";
470 print << "EOF";
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
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"
492 # Determine whether to use a -j flag for faster building
493 my $j = "";
494 print << "EOF";
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
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";
536 # Compose the build line
537 my $build_line = "./build $target $arch $compilers $options $j $nobs ${compiler_flags}\n";
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);
548 print "We have determined a suitable build line is:\n";
549 print "\t$build_line\n\n";
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";