doc:Adv Arrays+PUP: insert and update paths to pup examples
[charm.git] / smart-build.pl
blob69d3f766b6dd8b59925b97795e1a18571ed0eef4
1 #!/usr/bin/perl
4 # This is an interactive script that knows
5 # common ways to build Charm++ and AMPI.
7 # Authors: dooley, becker
10 # Turn off I/O buffering
11 $| = 1;
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";
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 print "\n============================================================\n\n\n";
37 # Use uname to get the cpu type and OS information
38 $os = `uname -s`;
39 $cpu = `uname -m`;
41 #Variables to hold the portions of the configuration:
42 $nobs = "";
43 $arch = "";
44 $compilers = "";
45 $options = "";
47 #remove newlines from these strings:
48 chomp($os);
49 chomp ($cpu);
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 } elsif ($os =~ m/CYGWIN/ ) {
64 print "Detected a Cygwin system\n";
65 print "This uses the gnu compiler by default,\n";
66 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";
67 $arch_os = "cygwin";
72 # Determine architecture (x86, ppc, ...)
73 if($cpu =~ m/i[0-9]86/){
74 $x86 = 1;
75 } elsif($cpu =~ m/x86\_64/){
76 $amd64 = 1;
77 } elsif($cpu =~ m/ia64/){
78 $ia64 = 1;
79 $nobs = "--no-build-shared";
80 } elsif($cpu =~ m/powerpc/){
81 $ppc = 1;
82 } elsif($cpu =~ m/Power Mac/){
83 $ppc = 1;
84 } elsif($cpu =~ m/ppc*/){
85 $ppc = 1;
86 } elsif($cpu =~ m/alpha/){
87 $alpha = 1;
92 # default to net
93 $converse_network_type = "net";
96 # check for MPI
98 $skip_choosing = "false";
100 $mpi_found = "false";
101 $m = system("which mpicc mpiCC > /dev/null 2>/dev/null") / 256;
102 if($m == 0){
103 $mpi_found = "true";
104 $mpioption = "";
106 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
107 if($m == 0){
108 $mpi_found = "true";
109 $mpioption = "mpicxx";
112 # Give option of just using the mpi version if mpicc and mpiCC are found
113 if($mpi_found eq "true"){
114 print "\nI found that you have an mpicc available in your path.\nDo you want to build Charm++ on this MPI? [y/N]: ";
115 $p = promptUserYN();
116 if($p eq "yes"){
117 $converse_network_type = "mpi";
118 $skip_choosing = "true";
119 $options = "$options $mpioption";
123 if($skip_choosing eq "false") {
125 print "\nDo you have a special network interconnect? [y/N]: ";
126 $p = promptUserYN();
127 if($p eq "yes"){
128 print << "EOF";
130 Choose an interconnect from below: [1-11]
131 1) MPI
132 2) Infiniband (native ibverbs alpha version)
133 3) Myrinet GM
134 4) Myrinet MX
135 5) LAPI
136 6) Cray XT3, XT4
137 7) Cray XT5
138 8) Bluegene/L Native (only at T. J. Watson)
139 9) Bluegene/L MPI
140 10) Bluegene/P Native
141 11) Bluegene/P MPI
142 12) VMI
146 while($line = <>){
147 chomp $line;
148 if($line eq "1"){
149 $converse_network_type = "mpi";
150 last;
151 } elsif($line eq "2"){
152 $converse_network_type = "net";
153 $options = "$options ibverbs ";
154 last;
155 } elsif($line eq "3"){
156 $converse_network_type = "net";
157 $options = $options . "gm ";
158 last;
159 } elsif($line eq "4"){
160 $converse_network_type = "net";
161 $options = $options . "mx ";
162 last;
163 } elsif($line eq "5"){
164 $arch = "lapi";
165 last;
166 } elsif($line eq "6"){
167 $arch = "mpi-crayxt3";
168 last;
169 } elsif($line eq "7"){
170 $arch = "mpi-crayxt";
171 last;
172 } elsif($line eq "8"){
173 $arch = "bluegenel";
174 $compilers = "xlc ";
175 $nobs = "--no-build-shared";
176 last;
177 } elsif($line eq "9"){
178 $arch = "mpi-bluegenel";
179 $compilers = "xlc ";
180 $nobs = "--no-build-shared";
181 last;
182 } elsif($line eq "10"){
183 $arch = "bluegenep";
184 $compilers = "xlc ";
185 last;
186 } elsif($line eq "11"){
187 $arch = "mpi-bluegenep";
188 $compilers = "xlc ";
189 last;
190 } elsif($line eq "12"){
191 $converse_network_type = "vmi";
192 last;
193 } else {
194 print "Invalid option, please try again :P\n"
201 # construct an $arch string if we did not explicitly set one above
202 if($arch eq ""){
203 $arch = "${converse_network_type}-${arch_os}";
204 if($amd64) {
205 $arch = $arch . "-x86_64";
206 } elsif($ia64){
207 $arch = $arch . "-ia64";
208 } elsif($ppc){
209 $arch = $arch . "-ppc";
210 } elsif($alpha){
211 $arch = $arch . "-axp";
215 # Fixup $arch to match the inconsistent directories in src/archs
217 if($arch eq "net-darwin"){
218 $arch = "net-darwin-x86";
219 } elsif($arch eq "net-ppc-darwin"){
220 $arch = "net-darwin-ppc";
221 } elsif($arch eq "mpi-ppc-darwin"){
222 $arch = "mpi-darwin-ppc";
223 } elsif($arch eq "multicore-linux-x86_64"){
224 $arch = "multicore-linux64";
231 #================ Choose SMP/PXSHM =================================
233 # find what options are available
234 $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
235 $opts =~ m/Supported options: (.*)/;
236 $opts = $1;
239 #always provide multicore and single-threaded versions
240 print << "EOF";
241 How do you want to handle SMP/Multicore: [1-4]
242 1) single-threaded [default]
243 2) multicore(single node only)
246 # only add the smp or pxshm options if they are available
247 $counter = 3; # the next index used in the list
249 $smpIndex = -1;
250 if($opts =~ m/smp/){
251 print " $counter) SMP\n";
252 $smpIndex = $counter;
253 $counter ++;
256 $pxshmIndex = -1;
257 if($opts =~ m/pxshm/){
258 print " $counter) POSIX Shared Memory\n";
259 $pxshmIndex = $counter;
260 $counter ++;
263 while($line = <>){
264 chomp $line;
265 if($line eq "1" || $line eq ""){
266 last;
267 } elsif($line eq "2"){
268 $converse_network_type = "multicore";
269 last;
270 } elsif($line eq $smpIndex){
271 $options = "$options smp ";
272 last;
273 } elsif($line eq $pxshmIndex){
274 $options = "$options pxshm ";
275 last;
285 #================ Choose Compiler =================================
287 # Lookup list of compilers
288 $cs = `./build charm++ $arch help 2>&1 | grep "Supported compilers"`;
289 # prune away beginning of the line
290 $cs =~ m/Supported compilers: (.*)/;
291 $cs = $1;
292 # split the line into an array
293 @c_list = split(" ", $cs);
295 # print list of compilers
296 $numc = @c_list;
298 if ($numc > 0) {
299 print "\nDo you want to specify a compiler? [y/N]";
300 $p = promptUserYN();
301 if($p eq "yes" ){
302 print "Choose a compiler: [1-$numc] \n";
304 $i = 1;
305 foreach $c (@c_list){
306 print "\t$i)\t$c\n";
307 $i++;
310 # Choose compiler
311 while($line = <>){
312 chomp $line;
313 if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
314 $compilers = $c_list[$1-1];
315 last;
316 } else {
317 print "Invalid option, please try again :P\n"
326 #================ Choose Options =================================
328 #Create a hash table containing descriptions of various options
329 %explanations = ();
330 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
331 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
332 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
333 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
334 $explanations{"g95"} = "Use g95 compiler";
335 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
336 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
337 $explanations{"ifc"} = "Use Intel's ifc compiler";
338 $explanations{"ammasso"} = "Use native RDMA support on Ammasso interconnect";
339 $explanations{"syncft"} = "Use initial fault tolerance support";
340 $explanations{"mlogft"} = "Use message logging fault tolerance support";
341 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
347 # Produce list of options
349 $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
350 # prune away beginning of line
351 $opts =~ m/Supported options: (.*)/;
352 $opts = $1;
354 @option_list = split(" ", $opts);
357 # Prune out entries that would already have been chosen above, such as smp
358 @option_list_pruned = ();
359 foreach $o (@option_list){
360 if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
361 @option_list_pruned = (@option_list_pruned , $o);
365 # sort the list
366 @option_list_pruned = sort @option_list_pruned;
367 if (@option_list_pruned > 0) {
369 print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
370 $special_options = promptUserYN();
372 if($special_options eq "yes"){
374 # print out list for user to select from
375 print "Please enter one or more numbers separated by spaces\n";
376 print "Choices:\n";
377 $i = 1;
378 foreach $o (@option_list_pruned){
379 $exp = $explanations{$o};
380 print "\t$i)\t$o";
381 # pad whitespace before options
382 for($j=0;$j<20-length($o);$j++){
383 print " ";
385 print ": $exp";
386 print "\n";
387 $i++;
389 print "\t$i)\tNone Of The Above\n";
391 $num_options = @option_list_pruned;
393 while($line = <>){
394 chomp $line;
395 $line =~ m/([0-9 ]*)/;
396 @entries = split(" ",$1);
397 @entries = sort(@entries);
399 $additional_options = "";
400 foreach $e (@entries) {
401 if($e>=1 && $e<= $num_options){
402 $estring = $option_list_pruned[$e-1];
403 $additional_options = "$additional_options $estring";
404 } elsif ($e == $num_options+1){
405 # user chose "None of the above"
406 # clear the options we may have seen before
407 $additional_options = " ";
411 # if the user input something reasonable, we can break out of this loop
412 if($additional_options ne ""){
413 $options = "$options ${additional_options} ";
414 last;
429 # Choose compiler flags
430 print << "EOF";
432 Choose a set of compiler flags [1-5]
433 1) none
434 2) debug mode -g -O0
435 3) production build [default] --with-production
436 4) production build w/ projections --with-production --enable-tracing
437 5) custom
441 $compiler_flags = "";
443 while($line = <>){
444 chomp $line;
445 if($line eq "1"){
446 last;
447 } elsif($line eq "2"){
448 $compiler_flags = "-g -O0";
449 last;
450 } elsif($line eq "4" ){
451 $compiler_flags = "--with-production --enable-tracing";
452 last;
453 } elsif($line eq "3" || $line eq ""){
454 $compiler_flags = "--with-production";
455 last;
456 } elsif($line eq "5"){
458 print "Enter compiler options: ";
459 $input_line = <>;
460 chomp($input_line);
461 $compiler_flags = $input_line;
463 last;
464 } else {
465 print "Invalid option, please try again :P\n"
472 # Determine the target to build.
473 # We want this simple so we just give 2 options
474 $target = "";
476 print << "EOF";
478 What do you want to build?
479 1) Charm++ [default] (choose this if you are building NAMD)
480 2) Charm++, AMPI, ParFUM, FEM and other libraries
484 while($line = <>){
485 chomp $line;
486 if($line eq "1" || $line eq ""){
487 $target = "charm++";
488 last;
489 } elsif($line eq "2"){
490 $target = "LIBS";
491 last;
492 } else {
493 print "Invalid option, please try again :P\n"
498 # Determine whether to use a -j flag for faster building
499 $j = "";
500 print << "EOF";
502 Do you want to compile in parallel?
503 1) No
504 2) Build with -j2
505 3) Build with -j4
506 4) Build with -j8
507 5) Build with -j16 [default]
508 6) Build with -j32
509 7) Build with -j
513 while($line = <>) {
514 chomp $line;
515 if($line eq "1"){
516 $j = "";
517 last;
518 } elsif($line eq "2") {
519 $j = "-j2";
520 last;
521 } elsif($line eq "3") {
522 $j = "-j4";
523 last;
524 } elsif($line eq "4") {
525 $j = "-j8";
526 last;
527 } elsif($line eq "5" || $line eq "") {
528 $j = "-j16";
529 last;
530 } elsif($line eq "6") {
531 $j = "-j32";
532 last;
533 } elsif($line eq "7") {
534 $j = "-j";
535 last;
536 } else {
537 print "Invalid option, please try again :P\n";
542 # Compose the build line
543 $build_line = "./build $target $arch $compilers $options $smp $j $nobs ${compiler_flags}\n";
546 # Save the build line in the log
547 open(BUILDLINE, ">>smart-build.log");
548 print BUILDLINE `date`;
549 print BUILDLINE "Using the following build command:\n";
550 print BUILDLINE "$build_line\n";
551 close(BUILDLINE);
554 print "We have determined a suitable build line is:\n";
555 print "\t$build_line\n\n";
558 # Execute the build line if the appropriate architecture directory exists
559 print "Do you want to start the build now? [Y/n]";
560 $p = promptUserYN();
561 if($p eq "yes" || $p eq "default"){
562 if(-e "src/arch/$arch"){
563 print "Building with: ${build_line}\n";
564 # Execute the build line
565 system($build_line);
566 } else {
567 print "We could not figure out how to build charm with those options on this platform, please manually build\n";
568 print "Try something similar to: ${build_line}\n";