Rename internal libmetis to libckmetis, to ensure we get our copy and not a system...
[charm.git] / smart-build.pl
blobd9259759f1001cdf2a8fe4adf304df4077fa8f0e
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";
66 my $x86;
67 my $amd64;
68 my $ppc;
69 my $arm7;
70 # Determine architecture (x86, ppc, ...)
71 if($cpu =~ m/i[0-9]86/){
72 $x86 = 1;
73 } elsif($cpu =~ m/x86\_64/){
74 $amd64 = 1;
75 } elsif($cpu =~ m/powerpc/){
76 $ppc = 1;
77 } elsif($cpu =~ m/ppc*/){
78 $ppc = 1;
79 } elsif($cpu =~ m/arm7/){
80 $arm7 = 1;
84 # default to netlrts
85 my $converse_network_type = "netlrts";
86 my $skip_choosing = "false";
88 print "Are you building to run just on the local machine, and not across multiple nodes? [";
89 if($arch_os eq "darwin") {
90 print "Y/n]\n";
91 } else {
92 print "y/N]\n";
95 my $p = promptUserYN();
96 if($p eq "yes" || ($arch_os eq "darwin" && $p eq "default")){
97 $converse_network_type = "multicore";
98 $skip_choosing = "true";
102 # check for MPI
104 my $mpi_found = "false";
105 my $m = system("which mpicc mpiCC > /dev/null 2>/dev/null") / 256;
106 my $mpioption;
107 if($m == 0){
108 $mpi_found = "true";
109 $mpioption = "";
111 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
112 if($m == 0){
113 $mpi_found = "true";
114 $mpioption = "mpicxx";
117 # Give option of just using the mpi version if mpicc and mpiCC are found
118 if($skip_choosing eq "false" && $mpi_found eq "true"){
119 print "\nI found that you have an mpicc available in your path.\nDo you want to build Charm++ on this MPI? [y/N]: ";
120 my $p = promptUserYN();
121 if($p eq "yes"){
122 $converse_network_type = "mpi";
123 $skip_choosing = "true";
124 $options = "$options $mpioption";
128 if($skip_choosing eq "false") {
130 print "\nDo you have a special network interconnect? [y/N]: ";
131 my $p = promptUserYN();
132 if($p eq "yes"){
133 print << "EOF";
135 Choose an interconnect from below: [1-10]
136 1) MPI
137 2) Infiniband (ibverbs)
138 3) Cray XE, XK
139 4) Cray XC
140 5) Blue Gene/Q
144 while(my $line = <>){
145 chomp $line;
146 if($line eq "1"){
147 $converse_network_type = "mpi";
148 last;
149 } elsif($line eq "2"){
150 $converse_network_type = "verbs";
151 last;
152 } elsif($line eq "3"){
153 $arch = "gni-crayxe";
154 last;
155 } elsif($line eq "4"){
156 $arch = "gni-crayxc";
157 last;
158 } elsif($line eq "5"){
159 $arch = "pamilrts-bluegeneq";
160 last;
161 } else {
162 print "Invalid option, please try again :P\n"
169 # construct an $arch string if we did not explicitly set one above
170 if($arch eq ""){
171 $arch = "${converse_network_type}-${arch_os}";
172 if($amd64) {
173 $arch = $arch . "-x86_64";
174 } elsif($ppc){
175 $arch = $arch . "-ppc";
176 } elsif($arm7){
177 $arch = $arch . "-arm7";
181 # Fixup $arch to match the inconsistent directories in src/archs
183 if($arch eq "netlrts-darwin"){
184 $arch = "netlrts-darwin-x86_64";
185 } elsif($arch eq "multicore-linux-arm7"){
186 $arch = "multicore-arm7";
190 #================ Choose SMP/PXSHM =================================
192 # find what options are available
193 my $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
194 $opts =~ m/Supported options: (.*)/;
195 $opts = $1;
197 my $smp_opts = <<EOF;
198 1) single-threaded [default]
201 # only add the smp or pxshm options if they are available
202 my $counter = 1; # the last index used in the list
204 my $smpIndex = -1;
205 if($opts =~ m/smp/){
206 $counter ++;
207 $smp_opts = $smp_opts . " $counter) SMP\n";
208 $smpIndex = $counter;
211 my $pxshmIndex = -1;
212 if($opts =~ m/pxshm/){
213 $counter ++;
214 $smp_opts = $smp_opts . " $counter) POSIX Shared Memory\n";
215 $pxshmIndex = $counter;
218 if ($counter != 1) {
219 print "How do you want to handle SMP/Multicore: [1-$counter]\n";
220 print $smp_opts;
222 while(my $line = <>){
223 chomp $line;
224 if($line eq "" || $line eq "1"){
225 last;
226 } elsif($line eq $smpIndex){
227 $options = "$options smp ";
228 last;
229 } elsif($line eq $pxshmIndex){
230 $options = "$options pxshm ";
231 last;
237 #================ Choose Compiler =================================
239 # Lookup list of compilers
240 my $cs = `./build charm++ $arch help 2>&1 | grep "Supported compilers"`;
241 # prune away beginning of the line
242 $cs =~ m/Supported compilers: (.*)/;
243 $cs = $1;
244 # split the line into an array
245 my @c_list = split(" ", $cs);
247 # print list of compilers
248 my $numc = @c_list;
250 if ($numc > 0) {
251 print "\nDo you want to specify a compiler? [y/N]";
252 my $p = promptUserYN();
253 if($p eq "yes" ){
254 print "Choose a compiler: [1-$numc] \n";
256 my $i = 1;
257 foreach my $c (@c_list){
258 print "\t$i)\t$c\n";
259 $i++;
262 # Choose compiler
263 while(my $line = <>){
264 chomp $line;
265 if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
266 $compilers = $c_list[$1-1];
267 last;
268 } else {
269 print "Invalid option, please try again :P\n"
278 #================ Choose Options =================================
280 #Create a hash table containing descriptions of various options
281 my %explanations = ();
282 $explanations{"ooc"} = "Out-of-core execution support in Charm++";
283 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
284 $explanations{"gfortran"} = "Use gfortran compiler for fortran";
285 $explanations{"ifort"} = "Use Intel's ifort fortran compiler";
286 $explanations{"pgf90"} = "Use Portland Group's pgf90 fortran compiler";
287 $explanations{"syncft"} = "Use fault tolerance support";
288 $explanations{"mlogft"} = "Use message logging fault tolerance support";
289 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
295 # Produce list of options
297 $opts = `./build charm++ $arch help 2>&1 | grep "Supported options"`;
298 # prune away beginning of line
299 $opts =~ m/Supported options: (.*)/;
300 $opts = $1;
302 my @option_list = split(" ", $opts);
305 # Prune out entries that would already have been chosen above, such as smp
306 my @option_list_pruned = ();
307 foreach my $o (@option_list){
308 if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
309 @option_list_pruned = (@option_list_pruned , $o);
313 # sort the list
314 @option_list_pruned = sort @option_list_pruned;
315 if (@option_list_pruned > 0) {
317 print "\nDo you want to specify any Charm++ build options, such as fortran compilers? [y/N]";
318 my $special_options = promptUserYN();
320 if($special_options eq "yes"){
322 # print out list for user to select from
323 print "Please enter one or more numbers separated by spaces\n";
324 print "Choices:\n";
325 my $i = 1;
326 foreach my $o (@option_list_pruned){
327 my $exp = $explanations{$o};
328 print "\t$i)\t$o";
329 # pad whitespace before options
330 for(my $j=0;$j<20-length($o);$j++){
331 print " ";
333 print ": $exp";
334 print "\n";
335 $i++;
337 print "\t$i)\tNone Of The Above\n";
339 my $num_options = @option_list_pruned;
341 while(my $line = <>){
342 chomp $line;
343 $line =~ m/([0-9 ]*)/;
344 my @entries = split(" ",$1);
345 @entries = sort(@entries);
347 my $additional_options = "";
348 foreach my $e (@entries) {
349 if($e>=1 && $e<= $num_options){
350 my $estring = $option_list_pruned[$e-1];
351 $additional_options = "$additional_options $estring";
352 } elsif ($e == $num_options+1){
353 # user chose "None of the above"
354 # clear the options we may have seen before
355 $additional_options = " ";
359 # if the user input something reasonable, we can break out of this loop
360 if($additional_options ne ""){
361 $options = "$options ${additional_options} ";
362 last;
370 # Choose compiler flags
371 print << "EOF";
373 Choose a set of compiler flags [1-5]
374 1) none
375 2) debug mode -g -O0
376 3) production build [default] --with-production
377 4) production build w/ projections --with-production --enable-tracing
378 5) custom
382 my $compiler_flags = "";
384 while(my $line = <>){
385 chomp $line;
386 if($line eq "1"){
387 last;
388 } elsif($line eq "2"){
389 $compiler_flags = "-g -O0";
390 last;
391 } elsif($line eq "4" ){
392 $compiler_flags = "--with-production --enable-tracing";
393 last;
394 } elsif($line eq "3" || $line eq ""){
395 $compiler_flags = "--with-production";
396 last;
397 } elsif($line eq "5"){
399 print "Enter compiler options: ";
400 my $input_line = <>;
401 chomp($input_line);
402 $compiler_flags = $input_line;
404 last;
405 } else {
406 print "Invalid option, please try again :P\n"
413 # Determine the target to build.
414 # We want this simple so we just give 2 options
415 my $target = "";
417 print << "EOF";
419 What do you want to build?
420 1) Charm++ [default] (choose this if you are building NAMD)
421 2) Charm++ and AMPI
422 3) Charm++, AMPI, ParFUM, FEM and other libraries
426 while(my $line = <>){
427 chomp $line;
428 if($line eq "1" || $line eq ""){
429 $target = "charm++";
430 last;
431 } elsif($line eq "2"){
432 $target = "AMPI";
433 last;
434 } elsif($line eq "3"){
435 $target = "LIBS";
436 last;
437 } else {
438 print "Invalid option, please try again :P\n"
443 # Determine whether to use a -j flag for faster building
444 my $j = "";
445 print << "EOF";
447 Do you want to compile in parallel?
448 1) No
449 2) Build with -j2
450 3) Build with -j4
451 4) Build with -j8
452 5) Build with -j16 [default]
453 6) Build with -j32
454 7) Build with -j
458 while(my $line = <>) {
459 chomp $line;
460 if($line eq "1"){
461 $j = "";
462 last;
463 } elsif($line eq "2") {
464 $j = "-j2";
465 last;
466 } elsif($line eq "3") {
467 $j = "-j4";
468 last;
469 } elsif($line eq "4") {
470 $j = "-j8";
471 last;
472 } elsif($line eq "5" || $line eq "") {
473 $j = "-j16";
474 last;
475 } elsif($line eq "6") {
476 $j = "-j32";
477 last;
478 } elsif($line eq "7") {
479 $j = "-j";
480 last;
481 } else {
482 print "Invalid option, please try again :P\n";
487 # Compose the build line
488 my $build_line = "./build $target $arch $compilers $options $j $nobs ${compiler_flags}\n";
491 # Save the build line in the log
492 open(BUILDLINE, ">>smart-build.log");
493 print BUILDLINE `date`;
494 print BUILDLINE "Using the following build command:\n";
495 print BUILDLINE "$build_line\n";
496 close(BUILDLINE);
499 print "We have determined a suitable build line is:\n";
500 print "\t$build_line\n\n";
503 # Execute the build line if the appropriate architecture directory exists
504 print "Do you want to start the build now? [Y/n]";
505 my $p = promptUserYN();
506 if($p eq "yes" || $p eq "default"){
507 if(-e "src/arch/$arch"){
508 print "Building with: ${build_line}\n";
509 # Execute the build line
510 system($build_line);
511 } else {
512 print "We could not figure out how to build charm with those options on this platform, please manually build\n";
513 print "Try something similar to: ${build_line}\n";