charmxi: correct mismatched appwork begin/begin tracing on Group [local] methods
[charm.git] / smart-build.pl
blob430a01620e3263c9ecd6914e812dca6fd4148549
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 netlrts
99 my $converse_network_type = "netlrts";
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) Cray XE, XK
153 4) Cray XC
154 5) Blue Gene/P Native
155 6) Blue Gene/P MPI
156 7) Blue Gene/Q
160 while(my $line = <>){
161 chomp $line;
162 if($line eq "1"){
163 $converse_network_type = "mpi";
164 last;
165 } elsif($line eq "2"){
166 $converse_network_type = "verbs";
167 last;
168 } elsif($line eq "3"){
169 $arch = "gni-crayxe";
170 last;
171 } elsif($line eq "4"){
172 $arch = "gni-crayxc";
173 last;
174 } elsif($line eq "5"){
175 $arch = "bluegenep";
176 $compilers = "xlc ";
177 last;
178 } elsif($line eq "6"){
179 $arch = "mpi-bluegenep";
180 $compilers = "xlc ";
181 last;
182 } elsif($line eq "7"){
183 $arch = "pamilrts-bluegeneq";
184 last;
185 } else {
186 print "Invalid option, please try again :P\n"
193 # construct an $arch string if we did not explicitly set one above
194 if($arch eq ""){
195 $arch = "${converse_network_type}-${arch_os}";
196 if($amd64) {
197 $arch = $arch . "-x86_64";
198 } elsif($ia64){
199 $arch = $arch . "-ia64";
200 } elsif($ppc){
201 $arch = $arch . "-ppc";
202 } elsif($alpha){
203 $arch = $arch . "-axp";
207 # Fixup $arch to match the inconsistent directories in src/archs
209 if($arch eq "net-darwin"){
210 $arch = "net-darwin-x86";
211 } elsif($arch eq "net-ppc-darwin"){
212 $arch = "net-darwin-ppc";
213 } elsif($arch eq "mpi-ppc-darwin"){
214 $arch = "mpi-darwin-ppc";
215 } elsif($arch eq "multicore-linux-x86_64"){
216 $arch = "multicore-linux64";
220 #================ Choose SMP/PXSHM =================================
222 # find what options are available
223 my $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
224 $opts =~ m/Supported options: (.*)/;
225 $opts = $1;
227 my $smp_opts = <<EOF;
228 1) single-threaded [default]
231 # only add the smp or pxshm options if they are available
232 my $counter = 1; # the last index used in the list
234 my $smpIndex = -1;
235 if($opts =~ m/smp/){
236 $counter ++;
237 $smp_opts = $smp_opts . " $counter) SMP\n";
238 $smpIndex = $counter;
241 my $pxshmIndex = -1;
242 if($opts =~ m/pxshm/){
243 $counter ++;
244 $smp_opts = $smp_opts . " $counter) POSIX Shared Memory\n";
245 $pxshmIndex = $counter;
248 if ($counter != 1) {
249 print "How do you want to handle SMP/Multicore: [1-$counter]\n";
250 print $smp_opts;
252 while(my $line = <>){
253 chomp $line;
254 if($line eq "" || $line eq "1"){
255 last;
256 } elsif($line eq $smpIndex){
257 $options = "$options smp ";
258 last;
259 } elsif($line eq $pxshmIndex){
260 $options = "$options pxshm ";
261 last;
267 #================ Choose Compiler =================================
269 # Lookup list of compilers
270 my $cs = `./build charm++ $arch help 2>&1 | grep "Supported compilers"`;
271 # prune away beginning of the line
272 $cs =~ m/Supported compilers: (.*)/;
273 $cs = $1;
274 # split the line into an array
275 my @c_list = split(" ", $cs);
277 # print list of compilers
278 my $numc = @c_list;
280 if ($numc > 0) {
281 print "\nDo you want to specify a compiler? [y/N]";
282 my $p = promptUserYN();
283 if($p eq "yes" ){
284 print "Choose a compiler: [1-$numc] \n";
286 my $i = 1;
287 foreach my $c (@c_list){
288 print "\t$i)\t$c\n";
289 $i++;
292 # Choose compiler
293 while(my $line = <>){
294 chomp $line;
295 if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
296 $compilers = $c_list[$1-1];
297 last;
298 } else {
299 print "Invalid option, please try again :P\n"
308 #================ Choose Options =================================
310 #Create a hash table containing descriptions of various options
311 my %explanations = ();
312 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
313 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
314 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
315 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
316 $explanations{"g95"} = "Use g95 compiler";
317 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
318 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
319 $explanations{"ifc"} = "Use Intel's ifc compiler";
320 $explanations{"ammasso"} = "Use native RDMA support on Ammasso interconnect";
321 $explanations{"syncft"} = "Use initial fault tolerance support";
322 $explanations{"mlogft"} = "Use message logging fault tolerance support";
323 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
329 # Produce list of options
331 $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
332 # prune away beginning of line
333 $opts =~ m/Supported options: (.*)/;
334 $opts = $1;
336 my @option_list = split(" ", $opts);
339 # Prune out entries that would already have been chosen above, such as smp
340 my @option_list_pruned = ();
341 foreach my $o (@option_list){
342 if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
343 @option_list_pruned = (@option_list_pruned , $o);
347 # sort the list
348 @option_list_pruned = sort @option_list_pruned;
349 if (@option_list_pruned > 0) {
351 print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
352 my $special_options = promptUserYN();
354 if($special_options eq "yes"){
356 # print out list for user to select from
357 print "Please enter one or more numbers separated by spaces\n";
358 print "Choices:\n";
359 my $i = 1;
360 foreach my $o (@option_list_pruned){
361 my $exp = $explanations{$o};
362 print "\t$i)\t$o";
363 # pad whitespace before options
364 for(my $j=0;$j<20-length($o);$j++){
365 print " ";
367 print ": $exp";
368 print "\n";
369 $i++;
371 print "\t$i)\tNone Of The Above\n";
373 my $num_options = @option_list_pruned;
375 while(my $line = <>){
376 chomp $line;
377 $line =~ m/([0-9 ]*)/;
378 my @entries = split(" ",$1);
379 @entries = sort(@entries);
381 my $additional_options = "";
382 foreach my $e (@entries) {
383 if($e>=1 && $e<= $num_options){
384 my $estring = $option_list_pruned[$e-1];
385 $additional_options = "$additional_options $estring";
386 } elsif ($e == $num_options+1){
387 # user chose "None of the above"
388 # clear the options we may have seen before
389 $additional_options = " ";
393 # if the user input something reasonable, we can break out of this loop
394 if($additional_options ne ""){
395 $options = "$options ${additional_options} ";
396 last;
404 # Choose compiler flags
405 print << "EOF";
407 Choose a set of compiler flags [1-5]
408 1) none
409 2) debug mode -g -O0
410 3) production build [default] --with-production
411 4) production build w/ projections --with-production --enable-tracing
412 5) custom
416 my $compiler_flags = "";
418 while(my $line = <>){
419 chomp $line;
420 if($line eq "1"){
421 last;
422 } elsif($line eq "2"){
423 $compiler_flags = "-g -O0";
424 last;
425 } elsif($line eq "4" ){
426 $compiler_flags = "--with-production --enable-tracing";
427 last;
428 } elsif($line eq "3" || $line eq ""){
429 $compiler_flags = "--with-production";
430 last;
431 } elsif($line eq "5"){
433 print "Enter compiler options: ";
434 my $input_line = <>;
435 chomp($input_line);
436 $compiler_flags = $input_line;
438 last;
439 } else {
440 print "Invalid option, please try again :P\n"
447 # Determine the target to build.
448 # We want this simple so we just give 2 options
449 my $target = "";
451 print << "EOF";
453 What do you want to build?
454 1) Charm++ [default] (choose this if you are building NAMD)
455 2) Charm++, AMPI, ParFUM, FEM and other libraries
459 while(my $line = <>){
460 chomp $line;
461 if($line eq "1" || $line eq ""){
462 $target = "charm++";
463 last;
464 } elsif($line eq "2"){
465 $target = "LIBS";
466 last;
467 } else {
468 print "Invalid option, please try again :P\n"
473 # Determine whether to use a -j flag for faster building
474 my $j = "";
475 print << "EOF";
477 Do you want to compile in parallel?
478 1) No
479 2) Build with -j2
480 3) Build with -j4
481 4) Build with -j8
482 5) Build with -j16 [default]
483 6) Build with -j32
484 7) Build with -j
488 while(my $line = <>) {
489 chomp $line;
490 if($line eq "1"){
491 $j = "";
492 last;
493 } elsif($line eq "2") {
494 $j = "-j2";
495 last;
496 } elsif($line eq "3") {
497 $j = "-j4";
498 last;
499 } elsif($line eq "4") {
500 $j = "-j8";
501 last;
502 } elsif($line eq "5" || $line eq "") {
503 $j = "-j16";
504 last;
505 } elsif($line eq "6") {
506 $j = "-j32";
507 last;
508 } elsif($line eq "7") {
509 $j = "-j";
510 last;
511 } else {
512 print "Invalid option, please try again :P\n";
517 # Compose the build line
518 my $build_line = "./build $target $arch $compilers $options $j $nobs ${compiler_flags}\n";
521 # Save the build line in the log
522 open(BUILDLINE, ">>smart-build.log");
523 print BUILDLINE `date`;
524 print BUILDLINE "Using the following build command:\n";
525 print BUILDLINE "$build_line\n";
526 close(BUILDLINE);
529 print "We have determined a suitable build line is:\n";
530 print "\t$build_line\n\n";
533 # Execute the build line if the appropriate architecture directory exists
534 print "Do you want to start the build now? [Y/n]";
535 my $p = promptUserYN();
536 if($p eq "yes" || $p eq "default"){
537 if(-e "src/arch/$arch"){
538 print "Building with: ${build_line}\n";
539 # Execute the build line
540 system($build_line);
541 } else {
542 print "We could not figure out how to build charm with those options on this platform, please manually build\n";
543 print "Try something similar to: ${build_line}\n";