4 # This is an interactive script that knows
5 # common ways to build Charm++ and AMPI.
7 # Authors: dooley, becker
12 # Get location of script
14 my $dirname = dirname
(__FILE__
);
16 # Create temporary file for compiler tests
17 use File
::Temp
qw(tempfile);
18 my $tempfile = new File
::Temp
(UNLINK
=> 1, SUFFIX
=> '.c');
21 # Turn off I/O buffering
26 # A subroutine that reads from input and returns a yes/no/default
30 if(lc($line) eq "y" || lc($line) eq "yes" ){
32 } elsif(lc($line) eq "n" || lc($line) eq "no" ){
34 } elsif( $line eq "" ){
41 # The beginning of the good stuff:
42 print "\n============================================================\n";
43 print "\nInteractive Charm++/AMPI configuration ...\n";
44 print "If you are a power user expecting a list of options, please use ./build --help\n";
45 print "\n============================================================\n\n\n";
48 # Use uname to get the cpu type and OS information
52 #Variables to hold the portions of the configuration:
58 #remove newlines from these strings:
66 } elsif ($os eq "Darwin") {
68 } elsif ($os =~ m/BSD/ ) {
70 } elsif ($os =~ m/OSF1/ ) {
79 # Determine architecture (x86, ppc, ...)
80 if($cpu =~ m/i[0-9]86/){
82 } elsif($cpu =~ m/x86\_64/){
84 } elsif($cpu =~ m/powerpc/){
86 } elsif($cpu =~ m/ppc*/){
88 } elsif($cpu =~ m/arm7/){
94 my $converse_network_type = "netlrts";
95 my $skip_choosing = "false";
97 print "Are you building to run just on the local machine, and not across multiple nodes? [";
98 if($arch_os eq "darwin") {
104 my $p = promptUserYN
();
105 if($p eq "yes" || ($arch_os eq "darwin" && $p eq "default")){
106 $converse_network_type = "multicore";
107 $skip_choosing = "true";
114 if($skip_choosing eq "false"){
115 my $BGQ_FLOOR = $ENV{'BGQ_FLOOR'};
116 if (not defined $BGQ_FLOOR) {
117 $BGQ_FLOOR = "/bgsys/drivers/ppcfloor";
120 my $bgq_found = system("which \"$BGQ_FLOOR/gnu-linux/bin/powerpc64-bgq-linux-cpp\" 2>/dev/null") / 256;
122 if ($bgq_found == 0) {
123 print "\nI found that you have a Blue Gene/Q toolchain available in your path.\nDo you want to build Charm++ targeting BG/Q? [Y/n]: ";
124 my $p = promptUserYN
();
125 if($p eq "yes" || $p eq "default") {
126 $arch = "pamilrts-bluegeneq";
127 $skip_choosing = "true";
135 if($skip_choosing eq "false"){
136 my $craycc_found = index(`which CC 2>/dev/null`, "/opt/cray/") != -1;
138 my $PE_PRODUCT_LIST = $ENV{'PE_PRODUCT_LIST'};
139 if (not defined $PE_PRODUCT_LIST) {
140 $PE_PRODUCT_LIST = "";
143 my $CRAY_UGNI_found = index(":$PE_PRODUCT_LIST:", ":CRAY_UGNI:") != -1;
145 my $gni_found = $craycc_found || $CRAY_UGNI_found;
148 my $CRAYPE_INTERLAGOS_found = index(":$PE_PRODUCT_LIST:", ":CRAYPE_INTERLAGOS:") != -1;
149 if ($CRAYPE_INTERLAGOS_found) {
150 print "\nI found that you have a Cray environment with Interlagos processors.\nDo you want to build Charm++ targeting Cray XE? [Y/n]: ";
151 my $p = promptUserYN
();
152 if($p eq "yes" || $p eq "default") {
153 $arch = "gni-crayxe";
154 $skip_choosing = "true";
157 print "\nI found that you have a Cray environment.\nDo you want to build Charm++ targeting Cray XC? [Y/n]: ";
158 my $p = promptUserYN
();
159 if($p eq "yes" || $p eq "default") {
160 $arch = "gni-crayxc";
161 $skip_choosing = "true";
170 if($skip_choosing eq "false"){
171 my $ofi_found = index(`cc $tempfile -Wl,-lfabric 2>&1`, "-lfabric") == -1;
174 print "\nI found that you have libfabric available in your toolchain.\nDo you want to build Charm++ targeting OFI? [Y/n]: ";
175 my $p = promptUserYN
();
176 if($p eq "yes" || $p eq "default") {
177 $converse_network_type = "ofi";
178 $skip_choosing = "true";
186 if($skip_choosing eq "false"){
187 my $MPI_ROOT = $ENV{'MPI_ROOT'};
188 if (not defined $MPI_ROOT) {
192 my $pami_found = index(`cc $tempfile -Wl,-L,"$MPI_ROOT/lib/pami_port" -Wl,-L,/usr/lib/powerpc64le-linux-gnu -Wl,-lpami 2>&1`, "-lpami") == -1;
195 print "\nI found that you have libpami available in your toolchain.\nDo you want to build Charm++ targeting PAMI? [Y/n]: ";
196 my $p = promptUserYN
();
197 if($p eq "yes" || $p eq "default") {
198 $converse_network_type = "pamilrts";
199 $skip_choosing = "true";
207 if($skip_choosing eq "false"){
208 my $verbs_found = index(`cc $tempfile -Wl,-libverbs 2>&1`, "-libverbs") == -1;
211 print "\nI found that you have libibverbs available in your toolchain.\nDo you want to build Charm++ targeting Infiniband Verbs? [Y/n]: ";
212 my $p = promptUserYN
();
213 if($p eq "yes" || $p eq "default") {
214 $converse_network_type = "verbs";
215 $skip_choosing = "true";
223 if($skip_choosing eq "false"){
224 my $mpi_found = "false";
225 my $m = system("which mpicc mpiCC > /dev/null 2>/dev/null") / 256;
231 $m = system("which mpicc mpicxx > /dev/null 2>/dev/null") / 256;
234 $mpioption = "mpicxx";
237 # Give option of just using the mpi version if mpicc and mpiCC are found
238 if($mpi_found eq "true"){
239 print "\nI found that you have an mpicc available in your path.\nDo you want to build Charm++ on this MPI? [y/N]: ";
240 my $p = promptUserYN
();
242 $converse_network_type = "mpi";
243 $skip_choosing = "true";
244 $options = "$options $mpioption";
250 if($skip_choosing eq "false") {
252 print "\nDo you have a special network interconnect? [y/N]: ";
253 my $p = promptUserYN
();
258 Choose an interconnect from below
: [1-10]
260 2) Infiniband
(verbs
)
264 6) Intel Omni
-Path
(ofi
)
269 while(my $line = <>){
272 $converse_network_type = "mpi";
274 } elsif($line eq "2"){
275 $converse_network_type = "verbs";
277 } elsif($line eq "3"){
278 $arch = "gni-crayxe";
280 } elsif($line eq "4"){
281 $arch = "gni-crayxc";
283 } elsif($line eq "5"){
284 $arch = "pamilrts-bluegeneq";
286 } elsif($line eq "6"){
287 $converse_network_type = "ofi";
289 } elsif($line eq "7"){
290 $converse_network_type = "pamilrts";
293 print "Invalid option, please try again :P\n"
302 my $nvcc_found = "false";
303 my $n = system("which nvcc > /dev/null 2>/dev/null") / 256;
305 $nvcc_found = "true";
308 if($nvcc_found eq "true"){
309 print "\nI found that you have NVCC available in your path.\nDo you want to build Charm++ with GPU Manager support for CUDA? [y/N]: ";
310 my $p = promptUserYN
();
312 $options = "$options cuda";
317 # construct an $arch string if we did not explicitly set one above
319 $arch = "${converse_network_type}-${arch_os}";
321 $arch = $arch . "-x86_64";
323 $arch = $arch . "-ppc64le";
325 $arch = $arch . "-arm7";
329 # Fixup $arch to match the inconsistent directories in src/archs
331 if($arch eq "netlrts-darwin"){
332 $arch = "netlrts-darwin-x86_64";
333 } elsif($arch eq "multicore-linux-arm7"){
334 $arch = "multicore-arm7";
338 #================ Choose SMP/PXSHM =================================
340 # find what options are available
341 my $opts = `$dirname/build charm++ $arch help 2>&1 | grep "Supported options"`;
342 $opts =~ m/Supported options: (.*)/;
345 my $smp_opts = <<EOF;
346 1) single-threaded [default]
349 # only add the smp or pxshm options if they are available
350 my $counter = 1; # the last index used in the list
355 $smp_opts = $smp_opts . " $counter) SMP\n";
356 $smpIndex = $counter;
360 if($opts =~ m/pxshm/){
362 $smp_opts = $smp_opts . " $counter) POSIX Shared Memory\n";
363 $pxshmIndex = $counter;
367 print "\nHow do you want to handle SMP/Multicore: [1-$counter]\n";
370 while(my $line = <>){
372 if($line eq "" || $line eq "1"){
374 } elsif($line eq $smpIndex){
375 $options = "$options smp ";
377 } elsif($line eq $pxshmIndex){
378 $options = "$options pxshm ";
385 #================ Choose Compiler =================================
387 # Lookup list of compilers
388 my $cs = `$dirname/build charm++ $arch help 2>&1 | grep "Supported compilers"`;
389 # prune away beginning of the line
390 $cs =~ m/Supported compilers: (.*)/;
392 # split the line into an array
393 my @c_list = split(" ", $cs);
395 # print list of compilers
399 print "\nDo you want to specify a compiler? [y/N]: ";
400 my $p = promptUserYN
();
402 print "Choose a compiler: [1-$numc] \n";
405 foreach my $c (@c_list){
411 while(my $line = <>){
413 if($line =~ m/([0-9]*)/ && $1 > 0 && $1 <= $numc){
414 $compilers = $c_list[$1-1];
417 print "Invalid option, please try again :P\n"
426 #================ Choose Options =================================
428 #Create a hash table containing descriptions of various options
429 my %explanations = ();
430 $explanations{"ooc"} = "Enable Out-of-core execution support in Charm++";
431 $explanations{"tcp"} = "Charm++ over TCP instead of UDP for net versions. TCP is slower";
432 $explanations{"gfortran"} = "Use the gfortran compiler for Fortran";
433 $explanations{"flang"} = "Use the flang compiler for Fortran";
434 $explanations{"ifort"} = "Use Intel's ifort Fortran compiler";
435 $explanations{"pgf90"} = "Use Portland Group's pgf90 Fortran compiler";
436 $explanations{"syncft"} = "Use fault tolerance support";
437 $explanations{"mlogft"} = "Use message logging fault tolerance support";
438 $explanations{"causalft"} = "Use causal message logging fault tolerance support";
439 $explanations{"omp"} = "Build Charm++ with integrated OpenMP support";
440 $explanations{"papi"} = "Enable PAPI performance counters";
441 $explanations{"pedantic"} = "Enable pedantic compiler warnings";
442 $explanations{"bigemulator"} = "Build additional BigSim libraries";
443 $explanations{"bigsim"} = "Compile Charm++ as running on the BigSim emulator";
444 $explanations{"nolb"} = "Build without load balancing support";
445 $explanations{"perftools"} = "Build with support for the Cray perftools";
446 $explanations{"persistent"} = "Build the persistent communication interface";
447 $explanations{"slurmpmi"} = "Use Slurm PMI for task launching";
448 $explanations{"slurmpmi2"} = "Use Slurm PMI2 for task launching";
449 $explanations{"tsan"} = "Compile Charm++ with support for Thread Sanitizer";
455 # Produce list of options
457 $opts = `$dirname/build charm++ $arch help 2>&1 | grep "Supported options"`;
458 # prune away beginning of line
459 $opts =~ m/Supported options: (.*)/;
462 my @option_list = split(" ", $opts);
465 # Prune out entries that would already have been chosen above, such as smp
466 my @option_list_pruned = ();
467 foreach my $o (@option_list){
468 if($o ne "smp" && $o ne "ibverbs" && $o ne "gm" && $o ne "mx"){
469 @option_list_pruned = (@option_list_pruned , $o);
474 @option_list_pruned = sort @option_list_pruned;
475 if (@option_list_pruned > 0) {
477 print "\nDo you want to specify any Charm++ build options, such as Fortran compilers? [y/N]: ";
478 my $special_options = promptUserYN
();
480 if($special_options eq "yes"){
482 # print out list for user to select from
483 print "Please enter one or more numbers separated by spaces\n";
486 foreach my $o (@option_list_pruned){
487 my $exp = $explanations{$o};
489 # pad whitespace before options
490 for(my $j=0;$j<20-length($o);$j++){
497 print "\t$i)\tNone Of The Above\n";
499 my $num_options = @option_list_pruned;
501 while(my $line = <>){
503 $line =~ m/([0-9 ]*)/;
504 my @entries = split(" ",$1);
505 @entries = sort(@entries);
507 my $additional_options = "";
508 foreach my $e (@entries) {
509 if($e>=1 && $e<= $num_options){
510 my $estring = $option_list_pruned[$e-1];
511 $additional_options = "$additional_options $estring";
512 } elsif ($e == $num_options+1){
513 # user chose "None of the above"
514 # clear the options we may have seen before
515 $additional_options = " ";
519 # if the user input something reasonable, we can break out of this loop
520 if($additional_options ne ""){
521 $options = "$options ${additional_options} ";
530 # Choose compiler flags
533 Choose a set of compiler flags
[1-5]
536 3) production build
[default] --with
-production
537 4) production build w
/ projections
--with
-production
--enable
-tracing
542 my $compiler_flags = "";
544 while(my $line = <>){
548 } elsif($line eq "2"){
549 $compiler_flags = "-g -O0";
551 } elsif($line eq "4" ){
552 $compiler_flags = "--with-production --enable-tracing";
554 } elsif($line eq "3" || $line eq ""){
555 $compiler_flags = "--with-production";
557 } elsif($line eq "5"){
559 print "Enter compiler options: ";
562 $compiler_flags = $input_line;
566 print "Invalid option, please try again :P\n"
573 # Determine the target to build.
574 # We want this simple so we just give 2 options
579 What
do you want to build?
580 1) Charm
++ [default] (choose this
if you are building NAMD
)
582 3) Charm
++, AMPI
, ParFUM
, FEM
and other libraries
586 while(my $line = <>){
588 if($line eq "1" || $line eq ""){
591 } elsif($line eq "2"){
594 } elsif($line eq "3"){
598 print "Invalid option, please try again :P\n"
603 # Determine whether to use a -j flag for faster building
607 Do you want to compile
in parallel?
612 5) Build with
-j16
[default]
618 while(my $line = <>) {
623 } elsif($line eq "2") {
626 } elsif($line eq "3") {
629 } elsif($line eq "4") {
632 } elsif($line eq "5" || $line eq "") {
635 } elsif($line eq "6") {
638 } elsif($line eq "7") {
642 print "Invalid option, please try again :P\n";
647 # Compose the build line
648 my $build_line = "$dirname/build $target $arch $compilers $options $j $nobs ${compiler_flags}\n";
651 # Save the build line in the log
652 open(BUILDLINE
, ">>smart-build.log");
653 print BUILDLINE
`date`;
654 print BUILDLINE
"Using the following build command:\n";
655 print BUILDLINE
"$build_line\n";
659 print "We have determined a suitable build line is:\n";
660 print "\t$build_line\n\n";
663 # Execute the build line if the appropriate architecture directory exists
664 print "Do you want to start the build now? [Y/n]: ";
665 my $p = promptUserYN
();
666 if($p eq "yes" || $p eq "default"){
667 if(-e
"$dirname/src/arch/$arch"){
668 print "Building with: ${build_line}\n";
669 # Execute the build line
672 print "We could not figure out how to build charm with those options on this platform, please manually build\n";
673 print "Try something similar to: ${build_line}\n";