AMPI: MPI_Win_free should set the window to MPI_WIN_NULL
[charm.git] / smart-build.pl
blob08a410e9c1977ee07d0bca4f4883e8523e24cf67
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/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";
71 my $x86;
72 my $amd64;
73 my $ppc;
74 my $arm7;
75 # Determine architecture (x86, ppc, ...)
76 if($cpu =~ m/i[0-9]86/){
77 $x86 = 1;
78 } elsif($cpu =~ m/x86\_64/){
79 $amd64 = 1;
80 } elsif($cpu =~ m/powerpc/){
81 $ppc = 1;
82 } elsif($cpu =~ m/ppc*/){
83 $ppc = 1;
84 } elsif($cpu =~ m/arm7/){
85 $arm7 = 1;
89 # default to netlrts
90 my $converse_network_type = "netlrts";
91 my $skip_choosing = "false";
93 print "Are you building to run just on the local machine, and not across multiple nodes? [";
94 if($arch_os eq "darwin") {
95 print "Y/n]\n";
96 } else {
97 print "y/N]\n";
100 my $p = promptUserYN();
101 if($p eq "yes" || ($arch_os eq "darwin" && $p eq "default")){
102 $converse_network_type = "multicore";
103 $skip_choosing = "true";
107 # check for MPI
109 my $mpi_found = "false";
110 my $m = system("which mpicc mpiCC > /dev/null 2>/dev/null") / 256;
111 my $mpioption;
112 if($m == 0){
113 $mpi_found = "true";
114 $mpioption = "";
116 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
117 if($m == 0){
118 $mpi_found = "true";
119 $mpioption = "mpicxx";
122 # Give option of just using the mpi version if mpicc and mpiCC are found
123 if($skip_choosing eq "false" && $mpi_found eq "true"){
124 print "\nI found that you have an mpicc available in your path.\nDo you want to build Charm++ on this MPI? [y/N]: ";
125 my $p = promptUserYN();
126 if($p eq "yes"){
127 $converse_network_type = "mpi";
128 $skip_choosing = "true";
129 $options = "$options $mpioption";
133 if($skip_choosing eq "false") {
135 print "\nDo you have a special network interconnect? [y/N]: ";
136 my $p = promptUserYN();
137 if($p eq "yes"){
138 print << "EOF";
140 Choose an interconnect from below: [1-10]
141 1) MPI
142 2) Infiniband (ibverbs)
143 3) Cray XE, XK
144 4) Cray XC
145 5) Blue Gene/Q
149 while(my $line = <>){
150 chomp $line;
151 if($line eq "1"){
152 $converse_network_type = "mpi";
153 last;
154 } elsif($line eq "2"){
155 $converse_network_type = "verbs";
156 last;
157 } elsif($line eq "3"){
158 $arch = "gni-crayxe";
159 last;
160 } elsif($line eq "4"){
161 $arch = "gni-crayxc";
162 last;
163 } elsif($line eq "5"){
164 $arch = "pamilrts-bluegeneq";
165 last;
166 } else {
167 print "Invalid option, please try again :P\n"
174 # construct an $arch string if we did not explicitly set one above
175 if($arch eq ""){
176 $arch = "${converse_network_type}-${arch_os}";
177 if($amd64) {
178 $arch = $arch . "-x86_64";
179 } elsif($ppc){
180 $arch = $arch . "-ppc";
181 } elsif($arm7){
182 $arch = $arch . "-arm7";
186 # Fixup $arch to match the inconsistent directories in src/archs
188 if($arch eq "netlrts-darwin"){
189 $arch = "netlrts-darwin-x86_64";
190 } elsif($arch eq "multicore-linux-arm7"){
191 $arch = "multicore-arm7";
192 } elsif($arch eq "multicore-linux-x86_64"){
193 $arch = "multicore-linux64";
197 #================ Choose SMP/PXSHM =================================
199 # find what options are available
200 my $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
201 $opts =~ m/Supported options: (.*)/;
202 $opts = $1;
204 my $smp_opts = <<EOF;
205 1) single-threaded [default]
208 # only add the smp or pxshm options if they are available
209 my $counter = 1; # the last index used in the list
211 my $smpIndex = -1;
212 if($opts =~ m/smp/){
213 $counter ++;
214 $smp_opts = $smp_opts . " $counter) SMP\n";
215 $smpIndex = $counter;
218 my $pxshmIndex = -1;
219 if($opts =~ m/pxshm/){
220 $counter ++;
221 $smp_opts = $smp_opts . " $counter) POSIX Shared Memory\n";
222 $pxshmIndex = $counter;
225 if ($counter != 1) {
226 print "How do you want to handle SMP/Multicore: [1-$counter]\n";
227 print $smp_opts;
229 while(my $line = <>){
230 chomp $line;
231 if($line eq "" || $line eq "1"){
232 last;
233 } elsif($line eq $smpIndex){
234 $options = "$options smp ";
235 last;
236 } elsif($line eq $pxshmIndex){
237 $options = "$options pxshm ";
238 last;
244 #================ Choose Compiler =================================
246 # Lookup list of compilers
247 my $cs = `./build charm++ $arch help 2>&1 | grep "Supported compilers"`;
248 # prune away beginning of the line
249 $cs =~ m/Supported compilers: (.*)/;
250 $cs = $1;
251 # split the line into an array
252 my @c_list = split(" ", $cs);
254 # print list of compilers
255 my $numc = @c_list;
257 if ($numc > 0) {
258 print "\nDo you want to specify a compiler? [y/N]";
259 my $p = promptUserYN();
260 if($p eq "yes" ){
261 print "Choose a compiler: [1-$numc] \n";
263 my $i = 1;
264 foreach my $c (@c_list){
265 print "\t$i)\t$c\n";
266 $i++;
269 # Choose compiler
270 while(my $line = <>){
271 chomp $line;
272 if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
273 $compilers = $c_list[$1-1];
274 last;
275 } else {
276 print "Invalid option, please try again :P\n"
285 #================ Choose Options =================================
287 #Create a hash table containing descriptions of various options
288 my %explanations = ();
289 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
290 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
291 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
292 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
293 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
294 $explanations{"syncft"} = "Use fault tolerance support";
295 $explanations{"mlogft"} = "Use message logging fault tolerance support";
296 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
302 # Produce list of options
304 $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
305 # prune away beginning of line
306 $opts =~ m/Supported options: (.*)/;
307 $opts = $1;
309 my @option_list = split(" ", $opts);
312 # Prune out entries that would already have been chosen above, such as smp
313 my @option_list_pruned = ();
314 foreach my $o (@option_list){
315 if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
316 @option_list_pruned = (@option_list_pruned , $o);
320 # sort the list
321 @option_list_pruned = sort @option_list_pruned;
322 if (@option_list_pruned > 0) {
324 print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
325 my $special_options = promptUserYN();
327 if($special_options eq "yes"){
329 # print out list for user to select from
330 print "Please enter one or more numbers separated by spaces\n";
331 print "Choices:\n";
332 my $i = 1;
333 foreach my $o (@option_list_pruned){
334 my $exp = $explanations{$o};
335 print "\t$i)\t$o";
336 # pad whitespace before options
337 for(my $j=0;$j<20-length($o);$j++){
338 print " ";
340 print ": $exp";
341 print "\n";
342 $i++;
344 print "\t$i)\tNone Of The Above\n";
346 my $num_options = @option_list_pruned;
348 while(my $line = <>){
349 chomp $line;
350 $line =~ m/([0-9 ]*)/;
351 my @entries = split(" ",$1);
352 @entries = sort(@entries);
354 my $additional_options = "";
355 foreach my $e (@entries) {
356 if($e>=1 && $e<= $num_options){
357 my $estring = $option_list_pruned[$e-1];
358 $additional_options = "$additional_options $estring";
359 } elsif ($e == $num_options+1){
360 # user chose "None of the above"
361 # clear the options we may have seen before
362 $additional_options = " ";
366 # if the user input something reasonable, we can break out of this loop
367 if($additional_options ne ""){
368 $options = "$options ${additional_options} ";
369 last;
377 # Choose compiler flags
378 print << "EOF";
380 Choose a set of compiler flags [1-5]
381 1) none
382 2) debug mode -g -O0
383 3) production build [default] --with-production
384 4) production build w/ projections --with-production --enable-tracing
385 5) custom
389 my $compiler_flags = "";
391 while(my $line = <>){
392 chomp $line;
393 if($line eq "1"){
394 last;
395 } elsif($line eq "2"){
396 $compiler_flags = "-g -O0";
397 last;
398 } elsif($line eq "4" ){
399 $compiler_flags = "--with-production --enable-tracing";
400 last;
401 } elsif($line eq "3" || $line eq ""){
402 $compiler_flags = "--with-production";
403 last;
404 } elsif($line eq "5"){
406 print "Enter compiler options: ";
407 my $input_line = <>;
408 chomp($input_line);
409 $compiler_flags = $input_line;
411 last;
412 } else {
413 print "Invalid option, please try again :P\n"
420 # Determine the target to build.
421 # We want this simple so we just give 2 options
422 my $target = "";
424 print << "EOF";
426 What do you want to build?
427 1) Charm++ [default] (choose this if you are building NAMD)
428 2) Charm++ and AMPI
429 3) Charm++, AMPI, ParFUM, FEM and other libraries
433 while(my $line = <>){
434 chomp $line;
435 if($line eq "1" || $line eq ""){
436 $target = "charm++";
437 last;
438 } elsif($line eq "2"){
439 $target = "AMPI";
440 last;
441 } elsif($line eq "3"){
442 $target = "LIBS";
443 last;
444 } else {
445 print "Invalid option, please try again :P\n"
450 # Determine whether to use a -j flag for faster building
451 my $j = "";
452 print << "EOF";
454 Do you want to compile in parallel?
455 1) No
456 2) Build with -j2
457 3) Build with -j4
458 4) Build with -j8
459 5) Build with -j16 [default]
460 6) Build with -j32
461 7) Build with -j
465 while(my $line = <>) {
466 chomp $line;
467 if($line eq "1"){
468 $j = "";
469 last;
470 } elsif($line eq "2") {
471 $j = "-j2";
472 last;
473 } elsif($line eq "3") {
474 $j = "-j4";
475 last;
476 } elsif($line eq "4") {
477 $j = "-j8";
478 last;
479 } elsif($line eq "5" || $line eq "") {
480 $j = "-j16";
481 last;
482 } elsif($line eq "6") {
483 $j = "-j32";
484 last;
485 } elsif($line eq "7") {
486 $j = "-j";
487 last;
488 } else {
489 print "Invalid option, please try again :P\n";
494 # Compose the build line
495 my $build_line = "./build $target $arch $compilers $options $j $nobs ${compiler_flags}\n";
498 # Save the build line in the log
499 open(BUILDLINE, ">>smart-build.log");
500 print BUILDLINE `date`;
501 print BUILDLINE "Using the following build command:\n";
502 print BUILDLINE "$build_line\n";
503 close(BUILDLINE);
506 print "We have determined a suitable build line is:\n";
507 print "\t$build_line\n\n";
510 # Execute the build line if the appropriate architecture directory exists
511 print "Do you want to start the build now? [Y/n]";
512 my $p = promptUserYN();
513 if($p eq "yes" || $p eq "default"){
514 if(-e "src/arch/$arch"){
515 print "Building with: ${build_line}\n";
516 # Execute the build line
517 system($build_line);
518 } else {
519 print "We could not figure out how to build charm with those options on this platform, please manually build\n";
520 print "Try something similar to: ${build_line}\n";